Core Java

Go (Con)Figure

Another post about Lightweight Config, a library I’ve recently built from the ground up, after creating various versions of it in previous projects.

Where previously, I’d tried to be clever and prepare the library for lots of possibilities, I took the opposite approach this time. I created a simple monolithic library to solve the core problem, and then in a later version added some new ideas that the simple idea opened up for me.

The Basic Challenge

In a service that has no specific injection framework, like Spring or DropWizard, and especially in a test, what’s the nicest way to load some configuration into an object.

E.g.

1
2
3
4
5
username: user
password: foo
urls:
  - http://foo.com
  - http://bar.com

We’d like to load this into an object:

1
2
3
4
5
6
7
public class Config {
    private String user;
    private String password;
    private List<String> urls;
 
    // getters and setters
}

This is easily achieved in one line with ConfigLoader.loadYmlConfigFromResource("config.yml", Config.class)

This assumes config.yml is in the appropriate resources.

Placeholders

What if we wanted to interpolate runtime values from environment variables or system properties? Well, that’s really the point of this framework. It’s intended to externalise the setting of values:

1
2
3
4
5
username: ${USERNAME}
password: ${PASSWORD}
urls:
  - http://foo.com
  - http://bar.com

Imports

If we have some common snippets of configuration to share between various configuration objects, then an import syntax would be nice. Even better if we can drive the import by a placeholder:

1
2
# config.yml
#import ${PROFILE}-config.yml

And then:

1
2
3
4
5
# dev-config.yml
username: username
password: foo
urls:
   - http://www.dev.com

And so on. Now we can load the config.yml but set PROFILE to determine which child config is also loaded. We can even put some common properties in the parent and it’ll all mash together into the load operation.

Plugins

What if we’re using a password/secret manager to load certain values dynamically? Let’s say we want to express that a certain value may be loaded from a secret:

1
2
username: !secret ${SECRET_ID}.user
password: !secret ${SECRET_ID}.password

We can add our custom tag – secret – to the loader:

1
2
3
Config myConfig = new ConfigLoader()
    .withTag("secret", secretPath -> secretsManager.load(secretPath))
    .loadAs("config.yml", Config.class);

Conclusion

With a little hindsight and a little code, I’ve put together a version of this framework I’m pleased to share with the open source community.

Published on Java Code Geeks with permission by Ashley Frieze, partner at our JCG program. See the original article here: Go (Con)Figure

Opinions expressed by Java Code Geeks contributors are their own.

Ashley Frieze

Software developer, stand-up comedian, musician, writer, jolly big cheer-monkey, skeptical thinker, Doctor Who fan, lover of fine sounds
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button