Load ResourceBundle from classpath

2019-09-06 02:28发布

问题:

I have two jar files. One of the jars needs to read language pack from another jar. Here is basic structure of both jars

jar1    
   |--com.example.BundleLoader 



jar2
   |--strings
         |--language.properties
         |--language_fr.properties

Language pack is on the classpath. In order to read language packs by the BundleLoader I am trying to use ResourseBundle in conjunction with ClassLoader.

This is how I am attempting to do that

<--snipet-->
private ResourceBundle englishStrings = null;
private ResourceBundle frenchStrings = null;
<--end of snippet--->


<---snippet--->
        System.out.println("About to load url from classpath for properties file "+bundleLocation);
        URL url=ClassLoader.getSystemResource(bundleLocation);
        bundleLocation=url.toString();
        System.out.println("Ok loaded it");
        System.out.println("url is "+(url==null?"not available":url.toString())); //Got the folder location

        try {
            URL[] urls = {new URL(bundleLocation)}; //created array of ULRs to be loaded by URLClassLoader
            this.englishStrings = ResourceBundle.getBundle("validationStrings", Locale.getDefault(),new URLClassLoader(urls)); //Exception here
            this.frenchStrings = ResourceBundle.getBundle("validationStrings", Locale.FRENCH,new URLClassLoader(urls));             
            } catch (MalformedURLException e1)
            {// TODO Auto-generated catch block
                e1.printStackTrace();
            }

    }
<--End of Snippet-->

The Exception that I get is

java.lang.ExceptionInInitializerError
    at com.example.Model.model.dObject.doCommon(dObject.java:70)
    at com.example.Model.model.dObject.validate(dObject.java:42)
    at com.example.Model.model.test.dObjectTest.testChpValidate(dObjectTest.java:49)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.util.MissingResourceException: Can't find bundle for base name validationStrings, locale en_CA
    at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:1499)
    at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1322)
    at java.util.ResourceBundle.getBundle(ResourceBundle.java:1028)
    at com.example.util.Strings.<init>(Strings.java:51)
    at com.example.util.Strings.<clinit>(Strings.java:26)
    ... 27 more

Basically I can't find bundles even though property files are in the folder. Have anyone ran into this? I assume that someone dealt with this before.

Thank you.

回答1:

ResourceBundle.getBundle("validationStrings", Locale.FRENCH) will look in any JAR on the classpath for a file called validationStrings_fr.properties directly under the root directory. If it can't find that, it will try validationStrings.properties.

If you aren't able to change the structure of the language pack JAR, try replacing your entire second snippet with just

this.englishStrings = ResourceBundle.getBundle("strings.language");
this.frenchStrings = ResourceBundle.getBundle("strings.language", Locale.FRENCH);

The englishStrings line will look for files strings/language_en_CA.properties (assuming your default locale is en_CA), and then fall back to strings/language.properties when it cannot find that. The frenchStrings line will look for strings/language_fr.properties.