Specifying A Priority Order of Properties Files in camel-context.xml

Apache Camel allows you to specify multiple properties files in camel-context.xml by separating them with a comma:

<propertyPlaceholder id="properties" 
location="file:/etc/configmap/app.properties,app.properties"/>

Great! But… this will still throw an exception if one of these files is missing. Not so great. Fortunately, we can fix that, and it’s relatively easy. There’s a property called ignoreMissingLocation:

<propertyPlaceholder id="properties" location="file:/etc/configmap/app.properties,app.properties"
 ignoreMissingLocation="true"/>

This is pretty useful, but still not quite what I need for my particular use-case. When multiple properties files are specified, and they all exist, they will all be loaded and their properties will be merged. In fact, the later files in the list will override earlier ones in the situation in which the same keys are specified in multiple files.

Camel

I need something else. I want to only use one properties file, the first one that exists, specified in priority order. This way I can load the properties file from its deployed location if my code is in production (or staging, etc.), and fall back to a local properties file if I’m still developing. This is particularly important when building multiple applications or services and I don’t want them all to point to the same properties file. Switching back and forth among applications would mean manually changing the properties file, or, worse, running with the wrong file. On my development machine now, I can leave /etc/configmap/app.properties missing.

So how do I do this? It seems subclassing DefaultPropertiesResolver is the only real option.

Here’s the relevant section of my camel-context.xml:

<bean id="propResolver" class="somepackage.OverriddenPropertiesResolver"/>
<bean id="propComponent" class="org.apache.camel.component.properties.PropertiesComponent"/>

<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="properties" propertiesResolverRef="propResolver" ignoreMissingLocation="true" location="file:/etc/configmap/app.properties,classpath:app.properties" />
</camelContext>

And now the code for the overridden class:

@Override
public Properties resolveProperties(CamelContext context, boolean ignoreMissingLocation, String... uris) throws Exception {
    Properties properties = null;
    for (final String uri : uris){
        try {
            properties = super.resolveProperties(context, ignoreMissingLocation, uri);
            break;
        }
        catch (Exception e) {
            // (Log if you want to, then move onto the next one)
        }
    }
    return properties;
}

Easy peasy.

Leave a Reply

Your email address will not be published. Required fields are marked *