Application profiles are a powerful feature in Spring Boot that allow you to customize application behavior for different environments (e.g., development, testing, production). Instead of maintaining multiple copies of your application with different configurations, you can use profiles to switch between configurations at runtime.
What are Application Profiles?
Think of profiles as named sets of configuration properties. You define different configurations for each profile, and Spring Boot activates the appropriate profile based on the current environment. This keeps your code clean and maintainable.
Key Benefits:
- Environment-Specific Configuration: Use different database connections, logging levels, or feature flags for different environments.
- Simplified Deployment: Deploy the same artifact to different environments without modification.
- Code Reusability: Avoid duplicating code for environment-specific logic.
- Testing: Easily switch to a testing profile with mock data or different configurations.
Defining Profiles
There are several ways to define profiles in Spring Boot:
1. application-{profile}.properties or application-{profile}.yml files:
This is the most common and recommended approach. Spring Boot automatically loads properties from files matching the active profile(s).
application.properties: Default properties (used when no profile is active).application-dev.properties: Properties specific to the development environment.application-test.properties: Properties specific to the testing environment.application-prod.properties: Properties specific to the production environment.
Example (application-dev.properties):
spring.datasource.url=jdbc:h2:mem:devdb
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create
logging.level.org.springframework=DEBUG
Example (application-prod.properties):
spring.datasource.url=jdbc:mysql://your-mysql-host:3306/productiondb
spring.datasource.username=production_user
spring.datasource.password=production_password
spring.jpa.hibernate.ddl-auto=none
logging.level.org.springframework=INFO
2. @Profile Annotation:
You can use the @Profile annotation to conditionally enable or disable beans based on the active profile(s).
Example:
@Configuration
@Profile("dev")
public class DevConfiguration {
@Bean
public DataSource devDataSource() {
// Create a development-specific DataSource
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:h2:mem:devdb");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
}
@Configuration
@Profile("prod")
public class ProdConfiguration {
@Bean
public DataSource prodDataSource() {
// Create a production-specific DataSource
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://your-mysql-host:3306/productiondb");
dataSource.setUsername("production_user");
dataSource.setPassword("production_password");
return dataSource;
}
}
In this example, the DevConfiguration will only be active when the "dev" profile is active, and ProdConfiguration will be active when the "prod" profile is active. Spring will choose the appropriate DataSource bean based on the active profile.
3. Programmatically:
You can also set the active profile programmatically, though this is less common for typical deployments.
Activating Profiles
There are several ways to activate profiles:
1. spring.profiles.active Property:
- Command-line argument:
java -jar your-app.jar --spring.profiles.active=dev - Environment variable: Set the
SPRING_PROFILES_ACTIVEenvironment variable to the desired profile(s) (e.g.,SPRING_PROFILES_ACTIVE=dev). application.propertiesorapplication.yml:spring.profiles.active=dev(Not recommended for production, as it hardcodes the profile).
2. Comma-Separated Profiles:
You can activate multiple profiles by separating them with commas:
java -jar your-app.jar --spring.profiles.active=dev,debugSPRING_PROFILES_ACTIVE=dev,debug
3. Default Profile:
If no profile is explicitly activated, Spring Boot defaults to the default profile. You can define properties in application.properties or application.yml that will be used when no other profile is active.
4. Profile-Specific Configuration Files:
As mentioned earlier, Spring Boot automatically loads properties from files named application-{profile}.properties or application-{profile}.yml.
Profile Ordering and Precedence
When multiple profiles are active, Spring Boot resolves properties in the following order of precedence (highest to lowest):
- Command-line arguments
SPRING_PROFILES_ACTIVEenvironment variablespring.profiles.activeproperty inapplication.propertiesorapplication.yml- Profile-specific properties files (e.g.,
application-dev.properties) - Default properties (
application.propertiesorapplication.yml)
This means that properties defined in a command-line argument will override properties defined in a profile-specific file, and so on.
Example Scenario
Let's say you have the following files:
application.properties:server.port=8080application-dev.properties:server.port=8081application-prod.properties:server.port=8082
If you run the application with --spring.profiles.active=dev, the server will start on port 8081. If you run it with --spring.profiles.active=prod, it will start on port 8082. If you run it without any profile activation, it will start on port 8080.
Best Practices
- Use Profile-Specific Files: This is the most organized and maintainable approach.
- Avoid Hardcoding Profiles: Don't hardcode
spring.profiles.activein yourapplication.propertiesorapplication.ymlfor production deployments. Use environment variables or command-line arguments instead. - Keep Profiles Focused: Each profile should represent a specific environment or configuration scenario.
- Test Your Profiles: Ensure that your application behaves as expected in each profile.
- Consider Profile-Specific Logging: Adjust logging levels based on the active profile (e.g., DEBUG for development, INFO for production).
By leveraging application profiles, you can create flexible and maintainable Spring Boot applications that adapt to different environments without requiring code changes. This simplifies deployment and improves the overall quality of your software.