View Full Version : Environment sensitive Spring wiring
ggerard
Aug 31st, 2004, 04:32 AM
Currently I have the same webapp codebase deployed multiple times. The name of the webapp is used to drive customer specific things like where to find data files, database connections, etc. The nice part about this is bring a new customer up is as simple as copying the webapp directory and only if the defaults aren't right would I provide something more specific (again, using the context name to find). If the non-servelet container specific code is run outside of the webapp, I use a Java System.property as a surrogate.
I'd like to use Spring to control all my JDBC settings for now and other stuff later.
What's the best way to do this? I like the two-level configuration thing I have now (search the context specific stuff first, not found, move to the parent -- like classpath or other things).
dhalbrook
Sep 9th, 2004, 08:58 PM
I'm not sure I understand completely what you're trying to do, but perhaps this will help.
I work at a company where we have multiple application lifecycles (i.e. development, staging, production) keyed to a java System property (lets call it "app.lifecycle"). Each lifecyle often has its own specific set of DB credentials and URLs.
What I do is to use that property and a PropertyPlaceholderConfigurer like so:
<!-- property placeholder post-processor -->
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyP laceholderConfigurer">
<property name="location">
<value>/WEB-INF/jdbc.${app.lifecycle}.properties</value>
</property>
</bean>
to load the desired jdbc properties file. This in turn makes any properties defined in the properties file available to the spring config, so if your properties file is called "jdbc.dev.properties" and contains:
jdbc.url=jdbc:oracle:oci8:@foodb
jdbc.username=foo
jdbc.password=bar
then as long as the System app.lifecycle property equals "dev" it will load this file, and consequently you can pass those properties to your dataSource like so:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" depends-on="placeholderConfig">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url">
<value>${jdbc.url}</value>
</property>
<property name="username">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<property name="removeAbandoned">
<value>true</value>
</property>
<property name="validationQuery">
<value>select 1 from DUAL</value>
</property>
<property name="maxActive">
<value>50</value>
</property>
</bean>
and so on and so forth. The trick is to have an inital bean which sets a valid default value for the "app.lifecycle" system property, else you might see issues.
Good luck.
dmfrey
Sep 13th, 2004, 12:52 PM
I have found the best place to do this is in my ant build script. I have an ant properties file that I pass in based upon my environment, ie. dev, qa, pre-prod, etc. Then I use the ant filter capabilites to dynamically place the appropriate values in my spring context file. So I can set the propterties for any db, deploy with the appropriate environment, and it builds without a hitch.
I hope this helps.
dtanner
Mar 17th, 2006, 04:39 PM
Here's how I eased some integration test code into our build. It allows a default configuration (our test database) without breaking the build, with the intention that eventually each developer will have their own local database-specific properties file. It's similar to the above example, except it shows how to provide a default properties file that will work if the overridden property file isn't there.
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyP laceholderConfigurer">
<property name="locations">
<list>
<value>scm.jdbc.properties</value>
<value>${user.name}.jdbc.properties</value>
</list>
</property>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
</bean>
<bean id="busDataSource" class="org.springframework.jdbc.datasource.DriverManagerD ataSource" depends-on="placeholderConfig">
<property name="driverClassName" value="${test.jdbc.driverClassName}"/>
<property name="url" value="${test.jdbc.url}"/>
<property name="username" value="${test.jdbc.username}"/>
<property name="password" value="${test.jdbc.password}"/>
</bean>
I place the file in our test configuration directory. Also in that directory is the scm.jdbc.properties file, and any other $user.name properties files. e.g. jsmith.jdbc.properties), which can be kept in source control.
So the two advantages to this configuration are:
1) It works in our cruise control environment using the default configuration
2) Developers who haven't yet created their user-specific properties file can continue ininterrupted until they have a need for that.
jdwyah
Sep 7th, 2006, 01:50 PM
I've extended PropertyPlaceholder to prepend the host name for me if I've got a property that begins with HOST or something like that. I've been pretty darn happy with this solution.
http://jdwyah.blogspot.com/2006/06/alternatives-to-advanced-configuration.html
vBulletin® v3.7.3, Copyright ©2000-2009, Jelsoft Enterprises Ltd.