Technology: Spring Profiles provides a way to isolates the parts of application configuration, it will make available only in certain environments. It is mainly useful it wants to load spring beans based on environment configuration, for example if the operating system is windows we can load some specific spring beans, if it is other than load different spring beans. One more scenario where spring profiles widely used, like for QA environment we will use some database which is hosted locally, for UAT we will use some different host database, for production it will vary, in this scenario`s we will create separate beans for QA, UAT and production, based on spring active profile the corresponding bean will be loaded.
Using this without modifying the source code/configuration it will work for all three environments.
If we use Spring Boot we can also load properties based profile, like application-${env}.yml file is loaded, where ${env} is the spring active profile.
Note:
- Spring has supported @Profile annotation from 3.1 version onwards.
- spring-context-{version}.jar must be present in application libraries.
Creating Profiles:
Spring provides @Profile annotation to mark the spring bean to create a profile, and this annotation should be used with @Configuration or Spring stereotypes such as @Component, @Service, @Controller and @Repository.
Example:
@Component @Profile("dev") public class DevDatasourceConfig { }
If we want to exclude a spring bean for a particular profile then we can use ‘!’ operator in profile value.
@Component
@Profile("!dev")
public class DevDatasourceConfig {}
Specifying Profile using XML Configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd" profile="dev">
<bean id="devDatasourceConfig" class="org.examples.profiles.DevDatasourceConfig" />
</beans>
Using XML configuration, we can only profile at beans level, not on individual bean level.
Activating Spring Profiles:
In this section we will learn how to activate profiles so that it will register in spring container.
This can be done in multiple ways:
1) Specifying Context-param in web.xml file:
We can use spring.profiles.active context-param to set active profile(s), this is only valid for web based applications.
2) Using JVM System Parameter:
We can pass the command line spring.profiles.active argument with comma separated profiles to set active profiles.
-Dspring.profiles.active=dev
3) Environment Variable:
We can create spring.profiles.active environment variable with comma separated profiles to set active profiles for an application.
4) Using Properties/yml files:
If we are using spring boot type of applications then we can specify spring.profiles.active property in application.properties or any properties file which is loaded in application.
5) We can use Servlet 3.0 features to set spring active profiles.
a. WebApplicationInitializer: It is the interface provided by spring MVC to configure ServletContext programmatically, we can set spring.profiles.active param to servletContext to register profile based beans.
@Configuration
public class ProfileWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("spring.profiles.active", "dev");
}
}
b. We can also use ServletContainerInitializer interface provided by Servlet 3.0 to set profiles.
public class WebMVCApplicationInitializer implements ServletContainerInitializer
{
@Override
public void onStartup(Set<Class<?>> aC, ServletContext aCtx) throws ServletException
{
aCtx.setInitParameter("spring.profiles.active", "dev");
}
}
And create javax.servlet.ServletContainerInitializer file under META-INF\services folder and write the implemented class into the file.
6) Setting Profiles for test Environment.
Tests make it very easy to specify what profiles are active – using the @ActiveProfile annotation to enable specific profiles
@ActiveProfiles("dev")
If we won`t specify any profile means it belongs to default profile.
Spring also provides the default profile when any other profiles are active using “spring.profiles.default” property.
There are multiple ways to set spring active profile, but if we specify more than one way, we need to know the order of the lookup for spring profiles, below is the lookup order.
1) Context parameter in web.xml
2) WebApplicationInitializer
3) JVM System parameter
4) Environment variable
Getting the Spring Active Profile during Runtime:
For getting current active profile runtime we need to inject/autowire Environment type of bean and call getActiveProfiles() on that to get profiles.
for (final String profileName : environment.getActiveProfiles()) {
System.out.println("Currently active profile - " + profileName);
}
Including Active Profiles:
Spring boot can include a common set of profiles for every active profiles. We can configure spring.profiles.include property in our property file. Now whenever we add active profile using spring.profiles.active then by default profiles configured by spring.profiles.include will also be added.
Conclusion:
In this blog we learned how to define a profile, how to enable right profile into our Java application development based on conditions.
And also we learned how to include profile always using spring.profiles.active property.