Watched the spring framework 3.1 webinar today and it was pretty interesting.
Anyway, at work we are trying to possibly load property values from a database to resolve some tension between the developers and system specialists.
I played a little bit at home as how we would set this up. This is not a new issue obviously; many have solved it previously. I did it partly as an exercise to familiarize myself with cygwin, maven and intellij as they are the new tools I will be using at my new job 🙂
The things to accomplish
- Load properties to replace placeholders in spring config from both .properties file and a database table
- The configuration table will contain properties for more than one application
- Use another .properties file to initialize the datasource for the database configuration table.
Main libraries used
- Spring (3.0.3.RELEASE)
- H2 database (1.1.118)
- Spring modules (0.8a)
- Commons-configuration (1.6)
- JUnit (4.5)
- Spring-test (3.0.3.RELEASE)
I first created a simple project via maven. I assume you have maven installed with shell/batch access.
mvn archetype:generate -B -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.0 -DgroupId=net.pureessence -DartifactId=DatabaseConfiguration -Dversion=1.0 -Dpackage=net.pureessence.example
How I wired up the configuration datasource
I created a factory to create the datasource using org.apache.commons.dbcp.BasicDataSourceFactory.createDataSource(properties) and loaded the initial datasource properties statically via the class loader. For more information on the property keys used by BasicDataSourceFactory.createDataSource, visit this test case.
public static DataSource createDataSource(String propertyFilename) throws Exception { Properties properties = new Properties(); InputStream in = PropertiesDataSourceFactory.class.getClassLoader().getResourceAsStream(propertyFilename); properties.load(in); in.close(); return BasicDataSourceFactory.createDataSource(properties); }
<bean id="dataSource" class="net.pureessence.example.PropertiesDataSourceFactory" factory-method="createDataSource"> <constructor-arg type="java.lang.String" value="databaseForConfiguration.properties" /> </bean>
How I wired up the configuration
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" p:location="classpath:env.properties" p:properties-ref="commonsConfigurationFactoryBean"/> <bean id="commonsConfigurationFactoryBean" class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean"> <constructor-arg ref="databaseConfiguration"/> </bean> <bean id="databaseConfiguration" class="org.apache.commons.configuration.DatabaseConfiguration"> <constructor-arg type="javax.sql.DataSource" ref="dataSource"/> <constructor-arg name="table" value="configuration"/><!— configuration table name —> <constructor-arg name="nameColumn" value="application"/><!— name column —> <constructor-arg name="keyColumn" value="key"/><!— key column —> <constructor-arg name="valueColumn" value="value"/><!— value column —> <constructor-arg name="name"> <util:constant static-field="net.pureessence.example.Constants.APPLICATION_ONE"/> </constructor-arg><!— name (specific configurations) —> </bean> <bean id="person" class="net.pureessence.example.Person" p:firstName="${first.name}" p:lastName="${last.name}" p:email="${email}" p:car="${car}" />
The property key “car” is loaded from env.properties while “first.name”, “last.name” and “email” properties are loaded from the database table.
Why it works
In order to load configuration/placeholders from a database table, the datasource has to be instaniated prior to the instaniation of all of the other beans with placeholders. The databsource factory creates the instance of the datasource via another properties file loaded outside of spring.
Note about the tests
The tests are set up to load the H2 database with the configuration table & data prior to the loading of the spring context in order for it to work.
Source code
It contains both intellij and eclipse project files. You should have the m2eclipse plugin for eclipse installed in order to pull down the jars in pom.xml.
»>Git Repository<«
Thanks a lot for this tutorial. This works for me. Just wanted to know if this works with @Value annotation for the properties read from database.
I tried with @Value annotation for the properties read from database… It worked… Thanks.