Announcement Announcement Module
Collapse
No announcement yet.
DBCP & tomcat leave connections upon redeploy. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • DBCP & tomcat leave connections upon redeploy.

    We have an app which defines JNDI resources inside spring [dataAccess.xml] as
    Code:
    org.springframework.jndi.JndiObjectFactoryBean
    and uses both JDBC template and StoreProcedure data access. In addition, we define data sources [db] inside our tomcat configuration file [as found in ~/tomcat/conf/Catalina/localhost/xxx.xml] using DBCP:

    Code:
    	. . .
    	<ResourceParams name="jdbc/xxxDS">
    		<parameter>
    			<name>factory</name>
    			<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
    		</parameter>
    		<parameter>
    			<name>driverClassName</name>
    			<value>oracle.jdbc.driver.OracleDriver</value>
    		</parameter>
    	. . .
    The issue we run into is if we redeploy to tomcat by copying the WAR file into the webapps directory, the old connections to the database are not detroyed. I know that if I define the datasource within spring, I can specify the destroy method, however this is not acceptable since we've several environments in which to run this app.


    Springframework 1.1.5
    DBCP 1.2.1
    Tomcat 5.0.28

    Any ideas on how to solve this issue? Since we use
    Code:
    org.springframework.web.servlet.DispatcherServlet
    I was thinking of subclassing it and having it invoke the dbcp's destroy....of course there's getting hold of the dbcp object....

    Thanks.

  • #2
    I know that if I define the datasource within spring, I can specify the destroy method, however this is not acceptable since we've several environments in which to run this app.
    I don't understand this. Do you mean that it must come from JNDI for some reason (e.g. you'll deploy it in WebLogic as well and don't want to change the app)?

    I would refactor the XML definitions to pull out the datasource and transaction manager so that you can easily deploy to a different environment and switch between a JNDI and local datasource easily.

    The alternative you're suggesting to get around the Tomcat problem sounds more like hacking to me...

    Comment


    • #3
      We deploy to tomcat, however we have dev, qa, and production environments each with different database connection information. By using JNDI resources we extract any environment specific information from the WAR file. The definitions for these JNDI resources is held with in the specific environment's container [ala ~/tomcat/conf/Catalina/localhost/xxx.xml].

      This xxx.xml file simply defines the actual resources while the spring config contains references to these resources.


      Hmm, this makes me think....
      If we define the database connections w/i spring using variable substitution. Would I be able to define the values for these vars in the container's environment...

      I'll have to experiment....

      thanks.

      Comment


      • #4
        If we define the database connections w/i spring using variable substitution. Would I be able to define the values for these vars in the container's environment...
        Look at the PetStore and PetClinic sample applications. These pull out database connection details into properties files.

        Comment


        • #5
          Found a solution! [or atleast it seems to work :-]

          Since we were defining our datasources as JNDI via JndiObjectFactoryBean,
          I subclassed it, added a cleanupPool method, and of course, updated the spring config files to use the new class as well as destroy-method. Unfortuately, it only deals with DBCP...I explicitly check for it. It probably could be cleaned up to be more generic....perhaps w/ some reflection to make it generic.

          The subclass follows:
          Code:
          public class DBCleanupJndiObjectFactoryBean extends JndiObjectFactoryBean &#123;
          	private static final Log LOG = LogFactory.getLog&#40;DBCleanupJndiObjectFactoryBean.class&#41;;
          
          	public DBCleanupJndiObjectFactoryBean&#40;&#41; &#123;
          		super&#40;&#41;;
          		// TODO Auto-generated constructor stub
          	&#125;
          
          	/**
          	 * Close down the connection pool iff BasicDataSource.
          	 */
          	public void cleanupPool&#40;&#41; &#123;
          		Object o = this.getObject&#40;&#41;;
          		LOG.debug&#40;"OBJ&#58; " + o&#41;;
          		
          		if &#40;o instanceof BasicDataSource&#41; &#123;
          			try &#123;
          				LOG.debug&#40;"Closing connection pool to " + &#40;&#40;BasicDataSource&#41;o&#41;.getUrl&#40;&#41;&#41;;
          				&#40;&#40;BasicDataSource&#41;o&#41;.close&#40;&#41;;
          			&#125; catch&#40;SQLException e&#41;&#123;
          				LOG.error&#40;"Failed to close connection pool&#58; ", e&#41;;
          			&#125;
          		&#125; else &#123;
          			LOG.warn&#40;"Unhandled type!"&#41;;
          		&#125;
          	&#125;
          &#125;

          Comment

          Working...
          X