I am using annotations to configure my spring environment like this:
@Configuration ... @PropertySource("classpath:/config/default.properties") ... public class GeneralApplicationConfiguration implements WebApplicationInitializer { @Autowired Environment env; }
This leads to my properties from default.properties
being part of the Environment
. I want to use the @PropertySource
mechanism here, because it already provides the possibility to overload properties through several fallback layers and different dynamic locations, based on the environment settings (e.g. config_dir location). I just stripped the fallback to make the example easier.
However, my problem now is that I want to configure for example my datasource properties in default.properties
. You can pass the settings to the datasource without knowing in detail what settings the datasource expects using
Properties p = ... datasource.setProperties(p);
However, the problem is, the Environment
object is neither a Properties
object nor a Map
nor anything comparable. From my point of view it is simply not possible to access all values of the environment, because there is no keySet
or iterator
method or anything comparable.
Properties p <=== Environment env?
Am I missing something? Is it possible to access all entries of the Environment
object somehow? If yes, I could map the entries to a Map
or Properties
object, I could even filter or map them by prefix - create subsets as a standard java Map
... This is what I would like to do. Any suggestions?
You need something like this, maybe it can be improved. This is a first attempt:
... import org.springframework.core.env.PropertySource; import org.springframework.core.env.AbstractEnvironment; import org.springframework.core.env.Environment; import org.springframework.core.env.MapPropertySource; ... @Configuration ... @org.springframework.context.annotation.PropertySource("classpath:/config/default.properties") ... public class GeneralApplicationConfiguration implements WebApplicationInitializer { @Autowired Environment env; public void someMethod() { ... Map<String, Object> map = new HashMap(); for(Iterator it = ((AbstractEnvironment) env).getPropertySources().iterator(); it.hasNext(); ) { PropertySource propertySource = (PropertySource) it.next(); if (propertySource instanceof MapPropertySource) { map.putAll(((MapPropertySource) propertySource).getSource()); } } ... } ...
Basically, everything from the Environment that's a MapPropertySource
(and there are quite a lot of implementations) can be accessed as a Map
of properties.
This is an old question, but the accepted answer has a serious flaw. If the Spring Environment
object contains any overriding values (as described in Externalized Configuration), there is no guarantee that the map of property values it produces will match those returned from the Environment
object. I found that simply iterating through the PropertySource
s of the Environment
did not, in fact, give any overriding values. Instead it produced the original value, the one that should have been overridden.
Here is a better solution. This uses the EnumerablePropertySource
s of the Environment
to iterate through the known property names, but then reads the actual value out of the real Spring environment. This guarantees that the value is the one actually resolved by Spring, including any overriding values.
Properties props = new Properties(); MutablePropertySources propSrcs = ((AbstractEnvironment) springEnv).getPropertySources(); StreamSupport.stream(propSrcs.spliterator(), false) .filter(ps -> ps instanceof EnumerablePropertySource) .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()) .flatMap(Arrays::<String>stream) .forEach(propName -> props.setProperty(propName, springEnv.getProperty(propName)));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With