Modification of properties in Spring PropertyPlaceholderConfigurer

A while back I was using Spring to manage my properties using the PropertyPlaceholderConfigurer and I needed to provide an interface to manipulate the properties. Normally, I would store properties in a database or in a JNDI server, but I wanted something much quicker and the problem with using the database is that some properties such as the JDBC configuration is read as properties so it was really a chicken and egg problem.

The problem with the Spring PropertyPlaceholderConfigurer is that it won’t let you modify the properties that are set when Spring initializes. I can see the reasons for this, but I needed to expose the properties, be able to set them and persist the changes if I chose to. So I ended up extending PropertyPlaceholderConfigurer.

public class ExposablePropertyPlaceholderConfigurer extends
PropertyPlaceholderConfigurer {
private Map resolvedProps;

private Resource[] locations;

@Override
protected void processProperties(
ConfigurableListableBeanFactory beanFactoryToProcess,
Properties props) throws BeansException {
super.processProperties(beanFactoryToProcess, props);
resolvedProps = new HashMap();
for (Object key : props.keySet()) {
String keyStr = key.toString();
resolvedProps.put(keyStr, parseStringValue(props
.getProperty(keyStr), props, new HashSet()));
}
}

public Map getResolvedProps() {
//return Collections.unmodifiableMap(resolvedProps); //We want to be able to dynamically set
return resolvedProps;
}

@Override
public void setLocations(Resource[] locations){

this.locations = locations;

super.setLocations(locations);

}

@Override
public void setLocation(Resource location){

//If a single location is configured, we'll need to add it to our array in
//sposition #1
this.locations[0] = location;
super.setLocation(location);

}

public Resource[] getLocations(){

return locations;

}

}

<bean id="propertyConfigurer"
class=”com.springproject.spring.ExposablePropertyPlaceholderConfigurer”>

WEB-INF/application.properties
WEB-INF/jdbc.properties
WEB-INF/mail.properties

I expose the properties as a Map for display and I also fixed it so that the map that the properties is stored into is modifiable. Now all I had to do was write some quick code to display and edit the properties in a grid and save them back to the file. Easy peasy.

I did disover something really nice about Spring properties while doing this. You can nest properties and they will process inside out. I used this technique to provide properties for each environment I am working in so that I can switch a single property to switch the environment I am working in. Let’s look at an example.

site=dev

dev.webmethodsserver=dev.mydomain.com
test.webmethodsserver=dev.mydomain.com
prod.webmethodsserver=dev.mydomain.com

<property name="wsdlDocumentUrl"
value=”http://${${dev}.webmethodsserver}/foo?WSDL” />

Spring resolved this perfectly to my satisfaction in it’s own configuration, but I had to write a little code modification in my properties mechanism to reach a property regardles of the site.

private static ExposablePropertyPlaceholderConfigurer getConfigurer(){

return (ExposablePropertyPlaceholderConfigurer)SpringLoader.getApplicationContext().getBean(BeanName.PROPERTY_CONFIGURER);

}

public static String getSite() {

return getConfigurer().getResolvedProps().get("site");

}

public static String getProperty(String key) {

return getConfigurer().getResolvedProps().get(key);

}

public static String getPropertyBySite(String key) {

String value = getConfigurer().getResolvedProps().get(getSite() + "." + key);

if (StringUtil.isEmpty(value))
value = getConfigurer().getResolvedProps().get("default." + key);
return value;
}

If I had more time or I was developing a mechanism for a newer project, I wouldn’t use this method anymore. Instead I would either create a JNDI server using spring and a file and intialize that first and use it for my properties or I would leave my jdbc properties in the properties placeholder and put my other properties in the database and read those into the Map at startup. Either way, it would be a lot more work, but would eliminate my having to change the site key on each deployment.

About Chris Hardin
Chief Architect at Doozer Software in Birmingham, Al. I specialize in Java and .NET Architecture, Ajax Frameworks and Mobile Architecture with iOS and Android.

One Response to Modification of properties in Spring PropertyPlaceholderConfigurer

  1. milus says:

    Hi

    Just to be sure: you persist all the changes of
    ExposablePropertyPlaceholderConfigurer#getResolvedProps() to one of the resources objects from ExposablePropertyPlaceholderConfigurer#getLocations(), am i right?
    To make these changes be seen by Spring itself (to resolve ${…} ), you need to restart your application, don't you?

    In your xml snippet it should be

    not http://${${dev}.webmethodsserver}

    I really like reading your blog, but as a suggestion pls use any syntax highlighter( for example http://code.google.com/p/syntaxhighlighter/) to make your code readable

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 28 other followers