Tuesday, May 15, 2007

Configuration of Environment Settings

written by Daniel Rijkhof

I get a lot of questions asking how I deal with configuring environment specific settings. I'll explain my solution here.

The following solution depends on the Spring framework.

1) have a separate package per environment (e.g. production, test, local)
2) put a properties file in this directory (e.g. webapp.properties)
3) configure the spring context
4) set a system environment variable to choose your environment


I'll use the following packages:

com.mad.project.env.junit
com.mad.project.env.local
com.mad.project.env.test
com.mad.project.env.acceptance
com.mad.project.env.production


The webapp.properties files i'm using are simular to my junit.properties file:

hibernate.schemaUpdate=true

hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show_sql=false

dataSource.driverClassName=org.hsqldb.jdbcDriver
dataSource.url=jdbc:hsqldb:mem:test
dataSource.username=sa
dataSource.password=

webapp.logDir=../logs/junit

env.dir=junit
env.name=junit environment

Note: the env.dir line is only present in my junit env properties file.


The context:

<!-- Property Placeholder -->
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="1" />
<property name="locations">
<list>
<value>classpath:com/venspro/payment/env/junit/junit.properties</value>
<value>classpath:com/venspro/payment/env/${env.dir}/webapp.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>

<!-- Session Factory Bean -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="schemaUpdate" value="${hibernate.schemaUpdate}"/>
<property name="annotatedClasses">
<list>
...
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
<property name="dataSource" ref="dataSource" />
</bean>

<!-- Data Source Beans -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<description>Main DataSource</description>
<property name="driverClassName" value="${dataSource.driverClassName}"/>
<property name="url" value="${dataSource.url}"/>
<property name="username" value="${dataSource.username}"/>
<property name="password" value="${dataSource.password}"/>
</bean>

...



Take a close look at the propertyPlaceHolderConfigurer; there is a default configured, and one with an EL expression. If ${env.dir} is not specified, it will not find the properties file, and ignore this because of the ignoreResourceNotFound setting.

The properties in the junit.properties file, are overwritten by any settings in the next properties file.

The only thing left to do is specify the environment setting 'env.dir'. This can be done in several ways; in the servlet container configuration, or on the system environment, or as a parameter to the jvm (-Denv.dir=test).

No comments: