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.