The Problem
After a jaunt working with Rails I'm back in Java-land. Now that I've tasted the sweet simplicity I'm jonesin' to feed it back into my Java projects.
So here's a little hack that let me apply my Rails idiom of environment/[development|test|production] to the Java world.
The Implementation
The config files
development.properties:jdbc.driverClassName=oracle.jdbc.OracleDriver
jdbc.url=jdbc:oracle:thin:@...
hibernate.dialect=org.hibernate.dialect.OracleDialect
...
test.properties:
jdbc.driverClassName=org.hsqldb.jdbcDriverSame deal with production.properties
jdbc.url=jdbc:hsqldb:mem:unittest
jdbc.username=sa
jdbc.password=
hibernate.dialect=org.hibernate.dialect.HSQLDialect
Creating the ApplicationContext
It's not a web-app so I'm doing it programatically.beanFactory = new ClassPathXmlApplicationContext(new String[] {"beans.xml"}, false);
PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
configurer.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
String environment = System.getProperty("environment", "development");
File customProperties = new File("/etc/conf/custom.properties");
configurer.setLocations(new Resource[] {new ClassPathResource(environment + ".properties"), new FileSystemResource(customProperties)});
beanFactory.addBeanFactoryPostProcessor(configurer);
beanFactory.refresh();
Unit tests
I also created a mini spring file beans-test.xml:<beans>All it does is load in my test.properties.
<bean class=\"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer\">
<property name=\"locations\">
<value>classpath:test.properties</value>
</property>
</bean>
</beans>
My test superclass
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
public abstract class TestSupport extends AbstractDependencyInjectionSpringContextTests {
public AbstractMdsIntegrationTestSupport() {
setPopulateProtectedVariables(true);
}
@Override
protected String[] getConfigLocations() {
return new String[] {"classpath:/beans-test.xml", "classpath:/beans.xml"};
}
}
Results
Now I can check out a clean codebase and run the unit tests and also fire up my application with the main() function, both from my IDE with no flag, properties file editing, etc. Then I can switch to production mode with just a -Denvironment=production.You may have caught the customProperties file, that's how I keep from having to wrangle my production passwords into the classpath or system properties.