Friday, February 17, 2012

Automatically change configuration based on current environment - Part 1

The problem

Suppose you are developing a web application (I'm doing it right now). You use Spring, Hibernate, Maven and all those good old friends from Java world.

Now you have a production environment and a development environment, and you have 2 developers, each one with different operating systems. So you probably end up with 3 possible configurations (different file locations, connection urls and logging settings) for each of the possible environments (production, developer1, developer2).

How do you manage your configuration settings so any time you run the application the correct configuration applies?

Previous solution

Initially, in previous projects, we used what Maven calls "maven profiles" and "resource filtering".
Basically this means that our configuration files had variables that maven was able to replace with correct values based on the current profile.
For example, we could define a variable "v" that had different values for development, and production environments. Our configuration files used that variable "v" and running maven with the correct profile resulted in v replaced by "A". (You can see more details here)

This approach had 2 main drawbacks:
  1. It's purely manual. We had to run this filtering process by manually specifying which maven profile was adequate.
  2. You have different builds for different environments, so you have to quality test every one of them.
  3. You have an additional build step. You had to make sure that whenever the application is started, the "filtering process" was correctly executed. This is not a problem in production environment because the war is assembled by maven, but it is an annoyance when developing.

New idea

What if the application were aware of its different running environments so it could change its configuration automatically based on the current?

If we wanted to do that, we had to solve 2 issues:

Fortunately for the second issue we have Spring 3.1 which introduced the concept of profiles to bean definitions. This is similar to what maven does to files but applied to beans. (more details)

Now, we can define different set of beans according to the current spring profile. If we structure our configuration in different sets of beans for each desired configuration we can change it easily.
The problem remains in how to detect the current environment to tell which spring profile to use.

Detect current environment

If we were able to determine which spring profile corresponds to the current execution environment we could let the application auto-configure itself.

So how do we detect the current execution environment?

We need to add environment sensors to the application, and define which possible environment profiles exist. Then if you know how each sensor measured on each environment profile, when you read current values, you can determine which environment profile is currently valid.

About the decision strategy

To decide which profile is best, I used a fuzzy-like criteria.
Since environments change and it's likely that sensor values do change with them it's necessary that the application tolerates some level of change. I used a threshold approach for this.

When the application has to decide which profile is best, it evaluates each profile against all sensors assigning a score value to the profile. The best scored profile is the candidate for current environment profile, however there is a minimum value that any profile has to score to be accepted.

The rationale for this is that the environment can change, but if it changes a lot, it is another environment.

New Solution

I implemented this ideas in a very small maven project for the environment detection which you can freely use in your own projects. The "profile-detector" project is independent from Spring and can be used in any Java project to detect the current environment. (just the detection part)

Additionally you will want the integration classes that enable a web application with spring framework to auto-change its configuration based on the detected environment. (the configuration part)

In the second part of this article I will tell you the details to use the project and show you the code!

I share both zips with you to use it as you like. I only ask you to respect the authorship.
Profile-detector jars and pom.
Example web-app with different configurations

No comments:

Post a Comment