Question

We are using java.util.ResourceBundle to load property information. Our property file has grown so huge and we are thinking of splitting the master property file into several sub modules. Is it possible to achieve this?

master.properties

==> 

 master.properties
   include moduleA.properties
   include moduleB.properties

Let me know?

Was it helpful?

Solution

First of all, I wonder why you've chosen java.util.ResourceBundle over java.util.Properties. Given how your question is formulated, you don't seem to care about localization/internationalization nor about bundle file inheritance.

With Properties it's extraordinary easy since it implements Map which in turn offers a putAll() method to merge another map. Kickoff example:

Properties master = new Properties();
master.load(masterInput);

Properties moduleA = new Properties();
moduleA.load(moduleAinput);
master.putAll(moduleA);

Properties moduleB = new Properties();
moduleB.load(moduleBinput);
master.putAll(moduleB);

// Now `master` contains the properties of all files.

If you really insist in using ResourceBundle, your best bet is to create a custom ResourceBundle wherein you contol the loading by a custom Control.

Assuming that you've the following entry in master.properties which represents a commaseparated string with base names of the module properties files:

include=moduleA,moduleB

Then the following custom ResourceBundle example should work:

public class MultiResourceBundle extends ResourceBundle {

    protected static final Control CONTROL = new MultiResourceBundleControl();
    private Properties properties;

    public MultiResourceBundle(String baseName) {
        setParent(ResourceBundle.getBundle(baseName, CONTROL));
    }

    protected MultiResourceBundle(Properties properties) {
        this.properties = properties;
    }

    @Override
    protected Object handleGetObject(String key) {
        return properties != null ? properties.get(key) : parent.getObject(key);
    }

    @Override
    @SuppressWarnings("unchecked")
    public Enumeration<String> getKeys() {
        return properties != null ? (Enumeration<String>) properties.propertyNames() : parent.getKeys();
    }

    protected static class MultiResourceBundleControl extends Control {
        @Override
        public ResourceBundle newBundle(
            String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
                throws IllegalAccessException, InstantiationException, IOException
        {
            Properties properties = load(baseName, loader);
            String include = properties.getProperty("include");
            if (include != null) {
                for (String includeBaseName : include.split("\\s*,\\s*")) {
                    properties.putAll(load(includeBaseName, loader));
                }
            }
            return new MultiResourceBundle(properties);
        }

        private Properties load(String baseName, ClassLoader loader) throws IOException {
            Properties properties = new Properties();
            properties.load(loader.getResourceAsStream(baseName + ".properties"));
            return properties;
        }
    }

}

(trivial exception handling and localization handling is left aside, this is up to you)

This can be used as:

ResourceBundle bundle = new MultiResourceBundle("master");

OTHER TIPS

You can programatically, however, construct ResourceBundle but as you are saying your file is huge then what if it is loaded into memory.

update

public class Resource extends java.util.ResourceBundle {



    public Object handleGetObject(String key) {
         //code
    }

    public Enumeration getKeys() {
         //code
    }
}

then for IN locale

import java.util.*;

public class Resource_en_IN extends Resource{

  public Object handleGetObject(String key) {
    //code
  }
}

More Food for thought than a tested solution.

XML files support entities to inline text from other files during parsing. If seen complex xml files, where this technique has been used to modularise the files.

Properties now supports two file formats, the common .properties format with key/value pairs and an xml formats. Properties can load and store to/from xml files.

ResourceBundle has one direct subclass: PropertyResourceBundle. It looks like this class is actually limited to the older key/value pair format, but it could be used to implement another class, like XMLPropertyResourceBundle which is capable of reading properties from xml files where the entity trick could help to modularize those files.

If this works - transforming the existing property files to xml properties files should be easy, just use the Properties class, read from standard format and store to XML.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top