Using Profiles
Manage environment-specific configurations with Spring Profiles - development, testing, staging, and production setups
Understanding Profiles
Profile is a feature provided by Spring that represents the concept of an environment. It allows you to use a single codebase with different configurations and functionalities in different environments.
Environment-based Profiles
Git Branch-based Profiles
Activating Profiles
When starting a Spring application, you can pass in one or more environments:
-Dspring.profiles.active=test,masterIn most cases, using one environment is sufficient.
Multi-Profile Configuration in YAML
Spring Boot's support for Profiles allows configuration of each environment within a single application.yml file. Use --- as a separator between configurations:
spring:application:name: ${APP_NAME:unnamed}datasource:url: jdbc:hsqldb:file:testdb
username: sa
password:driver-class-name: org.hsqldb.jdbc.JDBCDriver
hikari:auto-commit:falseconnection-timeout:3000validation-timeout:3000max-lifetime:60000maximum-pool-size:20minimum-idle:1pebble:suffix:cache:falseserver:port: ${APP_PORT:8080}---spring:config:activate:on-profile: test
server:port:8000---spring:config:activate:on-profile: production
server:port:80pebble:cache:trueConfiguration Breakdown:
- • Default: Uses port 8080, Pebble cache disabled
- • test: Uses port 8000
- • production: Uses port 80, Pebble cache enabled
Starting with a Profile
If we start the application without specifying any profile, then the actual profile is default:
2022-11-25T11:10:34.006+08:00 INFO 13537 --- [main] c.i.learnjava.Application : No active profile set, falling back to 1 default profile: "default"To start with the test environment:
$ java-Dspring.profiles.active=test -jar springboot-profiles-1.0-SNAPSHOT.jarThe logs will show the active profile and the configured port:
2022-11-25T11:09:02.946+08:00 INFO 13510 --- [main] c.i.learnjava.Application : The following 1 profile is active: "test"
...
2022-11-25T11:09:05.124+08:00 INFO 13510 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8000 (http) with context path ''Profile-based Bean Configuration
Profiles allow you to use different implementations in different environments. For example, using file storage during development and cloud storage in production.
1. Define the Storage Interface:
publicinterfaceStorageService{// Open InputStream based on URI:InputStreamopenInputStream(String uri)throwsIOException;// Save and return URI based on extension + InputStream:Stringstore(String extName,InputStream input)throwsIOException;}Local Storage Implementation
@Component@Profile("default")publicclassLocalStorageServiceimplementsStorageService{@Value("${storage.local:/var/static}")String localStorageRootDir;finalLogger logger =LoggerFactory.getLogger(getClass());privateFile localStorageRoot;@PostConstructpublicvoidinit(){
logger.info("Initializing local storage with root dir: {}",this.localStorageRootDir);this.localStorageRoot =newFile(this.localStorageRootDir);}@OverridepublicInputStreamopenInputStream(String uri)throwsIOException{File targetFile =newFile(this.localStorageRoot, uri);returnnewBufferedInputStream(newFileInputStream(targetFile));}@OverridepublicStringstore(String extName,InputStream input)throwsIOException{String fileName =UUID.randomUUID().toString()+"."+ extName;File targetFile =newFile(this.localStorageRoot, fileName);try(OutputStream output =newBufferedOutputStream(newFileOutputStream(targetFile))){
input.transferTo(output);}return fileName;}}@Profile("default") means this implementation is enabled by default when no profile is specified.
Cloud Storage Implementation
@Component@Profile("!default")publicclassCloudStorageServiceimplementsStorageService{@Value("${storage.cloud.bucket:}")String bucket;@Value("${storage.cloud.access-key:}")String accessKey;@Value("${storage.cloud.access-secret:}")String accessSecret;finalLogger logger =LoggerFactory.getLogger(getClass());@PostConstructpublicvoidinit(){
logger.info("Initializing cloud storage...");}@OverridepublicInputStreamopenInputStream(String uri)throwsIOException{// TODO: Implement cloud storage readthrownewIOException("File not found: "+ uri);}@OverridepublicStringstore(String extName,InputStream input)throwsIOException{// TODO: Implement cloud storage writethrownewIOException("Unable to access cloud storage.");}}@Profile("!default") means this implementation is enabled when any profile OTHER than default is active (e.g., test, production).
Summary
Spring Boot allows configuration for different profiles in a single configuration file using --- separators.
Spring Boot defaults to the default profile if no profile is specified.
Use @Profile annotation to conditionally load beans based on the active profile.
Activate profiles using -Dspring.profiles.active=profileName when starting the application.