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.