Assume there are two applications "foo" and "bar", both have dependency "core", I want extract the common properties for better maintainability. current:
--- #application.yml from foo
spring.application.name: foo
spring.datasource.url: jdbc:mysql://${mysql.host}:${mysql.port}/${spring.application.name}
mysql:
host: localhost
port: 3306
--- #application.yml from bar
spring.application.name: bar
spring.datasource.url: jdbc:mysql://${mysql.host}:${mysql.port}/${spring.application.name}
mysql:
host: localhost
port: 3306
expected:
--- #default.yml from core
spring.application.name: bar
spring.datasource.url: jdbc:mysql://${mysql.host}:${mysql.port}/${spring.application.name}
mysql:
host: localhost
port: 3306
--- #application.yml from foo
spring.application.name: foo
--- #application.yml from bar
spring.application.name: bar
above default.yml should override spring boot (including devtools) defaults and could be overridden by application.yaml
My solution:
public class DefaultPropertiesPostProcessor implements EnvironmentPostProcessor, Ordered {
private static final String FILE_NAME = "default.yml";
public static final int ORDER = Ordered.HIGHEST_PRECEDENCE + 11; // after ConfigDataEnvironmentPostProcessor
@Override
public int getOrder() {
return ORDER;
}
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
try {
List<PropertySource<?>> list = new YamlPropertySourceLoader()
.load(FILE_NAME, new ClassPathResource(FILE_NAME)).stream().filter(ps -> {
String onProfile = (String) ps.getProperty("spring.config.activate.on-profile");
return onProfile == null || environment.acceptsProfiles(Profiles.of(onProfile));
}).collect(Collectors.toList());
Collections.reverse(list);
list.forEach(environment.getPropertySources()::addLast);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
I'm not sure it's the best practice, I wish spring boot will provide equivalent.
Comment From: quaff
It's a little similar to DefaultPropertiesPropertySource
https://github.com/spring-projects/spring-boot/blob/f798f26596e38d325cc5eeea44a31aabbca5617c/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L1066-L1085
but has some major differences:
1. It auto configured by applications, SpringApplication.setDefaultProperties() need be called in each application main method.
2. It provide the same experience as ConfigDataEnvironmentPostProcessor, properties can be externalized to yaml, and multiple document supported base on spring.config.activate.on-profile.
3. It should added right after ConfigDataEnvironmentPostProcessor and before any others default sources provide by libraries such as DevToolsPropertyDefaultsPostProcessor and DevToolsHomePropertiesPostProcessor, DefaultPropertiesPropertySource cannot override devtools properties.
Would you take a look at this ? @philwebb
Comment From: wilkinsona
This looks to be a duplicate of #24688.