Spring: Environment specific configuration

environment-variables, java, properties, spring

Solution

I use for this purpose a subcass of `PropertyPlaceholderConfigurer`:

public class EnvironmentPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {

    private static final String ENVIRONMENT_NAME = "targetEnvironment";

    private String environment;

    public EnvironmentPropertyPlaceholderConfigurer() {
        super();
        String env = resolveSystemProperty(ENVIRONMENT_NAME);
        if (StringUtils.isNotEmpty(env)) {
            environment = env;
        }
    }

    @Override
    protected String resolvePlaceholder(String placeholder, Properties props) {
        if (environment != null) {
            String value = props.getProperty(String.format("%s.%s", environment, placeholder));
            if (value != null) {
                return value;
            }
        }
        return super.resolvePlaceholder(placeholder, props);
    }

}

and using it in `applicationContext.xml` (or any other spring-configuration file):

<bean id="propertyPlaceholder"class="EnvironmentPropertyPlaceholderConfigurer">
    <property name="location" value="classpath:my.properties" />
</bean>

In `my.properties` you can define properties like:

db.driverClassName=org.mariadb.jdbc.Driver
db.url=jdbc:mysql:///MyDB
db.username=user
db.password=secret
prod.db.username=prod-user
prod.db.password=verysecret
test.db.password=notsosecret

Thereby you can prefix properties keys by an environment key (e.g. `prod`).

Using the vm argument `targetEnvironment` you can choose the enviroment you like to use, e.g. `-DtargetEnvironment=prod`.

If no environment-specific-property exists, the default one (without a prefix) is choosen. (You should always define a default one.)

Problem

Using Spring I need some kind of environment (dev|test|prod) specific properties. I have exactly one configuration file (myapp.properties) and for some reasons I cannot have more than one configuration file (even spring can handle more than one). So I need the possibility to add properties with a prefix like ``` dev.db.user=foo prod.db.user=foo ``` and tell the application which prefix (environment) to use with a VM-argument like `-Denv-target` or something like this.

Original source