Christian Vielma
Christian Vielma

Reputation: 16035

Why not use ResourceBundle instead of Properties?

This is an easy question to which I can't find a concluding answer.

I can load string properties (e.g.: a query for a prepared statement) from a config.properties file. Let's say I want to take the database connection to which to connect.

If I want to take this information from the file, I could do just the following in a class:

    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("scheduler");
    private static final String DRIVER  = BUNDLE.getString("bd.driver");
    private static final String CONNECTIONURL  =BUNDLE.getString("bd.url");
....

But instead I've seen that many people recommend using instead Properties, Then I would have to do the same with something like this (if I want to keep the class static and not have a proper constructor):

static {
        prop = new Properties(); 
        try {                prop.load(ReportsDB.class.getClassLoader().getResourceAsStream("config.properties"));
        } catch (IOException ex) {
            Logger.getLogger(ReportsDB.class.getName()).log(Level.SEVERE, null, ex);
            throw new RuntimeException(ex);
        }
    }

    private static final String DRIVER  = prop.getProperty("bd.driver");
    private static final String CONNECTIONURL  = prop.getProperty("bd.url");

So, why shouldn’t I use the ResourceBundle instead of Properties when the second one is more verbose?

Upvotes: 6

Views: 7706

Answers (2)

Luke
Luke

Reputation: 1673

One concrete difference is that ResourceBundle.getBundle("scheduler") will search for the file in the classpath (the src package folder for example). If you call ResourceBundle.getBundle("myfile") on an external file you will get the MissingResourceException.

If you want to use an external file (a file located in the project root for example) you can use the Properties class:

Properties configuration = new Properties();
try (InputStream input = new FileInputStream("configuration.properties")) {
        configuration.load(input);
        System.out.println("Configuration value: " + configuration.getProperty("key"));
    } catch (IOException e) {
        e.printStackTrace();
    }

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503649

So, why shouldn’t I use the ResourceBundle instead of Properties when the second one is more verbose?

Because that's not what ResourceBundle is for. The description of the class starts with:

Resource bundles contain locale-specific objects. When your program needs a locale-specific resource, a String for example, your program can load it from the resource bundle that is appropriate for the current user's locale. In this way, you can write program code that is largely independent of the user's locale isolating most, if not all, of the locale-specific information in resource bundles.

Does any of this sound like your use case? I don't think so.

It sounds like the problem is purely the verbosity of loading a properties file: so write a utility method to do that. Then your code can be simply:

private static final Properties CONFIGURATION = PropertyUtil.load("scheduler.properties");
private static final String DRIVER = CONFIGURATION.getString("bd.driver");
private static final String CONNECTIONURL = CONFIGURATION.getString("bd.url");

Admittedly I'm not keen on having static field initializers in an order-dependent way like that... I'd be tempted to encapsulate all of the configuration in a separate class, so you could write:

private static final SchedulerConfiguration CONFIG = 
    SchedulerConfiguration.load("scheduler.properties");

then use CONFIG.getDriver() etc which could fetch from the properties each time, or use a field, or whatever.

Upvotes: 9

Related Questions