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);
}
}
You create a PropertySource class as follows, it is similar to yours with the difference that you have to return the value or null and not let the lib throw a missing exception
Second step is to define a bean as follows
In cases where you want to autowire properties to other beans you need to use the annotation
@DependsOn
to the propertysource bean in order to ensure it is first loadedHope it helps
I think I came up with a slightly more idiomatic way than manually adding the
PropertySource
to the property sources. Creating aPropertySourceFactory
and referencing that with@PropertySource
First, we have a
TypesafeConfigPropertySource
almost identical to what you have:Next, we create a PropertySource factory that returns that property source
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:Laplie Anderson answer with some small improvements:
[
and:
charactersTypesafePropertySourceFactory.java
TypesafeConfigPropertySource.java
I tried all of the above and failed. One particular problem I had was initilization order of the beans. We for example needed flyway support to pick up some overriden properties which come from a typesafe config and also the same for other properties.
As suggested in one of the comments from m-deinum for us the following solutions works, also relying on the input from the other answers. By using an
ApplicationContextInitializer
when loading the main App we make sure that the props are loaded at the start of the App and merged into the "env" correctly:The
ContextInitializer
looks like this:The
PropertiesLoader
works like this to load the properties from the config and stuff it into the environment:And we also need the
TypesafeConfigPropertySource
which works for the typesafe config: