Reloading Java ResourceBundle at Runtime
One of my friends asked me a few days back for how to reload the ResourceBundle in Java while the program is still executing. The first question is that why do we need to reload a ResourceBundle while runtime.
There could be various reasons for reloading a ResourceBundle in Java. To mention a few -
- Your program is built so as to run continuously for a longer period with different inputs at different stages.
- Your program is divided in to stages and the output of one stage is input of the next one. You want the inputs to only go through ResourceBundle and the always through the same one.
The above mentioned reasons are what my friend asked me for. But the second question is whether Java really does not allow us to do so. Till Java 1.5, this is not possible. This a reported defect in Java 1.5. Next release of Java i.e. 1.6 has fixed this one. Then why not use Java 1.6 instead of Java 1.5. This could be because of various reasons. I hope all Java geeks must be knowing this.
How does the ResourceBundle work?
Initially you need to load the ResourceBundle into your program -
ResourceBundle myBundle = ResourceBundle.getBundle(“myResources.properties”);
Here, myResources.properties is a file that contains a key value pair. When you use getBundle() method of the ResourceBundle class, it loads all the data into a HashTable in the cache.
Now you can retrieve the values simply by the following code -
myBundle.getString(“key”); or myBundle.getObject(“key”);
Once loaded into the cache, this is kept till the program runs. In Java 1.5, there is no inbuilt way to clear this cache and reload the ResourceBundle.
So even if you change the values in myResources.properties file and call the getBundle() method again, the cache is not cleared and reloaded. So when you go ahead with getString() or getObject() method, you still retrieve the older values.
How to reload ResourceBundle in Java 1.5?
There is a little work around for this. You can use the following code to reload the resource. The code below uses reflection to access a private member of the ResourceBundle class and clear the cache.
//clear the cache
java.lang.Class myClass = ResourceBundle.class;
try{
java.lang.reflect.Field cacheList = class.getDeclaredField(“cacheList”);
cacheList.setAccessible(true);
((Map)cacheList.get(ResourceBundle.class)).clear();
}catch (NoSuchFieldException noSuchFieldEx) {
System.err.println(this.getClass().getName() + ” : ” +
noSuchFieldEx.getMessage());
}
I hope this will help you to reload ResourceBundle for long running processes.
If you like the post/ solution, please leave a comment here.




May 8th, 2009 at 5:03 pm
it is not working
May 11th, 2009 at 2:59 pm
Can you tell me what you did?
May 25th, 2009 at 5:19 pm
Hey Buddy,
Your solution is right. But it has a little problem. Let me explain. You are accessing private field (cacheList) of ResourceBundle using reflection and using ResourceBundle.class as key to get and clear the bundle cache. But cacheList usage ResourceCacheKey as key. Please check ResourceBundle class. So you will have to use instance of ResourceCacheKey as a key to search your bundle cache and clear it.
But I will suggest you to not to use this solution in enterprise application because accessing the private field using reflection is not recommended. It should be used when you don’t have any other alternative. But in this case java has provided you the alternative solution to load your resource bundle using the Properties utility of Java. So I will suggest you to use Properties to load your resource bundle. You can use singleton pattern to load the bundle for better performance and can use a boolean flag to pass a command to reload the bundle when required.
June 1st, 2009 at 1:24 pm
Nitesh you are absolutely correct from your point of view.
Firstly, this solution was neither for enterprise application and nor for day to day use. This was a completely personal requirement of my friend since his program was a long running program and used its output as input to resource bundle during runtime. I just thought of sharing this solution. Please read the blog entry for reference.
Secondly, my friend did not want to search for bundle cache with any key. He simply wanted all the cache to be cleared.
Thirdly, using Properties class of the java is good option but not when you work on localization. I think I should have mentioned the background in much detail.
Last but not the least, I am happy Nitesh was attracted to this post. To all, Nitesh is a geek! Kaisa hai dost?
To Suresh – This is not the complete solution. You need to use the peice of my code in your program. Create your own class and work out things. Need help, email me at – amar@gautamfamily.net
June 2nd, 2009 at 11:49 am
I really liked this post. Can I copy it to my site? Thank you in advance.
June 2nd, 2009 at 2:58 pm
You can copy it to your site but kindly give me a back link and an acknowledgement.
July 6th, 2009 at 11:18 pm
It’s a pity that people don’t realize the importance of this information. Thanks for posing it.
July 28th, 2009 at 2:31 pm
I’m glad that after surfing the web for such a long time I have found out this information. I’m really lucky.
July 30th, 2009 at 3:18 pm
Thanks for post. Nice to see such good ideas.
August 7th, 2009 at 3:18 pm
The best information i have found exactly here. Keep going Thank you
August 10th, 2009 at 11:20 am
I had this implemented in my web already, like this..
private static void clearMap(Class cl, Object obj, String name)
throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException,
InvocationTargetException
{
Field field = cl.getDeclaredField(name);
field.setAccessible(true);
Object cache = field.get(obj);
Class ccl = cache.getClass();
Method clearMethod = ccl.getMethod("clear", null);
clearMethod.invoke(cache, null);
}
But there is one problem in it,
I am using tomcat, and tomcat context reloads and invalidates the session. are there any work arounds for this?
September 11th, 2009 at 1:06 am
how about clearcache in java 1.6? .
i try this, but doesn’t work!
ResourceBundle.clearCache();
resourceBundle = ResourceBundle.getBundle(Constants.RESOURCES);
i apreciate any help!
September 11th, 2009 at 4:48 pm
This defect has been fixed in Java 1.6
Check specifications of Java 6.
October 29th, 2009 at 9:54 pm
ResourceBundle.clearCache() doesn’t work on my tomcat/jre 1.6
My walkaround solution is as follow:
Create ResourceBundle.Control subclass, override getTimeToLive and needsReload functions to force reload when necessary.
Then use ResourceBundle.getBundle(“myproperty”,locale,myResouceBundleControl)
Here’s the source (subclass). have fun:
boolean needReload = false;
class myResourceBundleControl extends ResourceBundle.Control{
@Override
public long getTimeToLive(String baseName, Locale locale) {
//System.out.println(“asking TTL”);
if(needReload)
return 0; //ResourceBundle.Control.TTL_DONT_CACHE doesn’t work;
else
return ResourceBundle.Control.TTL_NO_EXPIRATION_CONTROL;
}
@Override
public boolean needsReload(String baseName, Locale locale, String format, ClassLoader loader, ResourceBundle bundle, long loadTime)
{
return needReload;
}
}
June 11th, 2010 at 2:50 am
can you give me share a sample code how it works with ResourceBundle.control beacause i implemented it but it is not working with this resourcebundle.control