Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 476
Paul Avatar asked Mar 23 '11 15:03

Paul


People also ask

What is the use of JNDI DataSource?

A JNDI DataSource object is a file that contains the configuration details necessary to connect to a database. The DataSource object must be registered on a JNDI server, where it is identified using a JNDI name. You can register your DataSource object directly on your application server via its JNDI service.

Why is JNDI required?

JNDI, part of the J2EE specification, provides naming and directory functionality for Java applications. Because JNDI is defined independently of any specific naming or directory service implementation, it enables Java applications to access different naming and directory services using a single API.

What is JNDI DataSource in Tomcat?

Actual benefit of DataSource comes when we use it with a JNDI Context. For example, connection pool in a web application deployed in a servlet container. Most of the popular servlet containers provide built-in support for DataSource through Resource configuration and JNDI context.

Does Tomcat use JNDI?

Tomcat provides a JNDI InitialContext implementation instance for each web application running under it, in a manner that is compatible with those provided by a Java Enterprise Edition application server. The Java EE standard provides a standard set of elements in the /WEB-INF/web.


2 Answers

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);
  }
}
like image 112
sarcastictrade Avatar answered Sep 22 '22 17:09

sarcastictrade


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.

like image 38
skaffman Avatar answered Sep 20 '22 17:09

skaffman