Monday, July 19, 2010

What Database Am I Connecting To?

If you run your functional tests in different environments (your local box, the nightly build, etc.), in addition to running your components in a production setting, you might want to get feedback at startup time around just what database you're connecting to. Since I was recently bit by nightly tests that were wiping out my development-local database tables - since I'd hardwired the connection URL - I was motivated to put this kind of feedback in place. Here are some details around how I did this.

Our nightly build has certain environment variables set:

dbip=BuildHost
dbinstance=TestDatabase
dbuser=username
dbpass=password

To simulate this environment, I set these same variables in my shell (Unix, Cygwin, ...), changing the values as needed to facilitate connecting to my local database. Next I set up a property configuration in my Spring startup file that uses these variables, replacing things per the environment:
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="properties">
            <value>
                database.driver=oracle.jdbc.OracleDriver
                database.url=jdbc:oracle:thin:@//${dbip}:1521/${dbinstance}
                database.user=${dbuser}
                database.password=${dbpass}
            </value>
        </property>
    </bean>
These Spring-generated properties are used to create a data source, which is used to configure an iBatis SQLMapClient, which I then use in my DAO:
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close">
        <property name="driverClassName" value="${database.driver}"/>
        <property name="url" value="${database.url}"/>
        <property name="username" value="${database.user}"/>
        <property name="password" value="${database.password}"/>
    </bean>
....
    <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation" value="classpath:SqlMapConfig.xml"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>
....
    <bean id="ibatisDao" class="com.mybiz.resource.db.ibatis.IbatisDao">
        <property name="sqlMapClient" ref="sqlMapClient"/>
    </bean>
The DAO implements ApplicationContextAware so that it can examine the Spring context, in particular the properties of interest in the data source:
public class MyDao implements ApplicationContextAware
{
    private ApplicationContext context;

    public void setApplicationContext(ApplicationContext ctx)
    {
        context = ctx;
        dumpDataSource(ctx);
    }

    public void dumpDataSource(ApplicationContext ctx)
    {
        BasicDataSource dataSource =  ctx.getBean(BasicDataSource.class);
        logger.info("============>>> Data Source: " + dataSource.getUrl()
                + " (user " + dataSource.getUsername() + ")");
    }
}
Finally, I get myself into the habit of looking for that log output at the start of my test runs to be sure I'm connecting to the expected database. Once burned, twice shy.

No comments:

Post a Comment