Thursday, October 20, 2011

Spring 3.1 @Profile and @PropertySource

Today, I'd like to go over a cool new feature that the good folks at Spring are releasing as part of Spring 3.1...Profiles.

I won't go into too much detail about how profiles work because SpringSource's Chris Beams has already done a good job of that already -> Read about it here

Instead, I'd like to take on a very simple use case where this feature will be VERY helpful. Most developers have run into a scenario where they needed to bootstrap their application with beans that are slightly different based on the environment. For example, a datasource might be different for dev, test and prod. With the help of Spring @Profile and the @Configuration classes, this is a complete snap to do now. Let's dive into the example.

My project has two beans: CommonBean which is the same for all environments, and EnvBean which has environment specific configuration (in the real world, EnvBean could be a datasource, jms connectivity beans, etc..). The last wrinkle to this app is that my EnvBean requires environment specific properties as well. A very simple use-case, but complete enough to demo the new capabilities.

Here's the source for my application beans:

You see they are simple Java POJOs. Now, I create a per environment properties file for dev, test and prod with the properties, I am calling them -app.properties.

Now here's where @Profile comes into the picture. To distinguish the various environments, I create a common @Configuration class called AppBootstrap and a per environment @Configuration class to configure the EnvBean.

That's it. Now my app is configured to have a different configuration PER environment. So I can run a test to prove this out:

Voila! With each run*Example() test you will notice that the appropriate @Profile was invoked and the environment specific properties file was used to configure my EnvBean.

Pretty slick new feature from the guys at Spring! Did I mention, this whole thing was done with NO SPRING XML!!!

If you want the source for this, you can grab it from Bitbucket => click here

More to come and as always, I hope this helps! Cheers!

1 comment:

  1. Your article help me a lot. I wanted to do what you have but also use variable replacements inside @Value annotations. To get this working it wasn't obvious how this works but the magic was to include a static Bean definition in each file that uses @PropertySource. I thought it was only needed once somewhere in your app but it appears that you need to define it in each file using @PropertySource so that it gets created prior to the BFPP kicking in.


    @Configuration
    @Profile(value="PROD")
    @PropertySource("classpath:/prod-app.properties")
    public class ProdEnvConfig {

    @Value("${service.message}")
    private String serviceMessage;

    @Bean
    public EnvBean simpleBean(){
    EnvBean bean = new EnvBean(serviceMessage);
    return bean;
    }

    /**
    * This is the magic that enables variable replacements in @Value definitions
    */
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
    }
    }

    ReplyDelete