Enno Shioji
Enno Shioji

Reputation: 26882

Good library for parameter injection/properties management

I have a piece of code that I have been using to manage properties for a while now. My boss didn't like this solution on the ground that property management should be done by well-known libraries, like Spring/Guice. That's understandable, and I'm looking for alternatives, but I can't find one that gives me the features that I want (or maybe I don't know how to use them properly).

The features I'm looking for are:

  1. SUPER easy to add new properties to a class during coding
    1. No need to touch constructor, add dedicated field or setters
    2. Uses Java code (as much as possible)
    3. Easy to add defaults. No need to edit property file if you just want make something quickly configurable and keep the code working
  2. Can use any types (can define conversion from String within the framework)
  3. Custom validation that are run at config load time for each properties
    1. E.g. check for existence for a file, check if defined conversion succeeds etc.
  4. Ability to inject parameters to final fields
  5. Ability to auto-generate property file TEMPLATE
    1. Especially ability to define description, preferably in Java code which is then written to the template
  6. Ability to update config at runtime, in a thread-safe manner

Are there any library that gives me these features?

If I'm missing something and these can all be satisfied by Spring/Guice, are there any good resource online?

Example usage of my solution
Sample of generated property file TEMPLATE (you copy and edit this)

Upvotes: 2

Views: 1231

Answers (1)

meriton
meriton

Reputation: 70574

No need to touch constructor, add dedicated field or setters

That is not the dependency injection pattern. You might substitute the resource locator pattern, but doing that well (in particular, in a way the retains testability) is not trivial: With a setter, I can easily reconfigure the class under test. If that class depends on a config file, will I write a separate config file whenever I need to change settings for the unit test? Will I mock the config class? Possible, but not exactly straighforward ...

Ability to auto-generate property file TEMPLATE

As already pointed out in the comments, this doesn't seem very useful, as it can not migrate an old config file.

Ability to update config at runtime, in a thread-safe manner

That, in general, requires support from the component being configured (for instance, changing a setting for thread pool size involves starting / stopping worker threads ...). In general, the only simple way to handle that is restarting the application ...

If you drop these requirements, Spring's PropertyOverrideConfigurer fits nicely.

Alternatively, if you run inside a servlet container, you could pepper your Spring config with JNDI lookups.

If you really want to generate templates, I don't know a ready-made solution. I might do something like:

class Configuration {

    int threadCount = 10;

    String secretKey;

    @Description("Number of workers. Default value is number of available cores.")
    int workerThreadCount = Runtime.getRuntime().availableProcessors();

    /** Use default settings */
    Configuration() {

    }

    /** read the settings from the file */
    Configuration(Properties props) {
        for (String prop : props) {
            Field f = getClass().getField(prop);
            f.set(this, props.getValue(prop)); 
            // TODO: type conversion, 
            // e.g. with PropertyEditors, 
            // or Spring's ConversionService, 
            // or invoking the constructor that takes a single string argument, 
            // or ...
        }
    }

    void save() {
        for (Field f : getClass().getFields()) {
            // TODO save the setting
        }
    }
}

Writing the default configuration would be a simple as new Configuration().save(file), or upgrading an existing configuration as simple as `new Configuration(file).save(file)'.

Unlike your approach, this approach is statically type safe, and doesn't clutter the code accessing the configuration settings with redundant type specifiers. That is, instead of

if(config.value(Prop.PROXY_ENABLED,Boolean.class)){

you could simply write

if (config.proxyEnabled) {

and because the field can be of type boolean (not Boolean), you don't even risk a NullPointerException here.

Upvotes: 3

Related Questions