Paul
Paul

Reputation: 20091

Should I close JNDI-obtained data source?

Update: Apparently Tomcat, starting with 7.0.11, closes the DataSource for you, so it's not available in the webapp's contextDestroyed. See: https://issues.apache.org/bugzilla/show_bug.cgi?id=25060

Hi,

I'm using Spring 3.0 and Java 1.6.

If I get a data source this way:

<bean id="dataSource" class="my.data.Source" destroy-method="close">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="url" value="jdbc:oracle:thin:@localhost:1521:home"/>
    <property name="username" value="user"/>
    <property name="password" value="pw"/>
</bean>

then the data source is closed when the bean is destroyed.

If I get the data source like this:

<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/db" />

then do I have to explicitly close the data source in my contextDestroyed listener?

Thanks,

Paul

Upvotes: 9

Views: 7959

Answers (3)

sarcastictrade
sarcastictrade

Reputation: 66

I disagree. I would add a listener to your web.xml and implement the contextDestroyed() method. This method will get called by your web container/app server when the web app is destroyed or undeployed. Within the contextDestroyed(), I would close the datasource.

inside the web.xml

<listener>
   <listener-class>util.myApplicationWatcher</listener-class>
</listener>

The code:

package util;

public class myApplicationWatcher implementes ServletContextListener
{
  public void contextInitialized(ServletContextEvent cs)
  {
      // This web application is getting started

      // Initialize connection pool here by running a query
      JdbcTemplate jt = new JdbcTemplate(Dao.getDataSource() );
      jt.queryForInt("Select count(col1) from some_table");
  }

  public void contextDestroyed(ServeletContextEvent ce)
  {
      // This web application is getting undeployed or destroyed 

      // close the connection pool
      Dao.closeDataSource();
  }
}

public class Dao
{
  private static DataSource ds;
  private static bDataSourceInitialized=false;
  private static void initializeDataSource() throws Exception
  {
    InitialContext initial = new InitialContext();

    ds = (DataSource) initial.lookup(TOMCAT_JNDI_NAME);

    if (ds.getConnection() == null)
    {
      throw new RuntimeException("I failed to find the TOMCAT_JNDI_NAME");
    }

    bDataSourceInitialized=true;
  }

  public static void closeDataSource() throws Exception
  {
    // Cast my DataSource class to a c3po connection pool class
    // since c3po is what I use in my context.xml
    ComboPooledDataSource cs = (ComboPooledDatasource) ds;

    // close this connection pool
    cs.close();
  }

  public static DataSource getDataSource() throws Exception
  {
    if (bDataSourceInitialized==false)
    {
      initializeDataSource();
    }

    return(ds);
  }
}

Upvotes: 5

skaffman
skaffman

Reputation: 403591

No. The DataSource here is managed by the remote JNDI container, and it's that container's job to manage the lifecycle of the DataSource. Spring just makes use of it, it doesn't manage it.

Even if you wanted to, you couldn't - DataSource has no close() method, or anything like it.

Upvotes: 4

gkamal
gkamal

Reputation: 21000

When you get the data source through a JNDI lookup it a shared resource - configured in your container. It is managed by the container and not by the application, so it is not required (there is no way) to close it.

Upvotes: 1

Related Questions