Mastering Spring Boot Profiles for Different Environments

Naveen Metta
4 min readJun 9, 2024

--

credit goes to the owner : http://websystique.com/spring/spring-profile-example/
source : websystique.com

In modern software development, managing different environments — such as development, testing, and production — is crucial for a smooth workflow. Spring Boot profiles provide a powerful way to handle this. Let’s dive into how you can effectively use Spring Boot profiles to manage your application’s configurations for various environments.

What Are Spring Boot Profiles?

Spring Boot profiles allow you to define different configurations for different environments. For instance, you can have one set of configurations for development and another for production. This feature helps in maintaining clean and environment-specific settings without hardcoding them into the application.

Setting Up Spring Boot Profiles

To start with Spring Boot profiles, you need to define profile-specific properties files. These files are typically named application-{profile}.properties or application-{profile}.yml.

Example Configuration Files

application.properties:

spring.application.name=MyApp
server.port=8080

application-dev.properties:

spring.profiles.active=dev
server.port=8081
logging.level.org.springframework=DEBUG

application-prod.properties:

spring.profiles.active=prod
server.port=8082
logging.level.org.springframework=ERROR

Activating Profiles

You can activate profiles in several ways:

  1. Command Line:
java -jar myapp.jar --spring.profiles.active=dev

Programmatically:

public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplication.class);
app.setAdditionalProfiles("dev");
app.run(args);
}

Application Properties:

spring.profiles.active=dev

Using Profiles in Code

You can use @Profile annotation to mark beans as being profile-specific.

@Configuration
public class AppConfig {

@Bean
@Profile("dev")
public DataSource devDataSource() {
// Return dev-specific DataSource
}

@Bean
@Profile("prod")
public DataSource prodDataSource() {
// Return prod-specific DataSource
}
}

Example: Switching DataSource Based on Profile

Suppose you want to use an H2 database in development and a MySQL database in production.

application-dev.properties:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password

application-prod.properties:

spring.datasource.url=jdbc:mysql://localhost:3306/proddb
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=secret

DataSource Configuration:

@Configuration
public class DataSourceConfig {

@Bean
@Profile("dev")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource devDataSource() {
return DataSourceBuilder.create().build();
}

@Bean
@Profile("prod")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource prodDataSource() {
return DataSourceBuilder.create().build();
}
}

Testing with Spring Boot Profiles

Testing often requires a separate configuration. Spring Boot allows you to specify profiles for tests using the @ActiveProfiles annotation.

application-test.properties:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password

Test Class:

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
public class MyServiceTest {

@Autowired
private MyService myService;

@Test
public void testServiceMethod() {
// Test logic here
}
}

Real-World Usage of Spring Boot Profiles

In a real-world scenario, you might have multiple environments beyond just development and production. Let’s consider a scenario with three environments: dev, staging, and prod.

application-staging.properties:

spring.profiles.active=staging
server.port=8083
logging.level.org.springframework=INFO
spring.datasource.url=jdbc:mysql://staging-server:3306/stagingdb
spring.datasource.username=staginguser
spring.datasource.password=stagingpass

Conditional Beans with Profiles

You can also conditionally create beans based on the active profile.

Conditional Bean Creation:

@Configuration
public class MessageConfig {

@Bean
@Profile("dev")
public MessageService devMessageService() {
return new DevMessageService();
}

@Bean
@Profile("prod")
public MessageService prodMessageService() {
return new ProdMessageService();
}
}

Environment-Specific Controllers

You can create environment-specific controllers by using the @Profile annotation.

@RestController
@Profile("dev")
public class DevController {

@GetMapping("/dev-endpoint")
public String devEndpoint() {
return "This is the development endpoint";
}
}

@RestController
@Profile("prod")
public class ProdController {

@GetMapping("/prod-endpoint")
public String prodEndpoint() {
return "This is the production endpoint";
}
}

Handling Environment-Specific Configuration in Build Tools

You can also manage profiles using build tools like Maven and Gradle.

Maven Configuration

In Maven, you can define profiles in the pom.xml file:

pom.xml:

<profiles>
<profile>
<id>dev</id>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.profiles.active>prod</spring.profiles.active>
</properties>
</profile>
</profiles>

Activate a profile using Maven command:

mvn spring-boot:run -Pdev

Gradle Configuration

In Gradle, you can define profiles in build.gradle:

build.gradle:

bootRun {
if (project.hasProperty('profile')) {
systemProperty 'spring.profiles.active', profile
}
}

Run the application with a specific profile:

gradle bootRun -Pprofile=dev

Externalizing Configuration

Spring Boot supports externalizing configuration, which means you can load your properties files from external sources. This is particularly useful in cloud environments.

External Configuration Locations

You can specify external locations for configuration files using the spring.config.location parameter.

Example Command:

java -jar myapp.jar --spring.config.location=/path/to/config/

Spring Cloud Config

For managing configurations across multiple services, Spring Cloud Config provides a server and client architecture.

Config Server:

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}

Config Client:

spring.cloud.config.uri=http://localhost:8888
spring.application.name=myapp

Advanced Profile Management

Spring Boot also supports profile groups, which allows you to activate multiple profiles at once.

Profile Group Example:

spring.profiles.group.dev.includes=debug,dev-datasource

Using Profiles in Spring Boot Actuator

Spring Boot Actuator provides a way to monitor and manage your application. You can include profile information in Actuator endpoints.

application.properties:

management.endpoints.web.exposure.include=*
management.endpoint.env.show-values=WHEN_AUTHORIZED

Access the profile information:

curl -u user:password http://localhost:8080/actuator/env

Conclusion

Using Spring Boot profiles allows you to maintain clean and manageable configuration settings tailored for different environments. By defining profile-specific properties files and using the @Profile annotation, you can easily switch configurations and beans based on the environment, ensuring your application behaves correctly in development, testing, and production stages.

Profiles offer flexibility and control over your application’s configurations, enabling you to handle complex deployment scenarios seamlessly. Remember to keep your configurations organized and avoid hardcoding environment-specific details in your codebase. Profiles provide a powerful way to manage your application’s environments, enhancing maintainability and reducing the risk of configuration-related errors.

By mastering Spring Boot profiles, you’ll be better equipped to handle complex deployment scenarios and ensure your application runs smoothly across all environments. Happy coding!

--

--

Naveen Metta

I'm a Full Stack Developer with 2.5 years of experience. feel free to reach out for any help : mettanaveen701@gmail.com