I want to use typesafe config (HOCON config files) in my project, which facilitate easy and organized application configuration. Currently I am using normal Java properties file(application.properties) and which is difficult to handle on big project.
My project is a Spring MVC (Not a spring boot project). Is there a way to back my Spring Environment (that I am getting injected to my services) to be backed by typesafe config. Which should not brake my existing Environment usage Like @Value
annotation, @Autowired Environment
etc.
How can I do this with minimal effort and changes on my code.
This is my current solution: Looking for is there any other better way
@Configuration
public class PropertyLoader{
private static Logger logger = LoggerFactory.getLogger(PropertyLoader.class);
@Bean
@Autowired
public static PropertySourcesPlaceholderConfigurer properties(Environment env) {
PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
Config conf = ConfigFactory.load();
conf.resolve();
TypesafePropertySource propertySource = new TypesafePropertySource("hoconSource", conf);
ConfigurableEnvironment environment = (StandardEnvironment)env;
MutablePropertySources propertySources = environment.getPropertySources();
propertySources.addLast(propertySource);
pspc.setPropertySources(propertySources);
return pspc;
}
}
class TypesafePropertySource extends PropertySource<Config>{
public TypesafePropertySource(String name, Config source) {
super(name, source);
}
@Override
public Object getProperty(String name) {
return this.getSource().getAnyRef(name);
}
}
I think I came up with a slightly more idiomatic way than manually adding the PropertySource
to the property sources. Creating a PropertySourceFactory
and referencing that with @PropertySource
First, we have a TypesafeConfigPropertySource
almost identical to what you have:
public class TypesafeConfigPropertySource extends PropertySource<Config> {
public TypesafeConfigPropertySource(String name, Config source) {
super(name, source);
}
@Override
public Object getProperty(String path) {
if (source.hasPath(path)) {
return source.getAnyRef(path);
}
return null;
}
}
Next, we create a PropertySource factory that returns that property source
public class TypesafePropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
Config config = ConfigFactory.load(resource.getResource().getFilename()).resolve();
String safeName = name == null ? "typeSafe" : name;
return new TypesafeConfigPropertySource(safeName, config);
}
}
And finally, in our Configuration file, we can just reference the property source like any other PropertySource
instead of having to add the PropertySource ourselves:
@Configuration
@PropertySource(factory=TypesafePropertySourceFactory.class, value="someconfig.conf")
public class PropertyLoader {
// Nothing needed here
}