Flexible Configuration for Modular Systems

The Problem

Properties are cool, but you can only pickup the configuration of one property file at a time. If you have a base configuration in your framework jar and need to allow further tweaking of that configuration in a higher level, then a well defined chain of responsibilities often helps.
Usually this is done by

  • having the base configuration in yourframework.jar
  • overriding the configuration if the same config.properties file exists in WEB-INF/classes

But this solution is pretty restrictive and wont help you if you have a plugin architecture utilising the java.util.ServiceLoader mechanism. Speaking of OpenWebBeans, we have most of our functionality provided as SPI (Service Provider Interface) and the implementation which should get used is being picked via a config.properties. The problem we face is that we have lots of droppable plugins which need a different configuration. If you use the openwebbeans-resource.jar alone, then you’ll get a basic support for JPA via a SPI-implementation. If you additionally use openwebbeans-openejb, then we need to use another SPI implementation to get EntityManagers from OpenEJB instead.
But the config.properties are all contained in JARs which have the same layer (all in WEB-INF/lib, your EAR lib or in the EE-Server classpath) – which means the algorithm mentioned above isn’t enough anymore. This is even more true in OSGi environments where you don’t have any control over the classloader hierarchy anymore.

The Solution

Instead of maintaining the importance of an application implicitly via it’s location, we just explicitely give each config file a configuration.ordinal property. Higher values mean higher importance. And here is how it works:

  • First we scan for all config.properties files with ClassLoader.getResources()
  • Scan all found properties files for it’s configuration.ordinal value. If no such property is found, we assume a default value of 100
  • Sort all found config files by their configuration.ordinal values in ascending order
  • Start overlaying all properties by applying them in ascending configuration.ordinal order. All properties defined with a higher ordinal will just override the values from any less important config file.

The Usage

Just type your properties files as usual.

myconfig.properties has a configuration.ordinal of 15

configuration.ordinal=15
my.value = hello user
my.othervalue = not overwritten

Another jar contains a myconfig.properties with a configuration.ordinal of 20

configuration.ordinal=20
my.value = and now something completely different

The resulting property values are:

my.value = and now something completely different
my.othervalue = not overwritten

The Source

The whole source can be found in our Apache OpenWebBeans SVN repository:
PropertyLoader.java

Advertisements

About struberg
I'm an Apache Software Foundation member blogging about Java, µC, TheASF, OpenWebBeans, Maven, MyFaces, CODI, GIT, OpenJPA, TomEE, DeltaSpike, ...

5 Responses to Flexible Configuration for Modular Systems

  1. That is something could be shared inside commons-configuration as well! 🙂

  2. struberg says:

    of course, but commons-configuration is in the meantime pretty huge already. I don’t feel the need to configure something via database. Maybe it’s much more modular in the meantime already. Or if we would be able to just ‘auto-fork’ parts of it via maven-shade-plugin…

  3. Pingback: Why is OpenWebBeans so fast? « Struberg's Blog

  4. Mario says:

    Maybe this spring-like, annotation-based, configuration system is interesting for you: https://github.com/mariomac/kaconf

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: