Spring Framework offers us to maintain a separate profile for each environment in order to switch over the environments with a minimal effort. Hence, our topic of discussion is โProfiles In Spring Bootโ.
For example, if we think about database URL, it will always be different in different environments. Moreover, it also allows us to map our beans to different profiles. Also, we can have control over the beans in such a way that a particular bean to bootstrap only when a particular profile is active. Similarly, some other configuration settings are environment specific that we will discuss in detail in the subsequent sections. Letโs discuss our topic โProfiles In Spring Bootโ and its related concepts step by step.
Please note that this article covers the details ofย Profiles in Spring Boot and Spring framework both. We have clearly explained the additional features of Profiles In Spring Boot in a separate section.
What is Spring Profile?
Profiles are the group of configuration properties. These configuration properties belong to a specific environment. If all the configuration properties belong to development environment, we can call it development profile. Similarly, based on the specific configuration properties it holds, we can call other profiles as test profile, prod profile etc. Spring profiles provide a way to separate out parts of our application configuration and make it be available only in the specific environment/(s).
Programmatically, a profile is a property file with extension โ.propertiesโ similar to โapplication.propertiesโ file. In spring Boot, apart from โ.propertiesโ, a profile can also have โ.ymlโ extension.
What are the usages of Profiles in Spring Based Application?
Typically, Profiles control two things in a spring based application: configuration properties, and beans.
1) Configuration Properties: Profile controls which configuration properties should be active.
2) Beans: Profile controls which beans should be loaded into the Spring Container. It offers a provision to register beans by condition.
What is the Default Profile?
Spring Boot comes with a property file, named โapplication.propertiesโ file by default. Therefore, this file is the default profile. Similarly, โapplication.ymlโ file will also be the default profile. The default profile is always active. Spring Boot loads all properties from the default profile first.
If a property is defined in theย default profile, but not in the prodย profile, the property value will be populated from theย default profile. This is very handy for defining default values that are valid across all profiles. Hence, we should keep all properties in default profile (application. properties) which are common across all profiles.
How to create a Spring Profile?
Instead of changing multiple entries in the default profile each time, we will create a separate dedicated file for each environment. Further, we can activate the required profile by changing only a single entry in the default profile.
As aforementioned, Spring Profile contains the configuration properties of a specific environment. Therefore, we need to know how many environments we have in place. Suppose we have three environments such as: development, test, and production. In this case, we need to create three profiles.
Spring Boot comes with a property file, named โapplication.propertiesโ file by default. Letโs create three more property files at the same location where โapplication.propertiesโ file resides as below.
1) application-dev.properties
2) application-test.properties
3) application-prod.properties
Please note the naming convention: application-<environment>.properties
Now, letโs insert some configuration properties in these files. For example, letโs insert database configurations which are different in each file. Assume that h2 DB in development, MySQL in test, and Oracle DB in production. We will update the entries as shown below:
application-dev.properties
app.info= This is the DEV Environment Property file spring.h2.console.enabled=true spring.h2.console.path=/h2 spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:mem:db spring.datasource.userName=sa spring.datasource.password=sa
application-test.properties
app.info= This is the TEST Environment property file spring.datasource.url=jdbc:mysql://localhost:3306/myTestDB spring.datasource.username=root spring.datasource.password=root123 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
application-prod.properties
app.message = This is the PROD Environment property file spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe spring.datasource.username=username spring.datasource.password=password spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.datasource.driver-class-name=oracle.jdbc.OracleDriver spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
How to Activate a Particular Profile?ย
Although, we have multiple ways to make a particular profile active. Letโs discuss some of them one by one.
Approach#1: By setting โspring.profile.activeโ in application.properties
The โapplication.propertiesโ file will be the boss among all the properties files. Here we will specify which profile is active by setting the value of property โspring.profiles.activeโ. For example, below โapplication.propertiesโ file tells us that currently โdevelopment (dev)โ profile is active.
application.properties
spring.application.name = Spring Profiles spring.profiles.active = dev app.info = This is the Primary Application Property file
This is the most commonly used approach of making a particular profile active.
Approach#2: By setting in JVM System Parameter
We can also pass the profile name in a JVM System parameter as below. The specified profile will be activated during application startup.
-Dspring.profiles.active=dev
Approach#3: By setting context parameter in web.xml
If you have web.xml in a web application, spring active profile can be set by specifying a context parameter as shown below:
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>dev</param-value>
</context-param>
Approach#4: By implementing WebApplicationInitializerย Interface
Programmatically, in web applications, we can configure theย ServletContextby implementing WebApplicationInitializer interface. Here, we can also set our active profiles programmatically as shown below:
@Configuration
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter( "spring.profiles.active", "dev");
}
}
Approach#5: By setting active profiles in pom.xml
We can also activate spring profile via Maven profiles by specifying the โspring.profile.activeโ property as shown below.
<profiles>
<profile>
<id>dev</id>
<activation> <activeByDefault>true</activeByDefault> </activation>
<properties> <spring.profiles.active>dev</spring.profiles.active> </properties>
</profile>
<profile>
<id>test</id>
<properties> <spring.profiles.active>test</spring.profiles.active> </properties>
</profile>
</profiles>
Priority on Using Multiple Approaches
Suppose we have used multiple approaches to set active profile in the same project, then Spring will prioritize approaches in below order.
1) By Setting a context parameter in web.xml
2) By Implementing WebApplicationInitializer Interface
3) By Setting JVM System Parameter
4) By Setting active profiles on pom.xml
How to specify all Profiles in the same application.properties file?
Instead of defining separate profiles for each environment, we can even combine all the properties in the same file and use a separator to indicate the profile. This has become possible since Spring Boot 2.4. Spring Boot has extended its support for multi-document files for properties files. This feature was already available in a YAML file. Therefore, we can specify theย dev, test,ย andย production properties in the same application.properties file as shown below:
app.info= This is the multi-document file spring.config.activate.on-profile=dev spring.h2.console.enabled=true spring.h2.console.path=/h2 spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:mem:db spring.datasource.userName=sa spring.datasource.password=sa # --- spring.config.activate.on-profile=test spring.datasource.url=jdbc:mysql://localhost:3306/myTestDB spring.datasource.username=root spring.datasource.password=root123 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect # --- spring.config.activate.on-profile=prod spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe spring.datasource.username=username spring.datasource.password=password spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.datasource.driver-class-name=oracle.jdbc.OracleDriver spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
How does Spring Container read multi-document file?
Spring Container reads this file from top to bottom order. That is, if some property, say โspring.datasource.urlโ, occurs more than once in the file, the container will consider the endmost value. In the above example, based on the endmost value, it is clear that the prod profile is active as the value of property โspring.config.activate.on-profileโ is set to โprodโ.
Note: One point to note here is that starting Spring Boot 2.4, property โspring.config.activate.on-profileโ canโt be used in combination with propertyย โspring.profiles.activeโ. On doing so, we can see a ConfigDataException.
How To Use @Profile Annotation?
By using @Profile annotation, we can make a bean belong to a particular profile. The @Profile annotation simply takes the names of one or multiple profiles. In simple words, @Profile annotation associates a bean to a particular profile. For example, letโs consider a scenario: We need a bean that should only be active during development, but not production. It will only be present in the container during development. In production, it wonโt be active. Below code demonstrates the concept:
@Profile("dev")
@Component
public class MyBeanConfig{...}
Furthermore, profile names can also be prefixed with a NOT operator, e.g., !dev, to exclude them from a profile.ย For example, the below component is activated only if devย profile is not active:
@Profile("!dev")
@Component
public class MyBeanConfig {...}
Moreover, we can also associate a bean with a particular profile via XML configuration.ย The <beans> tag has a profile attribute to specify active profiles for that bean as shown below:
<beans profile="dev">
<bean id="myBeanConfig"
class="com.dev.profiles.MyBeanConfig"/>
</beans>
Furthermore, We can also activate multiple profiles at a time by using @Profile annotation as shown below:
@Configuration
public class AppConfig {
@Profile({"prod", "dev"})
@Bean
public MyBean getBean() {
return new MyBean();
}
}
How to work with profiles using .yml?
Profiles in Spring Boot also offers to work with YAML(.yml) files. As an alternative to application.properties file, we can create application.yml file as a default profile. Like application.properties file, when application.yml file exists in the project, Spring Container will load it automatically on application startup. Further, similar to .properties file, we can create multiple profiles following the naming convention (application-<environment>.yml). However, we also have second approach to create multiple profiles in the same file using .yml. Here, we will talk about both approaches in detail step by step.
Approach#1: By Creating Separate files for each Profile
Letโs create application.yml and three profiles for development, test & production environment respectively.
application.yml
spring:
profiles: ย
active: dev
application:
name: This is default profile
app:
name: This is the Primary Application yml file
application-dev.yml
spring: profiles: dev datasource: username: sa password: sa url: jdbc:h2:mem:db driver-class-name: org.h2.Driver
application-test.ymlย
spring: profiles: test datasource: username: root password: root123 url: jdbc:mysql://localhost:3306/myTestDB driver-class-name: com.mysql.cj.jdbc.Driver
application-prod.yml
spring: profiles: prod datasource: username: username1 password: password@123 url: jdbc:oracle:thin:@localhost:1521:xe driver-class-name: oracle.jdbc.OracleDriver jpa: hibernate: ddl-auto: update show-sql: true properties: hibernate: dialect: org.hibernate.dialect.Oracle10gDialect
Approach#2: By Creating Single file for all Profiles
Create an application.yml and accommodate all the profiles in it. The first property โspring.profiles.activeโ represents the active profile. Three hyphens work as a profile separator in this file. Hence, after completion of one profile insert three hyphens as shown below.
spring: profiles: ย active: dev --- spring: profiles: dev datasource: username: sa password: sa url: jdbc:h2:mem:db driver-class-name: org.h2.Driver --- spring: profiles: test datasource: username: root password: root123 url: jdbc:mysql://localhost:3306/myTestDB driver-class-name: com.mysql.cj.jdbc.Driver --- spring: profiles: prod datasource: username: username1 password: password@123 url: jdbc:oracle:thin:@localhost:1521:xe driver-class-name: oracle.jdbc.OracleDriver jpa: hibernate: ddl-auto: update show-sql: true properties: hibernate: dialect: org.hibernate.dialect.Oracle10gDialect ---
As shown in the above example, from the first property, it is clear that โdevโ profile is active. Additionally, this single file accommodates all the profiles in it.
Profiles In Spring Boot
This section is dedicated to Profiles In Spring Boot, especially about the new features introduced in Spring Boot 2.4.
Starting Spring Boot 2.4, there are multiple changes came into the picture in the context of Profiles In Spring Boot. Letโs summarize them one by one.
1) Activation of a Specific Profile: Apart from property โspring.profiles.activeโ, a new property โspring.config.activate.on-profileโ can be used to set/activate a specific profile. However, we canโt use them together otherwise we may see ConfigDataException.
2) To activate Profiles In Spring Boot programmatically, we can also use the SpringApplication class(main class of the application) as below:
SpringApplication.setAdditionalProfiles("test");
3) In order to activate a profile in Spring Boot using pom.xml, we can specify profile names under โspring-boot-maven-pluginโ as below:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<profiles>
<profile>test</profile>
</profiles>
</configuration>
</plugin>
...
</plugins>
4) Spring Boot 2.4 has also introduced a feature called โProfile Groupsโ. Using this feature of Profiles In Spring Boot 2.4, we can group similar profiles in spring boot together. Suppose we have multiple profiles for development environment. Letโs say a โdevdbโ for the database configuration, and โdevemailโ for the email configuration. In order to activate these profiles together via โapplication.propertiesโ, we can do it as shown below.
spring.profiles.group.production=devdb,devemail
As a result, once we activate the development profile, it will activate โdevdbโ and โdevemailโ as well.
5) As aforementioned, we can even combine all the properties of multiple profiles in a single file โapplication.propertiesโ and use a separator to indicate the profile. This feature was already existing in case of YAML(application.yml) file before Spring Boot 2.4 as well.
How to check which Profile is currently Active?
We have discussed at length about creating and activating profiles in Spring Boot. Now, its time to find out how we can check which profile is currently active. Typically, there are two ways to do it. Letโs discuss them one by one.
Approach#1: Using Environment Object
We can use Javaโs Environment object as a bean via auto-wiring to get the active profile as shown below:
import org.springframework.core.env;
public class ProfileController {
@Autowired ย ย ย
private Environment env;
ย ย
public void getActiveProfiles() { ย ย ย ย ย ย
ย for (String profile : env.getActiveProfiles()) {
ย ย ย ย ย ย ย ย ย ย ย ย System.out.println("Current active profile: " + profile); ย ย ย ย ย ย ย
}ย ย ย ย ย ย
}
}
Approach#2: By injecting the property โspring.profiles.activeโ
Letโs observe the below code:
public class ProfileController {
@Value("${spring.profiles.active:}")
private String activeProfiles;
public String getActiveProfiles() {
for (String profile : activeProfiles.split(",")) {
System.out.println("Current active profile: " + profile);
}
}
}
As shown in the code above, activeProfiles variable will hold the name of the profile that is currently active, and if there are multiple, it will contain their names separated by a comma.
For more Spring Core and Spring Boot Tutorials, kindly visit Spring Boot Tutorial section.
Thats great. i never believe to find free online course like this.
Great stuff !Thanks for sharing the knowledge .really worth It.
Awesome Explanation!.