2
votes

Is it possible to leverage Spring-Boot's YAML configuration outside a spring-boot application? i.e Can we use just the YAML config feature adding the spring-boot dependency?

My usecase is a small utility project which needs configuration and YAML approach is apt. If I wire this to the master project (which is a Spring-Boot app), all is fine. But if I want to test this utility project separately (simple java-app) it doesn't get the configuration wired. Any thoughts? may be I'm missing something basic here.

Sample code snippet below. The below package is part of the component-scan.

@Component
@ConfigurationProperties(prefix="my.profile")
public class TestConfig {

    private List<String> items;

    public List<String> getItems() {
        return items;
    }

    public void setItems(List<String> items) {
        this.items = items;
    }
}

YAML Config

my:
    profile:
        items:
            - item1
            - item2
1
Yaml and @ConfigurationProperties are 2 separate things. Yaml support is available in Spring itself, @ConfigurationProperties is a feature of spring boot. - M. Deinum
However the same code which works when run as a Spring-Boot application doesn't read the yaml config when run as non-Spring Boot application. Any thoughts? - Jebuselwyn Martin
I said that yaml support is available, I didn't say it is available out-of-the-box. You would have to explicitly add the YamlPropertiesFactoryBean to have a yaml file read and to be available as properties. It is also available as of Spring 4.1 so it wouldn't work on earlier versions. - M. Deinum
Thanks for the response.. May be I should have rephrased the question a bit.. In short, the out-of-box ability by spring-boot to read & bind yml is not available for non-spring-boot applications,.. I was wondering may be there is a way to just use this one feature without running this as a spring-boot application (reason - simple,, i like Spring-boot, but not always you have flexibility to migrate everything to it). And I already looked at the YamlPropertiesFactory, and what it provides is rather primitive and doesnt exactly match with that of spring-boot out of box ability. - Jebuselwyn Martin
Then the answer is quite short and is no... You would have to use a part of spring boot and migrate that to non spring boot. - M. Deinum

1 Answers

0
votes

The key is YamlPropertiesFactoryBean, as M. Deinum mentioned.

import org.springframework.beans.factory.config.YamlProcessor;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import org.springframework.core.io.ClassPathResource;

import java.util.Properties;

public class PropertyLoader {

    private static Properties properties;
    
    private PropertyLoader() {}

    public static Properties load(String... activeProfiles) {
        if (properties == null) {
            YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
            factory.setResources(new ClassPathResource("application.yml"));
            factory.setDocumentMatchers((profile) -> YamlProcessor.MatchStatus.FOUND); // TODO filter on active profiles
            factory.afterPropertiesSet();
            
            properties = factory.getObject();
        }
        return properties;
    }

    public static <T> T value(String property, Class<T> target) {
        load();
        ConfigurationPropertySource propertySource = new MapConfigurationPropertySource(properties);
        Binder binder = new Binder(propertySource);
        return binder.bind(property.toLowerCase(), target).get();
    }
}

PropertyLoader#value can then be used like so:

List<String> items = PropertyLoader.value("my.profile.items", List.class);