This is a webapp running on Tomcat, using Guice. According to the docs we should be able to call ResourceBundle.clearCache();
to clear the ResourceBundle cache and presumably get the latest from the bundle property files.
We have also tried the following:
Class klass = ResourceBundle.getBundle("my.bundle").getClass().getSuperclass();
Field field = klass.getDeclaredField("cacheList");
field.setAccessible(true);
ConcurrentHashMap cache = (ConcurrentHashMap) field.get(null);
cache.clear(); // If i debug here I can see the cache is now empty!
and
ResourceBundle.clearCache(this.class.getClassLoader());
The behavior that I am expecting is:
- Start up tomcat and hit a page and it says 'Hello World'
- Change the properties file containing 'Hello World' to 'Goodbye Earth'
- Clear the cache using a servlet
- Hit the page and expect to see 'Goodbye Earth'
So question is, how is ResourceBundle.clearCache() actually working ? And is there some generic file cache we need to clear also ?
This worked for me:
ResourceBundle.clearCache();
ResourceBundle resourceBundle= ResourceBundle.getBundle("YourBundlePropertiesFile");
String value = resourceBundle.getString("your_resource_bundle_key");
Notes:
- ResourceBundle.clearCache() is added at Java 1.6
- Do not use a static resourceBundle property, use
ResourceBundle.getBundle()
method after invokingclearCache()
method.
I do not believe you can effect the reloading of an already created ResourceBundle instance since its internal control class has already been created. You may try this as an alternative for initializing your bundle:
ResourceBundle.getBundle("my.bundle", new ResourceBundle.Control() {
@Override
public long getTimeToLive(String arg0, Locale arg1) {
return TTL_DONT_CACHE;
}
});
I have found this solution (works with tomcat):
- use a custom ResourceBundle.Control (because I need UTF8)
- add the getTimeToLive as "Perception" description
- force the reload flag
- the "ResourceBundle.clearCache" doesn't work
How to call :
ResourceBundle bundle = ResourceBundle.getBundle("yourfile", new UTF8Control());
The custom class :
public class UTF8Control extends Control
{
public ResourceBundle newBundle(
String baseName,
Locale locale,
String format,
ClassLoader loader,
boolean reload)
throws IllegalAccessException, InstantiationException, IOException
{
// The below is a copy of the default implementation.
String bundleName = toBundleName(baseName, locale);
String resourceName = toResourceName(bundleName, "properties");
ResourceBundle bundle = null;
InputStream stream = null;
// FORCE RELOAD because needsReload doesn't work and reload is always false
reload = true;
if (reload) {
URL url = loader.getResource(resourceName);
if (url != null) {
URLConnection connection = url.openConnection();
if (connection != null) {
connection.setUseCaches(false);
stream = connection.getInputStream();
}
}
}
else {
stream = loader.getResourceAsStream(resourceName);
}
if (stream != null) {
try {
// Only this line is changed to make it to read properties files as UTF-8.
bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8"));
}
finally {
stream.close();
}
}
return bundle;
}
// ASK NOT TO CACHE
public long getTimeToLive(String arg0, Locale arg1) {
return TTL_DONT_CACHE;
}
}
maybe this post can solve your problem.
this is one more possibility to clear cache
Class<ResourceBundle> type = ResourceBundle.class;
try {
Field cacheList = type.getDeclaredField("cacheList");
cacheList.setAccessible(true);
((Map<?, ?>) cacheList.get(ResourceBundle.class)).clear();
}
catch (Exception e) {
system.out.print("Failed to clear ResourceBundle cache" + e);
}
This works, iff you can intercept the very first creation of the resource bundle:
while (true) {
ResourceBundle resourceBundle = ResourceBundle.getBundle("SystemMessages", new Locale("hu", "HU"),
new ResourceBundle.Control() {
@Override
public List<String> getFormats(String baseName) {
return ResourceBundle.Control.FORMAT_PROPERTIES;
}
@Override
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException {
System.err.println(this.toBundleName(baseName, locale) + ": " + format + " - " + reload);
return super.newBundle(baseName, locale, format, loader, reload);
}
@Override
public long getTimeToLive(String baseName, Locale locale) {
long ttl = 1000;
System.err.println(this.toBundleName(baseName, locale) + " - " + ttl + "ms");
return ttl;
}
@Override
public boolean needsReload(String baseName, Locale locale, String format, ClassLoader loader, ResourceBundle bundle, long loadTime) {
System.err.println(baseName + "_" + locale + " - " + new Date(loadTime));
return true;
}
});
System.out.println(resourceBundle.getString("display.first_name") + ": John");
System.out.println(resourceBundle.getString("display.last_name") + ": Doe");
Thread.sleep(5000);
}
来源:https://stackoverflow.com/questions/9819999/how-to-clear-resourcebundle-cache