2

I'm trying to port our Custom Properties Placeholder with Spring's new Environment support but I can't figure out how to get what our current placeholder magic does.

What I would like is for a default bunch of property files to be read from classpath and then have those properties overridden (overlay) by a bunch of properties files from somewhere else. I don't want all of the properties replaced just the ones that are set in the other group of files.

Prior to Spring 3.1

<bean class="com.snaphop.spring.ConfigResourcesFactoryBean" id="customConfig">
    <property name="parameterName" value="customConfig"/>
    <property name="defaultResources" value="classpath*:META-INF/spring/*.properties"/>
</bean>

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="customPropertyPlaceholder">
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
    <property name="locations" ref="customConfig"/>
</bean>

Now ConfigResourcesFactoryBean is just a magically FactoryBean that finds the list of resources to feed to the placeholder config:

public class ConfigResourcesFactoryBean implements FactoryBean<Resource[]> {
// Loads a bunch of Resources (property files) 
// based on System.property/Environment variable "customConfig"
}

Now customConfig might be set like -DcustomConfig=file://blah/*.properties or export customConfig=file://blah/*.properties.

The properties in the directory blah only override a subset of the classpath*:META-INF/spring/*.properties. Thus the returned Resource[] from the factory will be a union of classpath*:META-INF/spring*.properties followed by file://blah/*.properties respectively.

Now it appears instead of my Resource[] factory I can make a custom PropertySources and wire that into the PlaceholderConfig but that seems like it offers no value then the above.

I cannot use ApplicationContextInitializer because I swear that only works with Servlet environments and thus will not work with integration tests (I don't feel like adding an annotation on every single one of my unit tests to go tell it what the environment is when I could just set a system property like I did before).

How does one overlay properties from hardcoded sources with custom sources with out having to overriding/implementing a bunch of classes?

Adam Gent
  • 47,843
  • 23
  • 153
  • 203
  • Somewhat similar: http://stackoverflow.com/questions/8587489/how-to-set-active-spring-3-1-environment-profile-via-a-properites-file-and-not-v – Adam Gent Nov 12 '12 at 23:33

1 Answers1

0

Overtime I slowly ported my original configuration resolution code to the new Spring Environment way of doing things.

I talk about it at this StackOverflow Question: How can I easily switch between environment specific runtime configuration with IntelliJ?

You can see the code as a Gist and use the same configuration logic I use for most of my Spring Projects.

For Unit testing sadly the Context Initializer will really only work with Spring 3.2. See the updated @ContextConfiguration Annotation. I had to use my old custom properties placeholder for projects using Spring 3.1 and older.

Community
  • 1
  • 1
Adam Gent
  • 47,843
  • 23
  • 153
  • 203