Using YAML Configuration Files in Spring Boot


The Scenario
Sometimes, some developers like to use Yaml property files in Spring-boot. 

This tutorial tells how: how to load properties for correct profile and  make their properties avaliable in Environment. So wen can use appContext.getEnvironment().getProperty to get property value in static or non-spring-managed context.

The implementation
EnvironmentAwarePropertySourcesPlaceholderConfigurer
First we will create EnvironmentAwarePropertySourcesPlaceholderConfigurer: we can use its addYamlPropertySource to add yaml file which will load properties defined for de the active profile and default properties.

/**
 * From http://jdpgrailsdev.github.io/blog/2014/12/30/groovy_script_spring_boot_yaml.html. This will
 * add propertySources into environment, so we can use environment().getProperty to get property
 * value in some cases.
 */
public class EnvironmentAwarePropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer
        implements EnvironmentAware, InitializingBean {

    private List<PropertySource<?>> propertySources = new ArrayList<>();
    private ConfigurableEnvironment environment;

    public EnvironmentAwarePropertySourcesPlaceholderConfigurer() {}

    /**
     * @param propertySources: order: abc-default.yaml, abc-{env}.yaml <br>
     *        This makes its usage same as org.springframework.context.annotation.PropertySource
     */
    public EnvironmentAwarePropertySourcesPlaceholderConfigurer(@Nonnull final List<PropertySource<?>> propertySources) {
        this.propertySources = propertySources;
    }

    @Override
    public void setEnvironment(final Environment environment) {
        // all subclasses extend ConfigurableEnvironment
        this.environment = (ConfigurableEnvironment) environment;
        super.setEnvironment(environment);
    }

    public EnvironmentAwarePropertySourcesPlaceholderConfigurer addYamlPropertySource(@Nonnull Resource resource)
            throws IOException {
        return addYamlPropertySource(resource.getFilename(), resource);
    }

    public EnvironmentAwarePropertySourcesPlaceholderConfigurer addYamlPropertySource(@Nonnull String name,
            @Nonnull Resource resource) throws IOException {
        YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
        // order: abc-default.yaml, abc-{env}.yaml
        PropertySource<?> defaultYamlPropertySource = loader.load(name + ".defualt", resource, null);
        propertySources.add(defaultYamlPropertySource);
        PropertySource<?> applicationYamlPropertySource =
                loader.load(name + "." + System.getProperty("env"), resource, System.getProperty("env"));
        propertySources.add(applicationYamlPropertySource);
        return this;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // This will ad it as abc-{env}.properties, abc-default.properties into
        // environment.propertySource
        // spring get value from the first propertySource which defines the property and return it.
        // check org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(String,
        // Class<T>, boolean)
        if (propertySources != null) {
            propertySources.forEach(propertySource -> environment.getPropertySources().addFirst(propertySource));
        }
    }
}
PropertySourcesPlaceholderConfigurer
Then we create static PropertySourcesPlaceholderConfigurer and load yaml files. Due to spring restriction, we can't use yaml file in @PropertySource
public static PropertySourcesPlaceholderConfigurer propertyConfig() throws IOException {
    final String password = System.getenv(ENV_APP_ENCRYPTION_PASSWORD);
    if (StringUtils.isBlank(password)) {
        return new EnvironmentAwarePropertySourcesPlaceholderConfigurer()
                .addYamlPropertySource(new ClassPathResource("cassandra.yaml")); // add more
    }
    return new EncryptedPropertySourcesPlaceholderConfigurer(password)
            .addYamlPropertySource(new ClassPathResource("cassandra.yaml"));
}
Check Spring - Encrypt Properties by Customizing PropertySourcesPlaceholderConfigurer to know more how to implement EncryptedPropertySourcesPlaceholderConfigurer. 

Resources
Leverage Spring Boot’s YAML Configuration Files in Groovy Scripts

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)