Switching datasources dynamically at runtime

Let’s say you are running your application on a database that requires a password change (or switching to a different machine or whatever). Normally this would require an application restart to reflect the new changes but there’s an easier way.

Since v0.6.4-rc2, BoneCP has support for lazy termination which means that:

  • Connections not in use are closed off
  • Helper threads are shut down
  • Connections in use are left to work but will be closed off when they are closed by the application.
  • This means that so long as we can tell our application to use a different connection pool we can seamlessly migrate to use the new settings by creating a new pool with the new parameters (ip, username, password, etc) and telling the old one to terminate gently.

    That’s the gist of it and thankfully Spring and BoneCP makes this easy. By using a DelegatingDataSource we can bounce off a request to our datasource to some custom logic. This is the approach provided by BoneCP’s DynamicDataSourceProxy that simply exposes a new method, switchDataSource, that takes the new BoneCPConfig configuration object and does all the required work.

    In other words, when DynamicDataSourceProxy’s switchDataSource method is called:

  • A new datasource with the new configuration is created (i.e. a new connection pool is created)
  • A connection is fetched and closed from the new pool to force any lazy initialization structures to kick-start.
  • The DelegatingDataSource target datasource is switched to the new pool (this forces the application to start using the new pool)
  • The old pool is asked to terminate lazily.
  • Spring’s context file is amended so that the obtained datasource bounces off the dynamicDataSourceProxy instead:

    1
    2
    3
    4
    5
    6
    7
    
    	<bean id="dynamicDataSourceProxy" class="com.jolbox.bonecp.spring.DynamicDataSourceProxy">
    		<property name="targetDataSource">
    			<ref local="mainDataSource" />
    		</property>
    	</bean>
     
    where mainDataSource is your old datasource.

    Now just create a mechanism to trigger the switch method by some means such as polling an LDAP server for new settings or reading a configuration file. Something like:

    1
    2
    3
    4
    5
    6
    
    BoneCPConfig newConfig = .. create new config here ...
    BoneCPConfig oldConfig = ((BoneCPDataSource)ds.getTargetDataSource()).getConfig();
     
    if (newConfig != null && !newConfig.equals(oldConfig)){
    	ds.switchDataSource(newConfig);
    }

    Tags: , , , , , , , ,

    7 Responses to “Switching datasources dynamically at runtime”

    1. Jon Demina says:

      Have a look at this post for a downloadable example of spring+hibernate+mysql:
      http://forum.springsource.org/showpost.php?p=296322&postcount=5

    2. andy says:

      Just to let you know that DataNucleus (http://www.datanucleus.org) is a JDO and JPA implementation providing persistence of Java objects to pretty much any type of datastore on the planet (RDBMS, ODBMS, LDAP, Excel, ODF, HBase, Amazon S3, etc etc), and it now supports use of BoneCP as a connection pool when persisting objects to RDBMS. Perhaps add a link to it from your docs ?
      DataNucleus docs for its use are at
      http://www.datanucleus.org/products/accessplatform_2_1/rdbms/bonecp.html

    3. admin says:

      Sure! Thanks for the heads-up.

    4. Kev says:

      Is it possible to use the DynamicDataSourceProxy in combination with the LazyConnectionDataSourceProxy?

    5. Arpit says:

      Hi,

      i am using a standalone java application and thus not using spring & datasources.

      Can you please help how can I do the database change dynamically at runtime.

      -Arpit

    6. @Kev: Yes
      @Arpit: You’re going to have to re-implement what Spring does.

    7. buy web traffic…

      Switching datasources dynamically at runtime « jolbox.com…

    Leave a Reply