I have a Spring 3.1 @Configuration
that needs a property foo
to build a bean. The property is defined in defaults.properties
but may be overridden by the property in overrides.properties
if the application has an active override
Spring profile.
Without the override, the code would look like this, and work...
@Configuration
@PropertySource("classpath:defaults.properties")
public class MyConfiguration {
@Autowired
private Environment environment;
@Bean
public Bean bean() {
...
// this.environment.getRequiredProperty("foo");
...
}
}
I would like a @PropertySource
for classpath:overrides.properties
contingent on @Profile("overrides")
. Does anyone have any ideas on how this could be achieved? Some options I've considered are a duplicate @Configuration
, but that would violate DRY, or programmatic manipulation of the ConfigurableEnvironment
, but I'm not sure where the environment.getPropertySources.addFirst()
call would go.
Placing the following in an XML configuration works if I inject the property directly with @Value
, but not when I use Environment
and the getRequiredProperty()
method.
<context:property-placeholder ignore-unresolvable="true" location="classpath:defaults.properties"/>
<beans profile="overrides">
<context:property-placeholder ignore-unresolvable="true" order="0"
location="classpath:overrides.properties"/>
</beans>
Update
If you're trying to do this now, check out Spring Boot's YAML support, particularly the 'Using YAML instead of Properties' section. The profile support there would make this question moot, but there isn't @PropertySource
support yet.
You can do:
Edit: if you need something more advanced, you can register your PropertySources on application startup.
web.xml
file you create:
Once you've done it you just need to add in your context:
I can't really answer to your question about multiple profiles but I guess you activate them on such an initializer, and you could register the appropriate PropertySource items during profile activations.
Note: This answer provides an alternate solution to using properties files with
@PropertySource
. I went this route because it was too cumbersome trying to work with multiple properties files that may each have overrides while avoiding repetitive code.Create a POJO interface for each related set of properties to define their names and types.
Implement to return the default values.
Subclass for each profile (e.g. development, production) and override any values that differ from the default. This requires a set of mutually-exclusive profiles, but you can easily add "default" as the alternative to "overrides".
Finally, autowire the properties configurations into the other configurations that need them. The advantage here is that you don't repeat any
@Bean
creation code.I am still not convinced I'll stick with this over manually configuring properties files based on the active profiles in a servlet context initializer. My thought was that doing manual configuration would not be as amenable to unit testing, but I'm not so sure now. I really prefer reading properties files to a list of property accessors.
I suggest, defining two files, where the second is optional with the profile as suffix:
Add the overriding
@PropertySource
in a static inner class. Unfortunately, you must specify all property sources together which means creating a "default" profile as the alternative to "override".I can't think of any other way than one you have suggested Emerson, which is to define this bean in a separate
@Configuration
file with an@Profile
annotation:In case you need to support multiple profiles you could do something like this:
That way you don't need to define a static configuration class for each profile. Thanks David Harkness for putting me into the right direction.