简体   繁体   中英

Load resource bundle at runtime

Here is what I would like to achieve. We have an application that is running as a servlet on an IBM Domino server. The application uses resource bundle to get translated messages and labels according to the browser language.

We want to enable customers to override some of the values. We cannot modify the bundle_lang.properties files in the .jar at runtime. So the idea was to provide additional bundleCustom_lang.properties files along with the .jar

This bundle could be loaded at runtime using

private static void addToClassPath(String s) throws Exception {
    File file = new File(s);
    URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader();
    java.lang.reflect.Method m = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
    m.setAccessible(true);
    m.invoke(cl, new Object[] { file.toURI().toURL() });
}

So far, so good, this works in Eclipse. Here I had the bundleCustom files in a directory outside the workspace ( /volumes/DATA/Temp/ )

Once the addition ResourceBundle is available, We check this bundle for the key first. If it returns a value than this value is being used for the translation. If no value is returned, or the file does not exist, the value from the bundle inside the .jar is used.

My full code is here

public class BundleTest2 {

    static final String CUSTOM_BUNDLE_PATH      = "/volumes/DATA/Temp/";
    static final String CUSTOM_BUNDLE_MODIFIER  = "Custom";

    public static void main(String[] args) {
        try {
            addToClassPath(CUSTOM_BUNDLE_PATH);

            System.out.println(_getTranslation("LabelBundle", "OutlineUsersAllVIP"));
        } catch (Exception e) {
        }
    }



    private static String _getTranslation(String bundle, String translation) {
        return _getTranslation0(bundle, new Locale("de"), translation);
    }

    private static String _getTranslation0(String bundle, Locale locale, String key) {
        String s = null;
        try {
            try {
                ResourceBundle custom = ResourceBundle.getBundle(bundle + CUSTOM_BUNDLE_MODIFIER, locale);
                if (custom.containsKey(key)) {
                    s = custom.getString(key);
                }
            } catch (MissingResourceException re) {
            System.out.println("CANNOT FIND CUSTOM RESOURCE BUNDLE: " + bundle + CUSTOM_BUNDLE_MODIFIER);
            }

            if (null == s || "".equals(s)) {
                s = ResourceBundle.getBundle(bundle, locale).getString(key);
            }
        } catch (Exception e) {
        }
        return s;
    }

    private static void addToClassPath(String s) throws Exception {
        File file = new File(s);
        URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader();
        java.lang.reflect.Method m = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
        m.setAccessible(true);
        m.invoke(cl, new Object[] { file.toURI().toURL() });
    }
}

When I try the same from inside the servlet, I get a MissingResourceException.

I also tried to put the .properties files into a customization.jar and provide the full path ( incl. the .jar ) when invoking addToClassPath(). Apparently, the customization.jar is loaded ( it is locked in the file system ), but I still get the MissingResourceException.

We already use the same code in addToClassPath to load a Db2 driver and this is working as expected.

What am I missing?

Why don't you use Database to store the overriden translations? Persisting something crated by client in the local deployment of application is generally not a good idea, what will happen if you redeploy the app, will these resources be deleted? What if you have to run another node of your app, how will you replicate the custom properties file?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM