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
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);