Software Musings

Software musings for the mildly amused

How to access Environment Variables in the Spring IoC Configuration

THE PROBLEM: We have a simple properties file used to dynamically define the Data Source. Here is the Data Source configuration:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>${db.driver}</value>
</property>
<property name="url">
<value>
${db.connectionType}://${db.url}:${db.port}/${db.name}
</value>
</property>
<property name="username">
<value>${db.username}</value>
</property>
<property name="password">
<value>${db.password}</value>
</property>
</bean>

I had a PropertyPlaceholderConfigurer that pointed to the location of my properties file, which was located in the classpath. (<property name="location" value="classpath:context.properties" />). My application, built using Maven, would create an executable jar containing the dependencies and everything ran perfectly… in my development environment.

I realized that this would not be ideal for other environments, but I kind of pushed this out of my mind during the initial development phase. However, it was now time to support multiple environments dynamically.
SOLUTIONS:

Manually editing the properties file was not an option, it was locked in the executable jar. So, it is clear that the file would need to be placed somewhere else in the file system.

My first solution was to simply change the location to: <property name="location" value="file://${ctx.props}" />. This would allow us to start the application with whichever properties we wished.

Unfortunately, we want to avoid using System properties when starting applications, instead we would like to use environment variables. Aside from being lazy, this can lead to enormous headaches trying to manage several environment variables throughout several environments. I would much rather create a simple startup script.

Here is where things get a bit confusing. Java 1.4 deprecated the System.getenv() method, which gave a Java application access to the environment variables. Therefore Spring did not support accessing environment variables. So, when I googled “spring environment variables”, I found several posting indicating that it was not supported and not possible.

It wasn’t until dug into the API (which is where I should have started), that I found that Spring does in fact support this out of the box. So, now the environment variable problem was solved as follows:
<property name="location" value="file://${CONFIG_DIR}/context.properties" />

Now, however, I (and all other developers) were stuck having to create an environment variable locally for a deployment requirement. So, after some quick research, I ended up with this solution:
<bean id="dataConfigPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file://${CONFIG_DIR}/batchContext.properties</value>
<value>file://${ctx.props}</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
<property name="searchSystemEnvironment" value="true" />
</bean>

Now, I can run this locally (assuming that I have not set the environment variable) with the ctx.props set as a System property or I can run it with the environment variable set (and no System variable).

ONE MORE THING:

With this setup, I would have a properties file in my jar that I never use (because I am using a file resource rather than a classpath resource). So, I had to update my Maven POM to exclude the properties file in the build.
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>executable.Startup</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>install</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>*.properties</exclude>
</excludes>
</resource>
</resources>
</build>

A more in-depth look at property files can be found here.

Single Post Navigation

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 )

Connecting to %s

Follow

Get every new post delivered to your Inbox.