The road so far….

November 22, 2010

Mixed approach of loading java.util.Properties using Spring

Filed under: java — Tags: — Rahul Sharma @ 8:05 pm

Last week  I was attending a training where we were developing  a command line application. The application had  few static properties that were stored in a properties file and few of them where supposed to be generated when the application would start.  The application was using Spring, so loading the Properties file was a simple use case of using PropertiesPlaceholderConfigurer but the complication came from, how to load the properties  that were generated when the application started ?

Solution One:

The solution that we adopted at that point was to have a dummy file in the classpath for the generated properties.  This file name was appended in the  PropertiesPlaceholderConfigurer locations property.  Every time the application starts it generates the properties and save them to the specific file in the classpath before loading the Spring application context.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:props-app.xml")
public class LoadedPropertiesTest {
	private static String generatedValue;
	@Resource
	String propertyValue;

	@BeforeClass
	public static void generateString() throws Exception {
		generatedValue = "Test-TimeStamp-" + System.currentTimeMillis();
		Properties properties = new Properties();
		properties.put("app.propertyOne", generatedValue);
		FileOutputStream fileOutputStream = new FileOutputStream(
				"target/classes/generated-app.properties");
		properties.store(fileOutputStream,
				"generated propeties");
		fileOutputStream.close();

	}

	@Test
	public void contextShouldLoadPropertiesGeneratedAtRuntime()
			throws Exception {
		assertEquals(generatedValue, propertyValue);

	}
}
    <bean id="applicationProperties"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:application.properties</value>
				<value>classpath*:generated-app.properties</value>
			</list>
		</property>
	</bean>

	<bean id="suppledValue" class="java.lang.String">
		<constructor-arg value="${app.propertyOne}"></constructor-arg>
	</bean>

This solution works but it has a problem, every time the application stores properties to a file in the classpath i.e. a file in the jar, this can be sufficient for a training/test application but not for an otherwise  useful application. We can avoid this, by writing this file to some external directory but the point is, if the application generates properties every time why should we even try to save them at all ?

Solution Two:

I did not want to store the properties in a file and the PropertyPlaceholderConfigurer is capable enough to cater to such a situation.

The properties are generated before the spring application context has been loaded so I could use the FactoryMethod of  Spring to inject these in the context. Then I injected these properties in the PropetyPlaceholderConfigurer in the properties field along with the already specified locations field. The  only thing that is required is tweaking the localOverride field. This is a boolean property and if set to true, then if there is a property that has values in both the cases i.e. there is a key-value in a file and the same key is also injected in the properties supplied then the value of the supplied property will override that of the file else not.

	<bean id="applicationProperties"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
		p:locations="classpath:application.properties" p:localOverride="true"
		p:properties-ref="suppliedProperties">
	</bean>

	<bean id="suppliedProperties" class="info.rahul.LoadedPropertiesTest"
		factory-method="getGeneratedProperties"></bean>

	<bean id="suppledValue" class="java.lang.String">
		<constructor-arg value="${app.propertyOne}"></constructor-arg>
	</bean>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:props-app.xml")
public class LoadedPropertiesTest {
	private static String generatedValue;
	@Resource
	String propertyValue;

	@BeforeClass
	public static void generateString() {
		generatedValue = "Test-TimeStamp-" + System.currentTimeMillis();
	}

	public static Properties getGeneratedProperties() {
		Properties properties = new Properties();
		properties.put("app.propertyOne", generatedValue);
		return properties;
	}

	@Test
	public void contextShouldLoadPropertiesGeneratedAtRuntime() {
		assertEquals(generatedValue, propertyValue);
	}
}
Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

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 )

Google+ photo

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

Connecting to %s

%d bloggers like this: