Profiles In Spring Boot java Spring Spring Boot by devs5003 - April 10, 2024April 11, 20244 When we work on a real time project, we maintain multiple environment for the same project. This happens because we use different infrastructures for different stages of the project. There are different useful environments that we maintain before making the project go live, such as: development (DEV), test, user acceptance testing (UAT), production (PROD). These environments are not fixed at all. Some projects may have some more environments or even sometimes less also. It totally depends on the decisions made by stakeholders involved in the specific project and its requirements. 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. Table of Contents Toggle What is Spring Profile?What are the usages of Profiles in Spring Based Application?What is the Default Profile?How to create a Spring Profile?application-dev.propertiesapplication-test.propertiesapplication-prod.propertiesHow to Activate a Particular Profile? Approach#1: By setting ‘spring.profile.active’ in application.propertiesApproach#2: By setting in JVM System ParameterApproach#3: By setting context parameter in web.xmlApproach#4: By implementing WebApplicationInitializer InterfaceApproach#5: By setting active profiles in pom.xmlPriority on Using Multiple ApproachesHow to specify all Profiles in the same application.properties file?How does Spring Container read multi-document file?How To Use @Profile Annotation?How to work with profiles using .yml?Approach#1: By Creating Separate files for each ProfileApproach#2: By Creating Single file for all ProfilesProfiles In Spring BootHow to check which Profile is currently Active?Approach#1: Using Environment ObjectApproach#2: By injecting the property ‘spring.profiles.active’ 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 particular 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 If we don’t implement profiles, we will have to accommodate all the above entries in a single file ‘application.properties’. Further, if we want to switch over to different profile, we will have to make many changes every time. Hence, maintaining a separate profile for each environment saves a lot of effort. 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 represents 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 In the preceding code, the value of ‘spring.profiles.active’ property tells Spring which profile to use. Here we have set the dev profile as active. 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 ServletContext by 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 Furthermore, we can 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. Related