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
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!
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.
ReplyDelete@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();
}
}