I am working in a project where I have to load two different property files (for example parent.properties & child.properties ) which are totally have different base name and it should also have inheritance relationship between this two bundle. So that if any keys are not found in child.properties it should get from parent.properties.
When I was analyzing the resource bundle code, I came to know there is method setParent(), this method is used to set which is your parent bundle (something like java super class). For example if we use bundle name called "child_en.properties" the my parent bundle should be "child.properties".
As this method was protected method in ResourceBundle Class, so to use this class I have sub classed my own ResourceBundle class and overridden the setParent Method like below.
public class P4JResourceBundle extends ResourceBundle { protected void setParent(ResourceBundle parent) { super.setParent(parent); } public void letsChangeParent(String parent){ this.setParent(ResourceBundle.getBundle(parent)); } public Enumeration getKeys() { return null; } protected Object handleGetObject(String key) { return null; }So after changing the class I have executed with the below method, excepts that it should pick the key from parent.properties file if the key is not present in child.properties file.
public class ResourceBundleExample { public static void main(String[] args) { P4JResourceBundle myBundle = new P4JResourceBundle(); myBundle.letsChangeParent("com.passion4java.resourcebundle.parent"); ResourceBundle bundle = myBundle.getBundle("com.passion4java.resourcebundle.child"); System.out.println(bundle.getString("i_am_not_in_child_file")); } }As usual J there is an error thrown saying the key was missing.
Exception in thread "main" java.util.MissingResourceException: Can't find resource for bundle java.util.PropertyResourceBundle, key i_am_not_in_child_file at java.util.ResourceBundle.getObject(Unknown Source) at java.util.ResourceBundle.getString(Unknown Source) at com.passion4java.resourcebundle.ResourceBundleExample.main(ResourceBundleExample.java:11)So what's wrong?
I tried to debug the code in the resource bundle class and below code surprised me.
public static final ResourceBundle getBundle(String baseName,Locale locale){ return getBundleImpl(baseName, locale, getLoader()); } private static ResourceBundle getBundleImpl(String baseName, Locale locale, ClassLoader loader){ if (baseName == null) { throw new NullPointerException (); } String bundleName = baseName; String localeSuffix = locale.toString(); if (localeSuffix.length() > 0) { bundleName += "_" + localeSuffix; } else if (locale.getVariant().length() > 0) { //new Locale("", "", "VARIANT").toString == "" bundleName += "___" + locale.getVariant(); } Locale defaultLocale = Locale.getDefault(); Object lookup = findBundleInCache(loader, bundleName, defaultLocale); if (lookup == NOT_FOUND) { throwMissingResourceException(baseName, locale); } else if (lookup != null) { return (ResourceBundle )lookup; } Object parent = NOT_FOUND; // **********THIS_LINE_OF_CODE********** try { //locate the root bundle and work toward the desired child Object root = findBundle(loader, baseName, defaultLocale, baseName, null); if (root == null) { putBundleInCache(loader, baseName, defaultLocale, NOT_FOUND); root = NOT_FOUND; } …contAs I was setting the value in setParent() of resource bundle to change the parent resource bundle, but when the bundle are created using ResourceBundle.getInstance(), internally it calls getBundleImpl() which set the parent as "NOT_FOUND" direcly.
I was really confused why the code was setting directly rather than using values from the setter method????
As user of this class this implementation really stops customization which users expects.
Please feel free to comment.
12 comments:
In which Java version?
i have checked in java 1.5
Seems that it no longer apply to Java6 ... I coulnd't found that code inside the ResourceBundle class ... ;-)
Thats really great Klli ...But is there any way available in java6 to set the parent ???
The parent is normally used for default values based on Locale, eg you have resources_fr_CH which parent is resources_fr which parent is resources. I don't think using setParent is really supported for what you want.
I had exactly the same problem with ResourceBundle a couple of weeks ago (in guts-gui), and my solution was simply to not use it at all!
I think jfpoilpret is correct. You could try to obtain the values you want from one bundle, and if not found, try to obtain it from the other bundle, but that's a solution you probably thought about ... ;-)
jfpoilpret, i think that may be a best solution :) (just kidding). I was think why sun have given as setParent method and not using it :(
this is a basic concept in OOPS
Kili Liam, that we may use when we directly handle ResourceBundle class.
I got this problem when i was using fmt:message tag of JSTL...
Their i have no help :)
Oooouuuuuhhhh! That's a different kind of problem ... hope you can solve it.
Still trying :)
When I bought my computer and I didn´t know how to use java graphics, so I decided looking for information in a webside and I found an useful information that helped me a lot.. Now I am interested in to do the best investment and I found a webside very useful and interesting called costa rica investment opportunities , I think it´s a very wonderful site.
I think that it quite interesting to set them with those attributes. It is a pity that it isn't available in java 1.6. I hope that you fix the problem.
Viagra Online Cheap Viagra
Post a Comment