Spring supports profile specific application properties via a file naming convention:
- Profile specific application properties outside your jar (application-{profile}.properties or application-{profile}.yml)
- Profile specific application properties packaged in your jar (application-{profile}.properties or application-{profile}.yml)
If you’re using YAML, then you can also use profile documents inside the YAML file. Let’s take a closer look using the CommandLineRunner from last week’s post Externalized Configuration in Spring
@SpringBootApplication
public class Application implements CommandLineRunner {
@Value("${myApp.name}")
private String name;
@Value("${myApp.primary}")
private String primary = "foo";
@Value("${myApp.secondary}")
private String secondary = "foo";
private static final Logger log = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) throws Exception {
final SpringApplication app = new SpringApplicationBuilder(Application.class)
.properties("spring.config.name=myApp")
.build();
app.run();
}
public void run(String ... strings)
throws Exception
{
log.warn("name\t {}", name);
log.warn("primary\t {}", primary);
log.warn("secondary\t {}", secondary);
}
}
A YAML file is actually a sequence of documents separated by --- lines, and Spring parses each document separately to a flattened map. If a YAML document contains a spring.profiles key, then that value controls whether that document is included in the final merge.
Let’s take a look at an example. Here is the file packaged in my jar:
myApp:
name: Package Default
primary: Package Default
secondary: Package Default
---
spring.profiles: one
myApp:
name: Package 1
---
spring.profiles: two
myApp:
name: Package 22
primary: Package 22
---
spring.profiles: three
myApp:
primary: Package 333
secondary: Package 333
With no active profile, we get the values from the first document.
$ java -jar target/application-config-0.1.0.jar
WARN [main] name Package Default
WARN [main] primary Package Default
WARN [main] secondary Package Default
Set one as the active profile, to merge the first document with the document containing spring.profiles: one:
$ (export SPRING_PROFILES_ACTIVE=one ; java -jar target/application-config-0.1.0.jar)
WARN [main] name Package 1
WARN [main] primary Package Default
WARN [main] secondary Package Default
Set two,three as the active profiles, to merge the first document with the documents containing spring.profiles: two, spring.profiles: three:
$ (export SPRING_PROFILES_ACTIVE=two,three ; java -jar target/application-config-0.1.0.jar)
WARN [main] name Package 22
WARN [main] primary Package 333
WARN [main] secondary Package 333
And finally, add a local myApp.yml that sets the active profile. The merge order is:
- packaged default document
- local default document
- active profile document
$ cat myApp.yml
spring.profiles.active: one
myApp:
name: Local
secondary: Local
$ java -jar target/application-config-0.1.0.jar
WARN [main] name Package 1
WARN [main] primary Package Default
WARN [main] secondary Local