by BehindJava

What is Externalized configuration and Spring Profiling in Spring Boot

Home » springboot » What is Externalized configuration and Spring Profiling in Spring Boot

In this tutorial we are going to learn about Externalized configuration or Spring Profiling in Spring Boot with an example.

Externalized Configuration

Spring Boot lets you externalize your configuration so that you can work with the same application code in different environments. You can use properties files, YAML files, environment variables, and command-line arguments to externalize configuration. Property values can be injected directly into your beans by using the @Value annotation, accessed through Spring’s Environment abstraction, or be bound to structured objects through @ConfigurationProperties.

What Are Profiles?

Every enterprise application has many environments, like:

Dev | Test | Stage | Prod | UAT / Pre-Prod

Each environment requires a setting that is specific to them. For example, in DEV, we do not need to constantly check database consistency. Whereas in TEST and STAGE, we need to. These environments host specific configurations called Profiles.

How Do we Maintain Profiles?

This is simple — properties files! We make properties files for each environment and set the profile in the application accordingly, so it will pick the respective properties file. Don’t worry, we will see how to set it up.

Let’s start with setting up a Spring Boot application from the Spring Starter.

In this demo application, we will see how to configure different databases and port numbers at runtime based on the specific environment by their respective profiles.

As the DB connection and port number is better to be kept in a property file, it remains external to an application and can be changed. We will do so here. But, Spring Boot — by default — provides just one property file ( application.properties). So, how will we segregate the properties based on the environment?

The solution would be to create more property files and add the “profile” name as the suffix and configure Spring Boot to pick the appropriate properties based on the profile.

Then, we need to create three application.properties:

  1. application-dev.properties
  2. application-test.properties
  3. application-prod.properties

Of course, the application.properties will remain as a master properties file, but if we override any key in the profile-specific file, the latter will gain precedence.

I will now define DB configuration properties for in respective properties file and add code in DBConfiguration.class to pick the appropriate settings.

Here is the base application.properties:

spring.profiles.active=dev

spring.application.name=employeeservice

app.message=This is the primary Application Property for ${spring.application.name} 

In DEV, we will use an different port number:

#DEV ENVIRONEMNT SETTING#

app.message= This is the property file for the ${spring.application.name} specific to DEV Environment

server.port=8082

spring.datasource.url=jdbc:mysql://localhost:3306/hclDEV
spring.datasource.username=root
spring.datasource.password=root123
spring.jpa.hibernate.ddl-auto=update

## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

In TEST, we will be using a different port number.

#TEST ENVIRONEMNT SETTING#

app.message= This is the property file for the ${spring.application.name} specific to TEST Environment

server.port=8084

spring.datasource.url=jdbc:mysql://localhost:3306/hclTEST
spring.datasource.username=root
spring.datasource.password=root123

In PROD, we will be using a different port number.

#PROD ENVIRONEMNT SETTING#

app.message= This is the property file for the ${spring.application.name} specific to PRODUCTION Environment!! Be ALERT!! 

server.port=8083

spring.datasource.url=jdbc:mysql://localhost:3306/hclPROD
spring.datasource.username=root
spring.datasource.password=root123

Now, we are done with properties files. Let’s configure in the DatabaseConfiguration.class to pick the correct one.

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration
@ConfigurationProperties("spring.datasource")
public class DatabaseConfiguration {

	private String url;
	private String username;
	private String password;

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Profile("dev")
	@Bean
	public String devDatabaseConnection() {
		System.out.println("DB connection to DEV");
		System.out.println(url);
		return "DB connection for DEV - H2";
	}

	@Profile("test")
	@Bean
	public String testDatabaseConnection() {
		System.out.println("DB Connection to TEST");
		System.out.println(url);
		return "DB Connection to TEST";
	}

	@Profile("prod")
	@Bean
	public String prodDatabaseConnection() {
		System.out.println("DB Connection to PROD");
		System.out.println(url);
		return "DB Connection to PROD";
	}

}

We have used the @Profile(“Dev”) to let the system know that this is the BEAN that should be picked up when we set the application profile to DEV. The other two beans will not be created at all.

One last setting is how to let the system know that this is DEV, TEST, or PROD. But, how do we do this?

We will use the application.properties to use the key below:

spring.profiles.active=dev

From here, Spring Boot will know which profile to pick. Let’s run the application now!

With the profile in DEV mode, and it should on port number 8082.

tt

Now, change the profile to PROD. and it will run on an different port number i.e., 8083.

tt

That’s it! We just have to change it once at the application.properties to let Spring Boot know which environment the code is deployed in, and it will do the magic with the setting.