Spring: profiles or not profiles?
I’m a big user of Spring, and I must confess I didn’t follow all the latest additions of version 3.1. One such addition is the notion of profile.
Profiles are meant to address the case when you use the same Spring configuration across all your needs, but when there are tiny differences. The most frequent use-case encountered is the datasource. For example, during my integration tests, I’m using no application server so my datasource comes from a simple
org.apache.commons.dbcp.BasicDataSource configured with URL, driver class name, user and password like so:
Note there are other alternatives to
BasicDataSource, such as
In an application server environment, I use another bean definition:
You probably noticed both previous bean definitions have the same name. Keep it in mind, it will play a role in the next section.
My legacy solution
In order to be able to switch from one bean to another in regard to the context, I use the following solution:
- I separate the datasource bean definition in its own Spring configuration file (respectively spring-datasource-it.xml and spring-datasource.xml)
- For production code, I create a main Spring configuration file that imports the latter:
- For integration testing, I use a Spring Test class as parent (like
AbstractTestNGSpringContextTests) and configure it with the
@ContextConfigurationhas a location
attributethat can be set with the location of all needed Spring configuration fragments for my integration test to run.
Besides, as a Maven user, I can neatly store the spring-datasource.xml file under
src/main/resources and the spring-datasource-it.xml file under
src/test/resources, or in separate modules. Given these, the final artifact only contains the relevant application server datasource bean in my Spring configuration: the basic datapool safely stays in my test code.
The profile solution
Remember when bean identifiers had to be unique across your entire Spring configuration, this is the case no more. With profiles, each bean (or more precisely beans group) can be added an extra profile information so that bean identifiers have to be unique across a profile. This means that we can define two beans with the
datasource identifier, and set a profile for each: Spring won’t complain. If we call those profiles
application-server, and activate those in the code when needed, this will have exactly the same results. The Spring configuration file will look like this:
Now, the Spring configuration file contains both contexts.
I’m not entirely sure that such a use of profiles brings anything to the table (despite the datasource example being depicted everywhere on the web). Granted, we switched from a build-time configuration to a runtime configuration. But the only consequence I see is that the final artifacts ships with information irrelevant to the environment: it’s bad practice at best, and at worst a security flaw.
Other use-cases could include the need to run the application both on an application server and in the cloud. Even then, I would be a in favor of distinct configuration files assembled at build time. I think I will stay with my legacy approach for the moment, at least until I’m proven wrong or until a case presents itself that can easily be solved by profiles without side-effects.