Configuring Spring for Test versus Production

Spring Configuration Options

The Spring Framework is not opinionated software. Instead, Spring has a rich set of configuration options about which you can — indeed, about which you must — make up your own mind. In this tutorial we’ll discuss some of the ways you can easily configure your application to be ready for production, while still making it easy to work with your code in a test environment.

The META-INF Gospel

When you’re first getting something working, the easiest path I’ve found is to locate your properties somewhere underneath what in the standard Maven directory structure is the src\main\resources\META-INF directory. Then, to give just one example for now, you want to point to those resources as shown in the following annotation from a Unit test:

This will work just fine, and although I’ve seen a few spec Nazis on Stackoverflow complain that the Java JAR specification contains the gospel truth about what files are allowed in the META-INF directory, I’ll take the side of Roo and other Spring tools to preach a new gospel to you:

**Generally speaking, put your configuration files in META-INF, unless you like pain.**

That will get your software working, but the limitation of this approach is that once you’ve located all your configuration files in META-INF\ to set up a single environment correctly, how do you set up _different_ environments like those you’ll need for test, staging, and production. Though I’m sure there are a lot more ways to skin this poor cat, let’s discuss two of the more popular approaches to this problem. The first option, which we’ll discuss more briefly, is to resolve all your option file dependencies at compile time.

Configuring Spring Properties Using Multiple Modules

To use this approach, you set up a multi-module project. This approach takes advantage of the fact that WAR files can pack all the jars they need inside themselves, ready to be deployed to Tomcat or another web server. So we bundle our code and any configuration files that are common to all our target environments in the WAR file, then build a jar file for each different environment containing only environment-specific files.

What we might end up with is a directory structure that looks something like this:

The app directory contains the whole structure of the application’s WAR file project. In the root directory is a pom file that builds the targets in the other directories, as shown in the following snippet:

The config_test and config_production files contain a src\main\resource\WEB-INF directory, whatever configuration files you need, and a pom file in the root to bundle the configuration files into a JAR. What’s important is that although the contents of the files will contain different settings, the names of the files should be the same in each configuration file we build — that way when they’re referenced from the main files in the application’s WAR files, all is well.

In turn, the WAR file in the main app depend on either the test configuration or the production configuration as desired, as shown in the snippet below. In the snippet below, we’re building for the test environment, so the production configuration is disabled.

I’ve used the multi-module approach and it works fine, but having to build three projects to configure one WAR file is a bit heavy handed. It also spreads the configuration files around more than I like. Fortunately, there’s an easier way to get this done, and that is to resolve the configuration files at run time, not at build time.

Configuring Spring Properties at Run Time Using the PropertyPlaceholderConfigurer

One powerful mechanism that Spring provides to make configuration flexible across different environments is the PropertyPlaceholderConfigurer. Since I think it’s the better approach, let’s take a look at a more detailed tutorial. The code for this is available under the PropertyPlaceholderConfigurer directory of our Github Tutorials Repository.

The structure of our PropertyPlaceholderConfigurer build is shown below:

propertyplaceholderconfigurer

We have a single bean under test (yes, you guessed it: TestBean), and our mission, if we choose to accept it, is to:

1. Dynamically set up properties in our configuration files, so we can switch to new properties in production.

2. Inject the values of those properties into the test bean. In many cases our properties would be consumed by another third-party bean, but injecting properties directly allows us to take the next step…

3. Set up a unit test to show that we correctly injected the properties we want for the appropriate environment

Setting up PropertyPlaceholderConfigurer in the ApplicationContext

Our main “common configuration” area is in the META-INF\spring. Our global properties file and main application context file go here. Let’s look at applicationContext.xml, where the detailed comment explains what’s going on:

Some Properties Files to Test

To have something to test, we’ve set up three simple properties files. First, we have a global “common.properties” with our humble title:

Next come two db.properties files:

test/db.properties:

production/db.properties:

Injecting Properties

To keep things simple, lets inject only two of these properties. If our setup is correct and we set the environment variable “environment” to “test” we should be able to verify that we get the right application name (a global property), and the test environment value for (for example) database.username.

We inject these properties in TestBean.java:

Testing with JUnit

As a final step, let’s make sure we’re running our test environment and our properties are injected correctly. Our JUnit test is as follows:

Working with the PropertyPlaceholderConfigurer class lets you easily configure your WAR file for production, test, and any other environments you need — and with that out of the way, you can now get busy writing your application. Enjoy!