简体   繁体   中英

How to Close HikariCP JNDI DataSource on Shutdown/Redeploy

I am using HikariCP 2.3.3 with Spring and Jetty 9 and am trying to resolve the fact that when I hot deploy a new war file, all of the Hikari database pool connections to MySQL are left open and idle. I am using a JNDI lookup in my spring applicationContext file to retrieve the datasource from a Jetty context file.

Since I cannot specify a destroy-method in the jndi-lookup like I can if I were to define a dataSource bean, I referred to this question: Should I close JNDI-obtained data source? , where it mentions you can attempt to close the datasource in the contextDestroyed() method of a ServletContextListener. In that case they were using tomcat and c3po so I'm not sure how much the example relates.

I have tried the following in my contextDestroyed method:

InitialContext initial;
DataSource ds;     

try
{
   initial = new InitialContext();
   ds = (DataSource) initial.lookup("jdbc/myDB");
   if (ds.getConnection() == null)
   {
       throw new RuntimeException("Failed to find the JNDI Datasource");
   }

   HikariDataSource hds = (HikariDataSource) ds;

   hds.close();
} catch (NamingException | SQLException ex)
{
   Logger.getLogger(SettingsInitializer.class.getName()).log(Level.SEVERE, null, ex);
}

But at HikariDataSource hds = (HikariDataSource) ds; I get the following exception: java.lang.ClassCastException: com.zaxxer.hikari.HikariDataSource cannot be cast to com.zaxxer.hikari.HikariDataSource

I have also tried the following after reading this issue on GitHub: Is it essential to call shutdown() on HikariDataSource? :

InitialContext initial;
DataSource ds;     

try 
{
     initial = new InitialContext();

     ds = (DataSource) initial.lookup("jdbc/myDB");
     ds.unwrap(HikariDataSource.class).close();

} catch (NamingException | SQLException ex) 
{
     Logger.getLogger(SettingsInitializer.class.getName()).log(Level.SEVERE, null, ex);
}

But I get the following exception: java.sql.SQLException: Wrapped connection is not an instance of class com.zaxxer.hikari.HikariDataSource at com.zaxxer.hikari.HikariDataSource.unwrap(HikariDataSource.java:177)

I feel like I'm close to a working solution but can't quite get it. What is the proper way to close a JNDI HikariCP data source, whether in contextDestroyed() or elsewhere?

I can't find where the 2.3.3 code lines up with the HikariDataSource.java:177 line number above. One suggestion is upgrading to the latest HikariCP version, 2.3.8.

While your code looks correct , I suspect that you are running into a classloader issue, whereby the HikariDataSource (class) loaded by Jetty/Spring classloader and registered in JNDI is not the same classloader that is loading HikariDataSource in your web app.

One quick way to check is to log/print both class instances like so:

...
ds = (DataSource) initial.lookup("jdbc/myDB");
logger.info("JNDI HikariDataSource : " + System.identityHashCode(ds.getClass()));
logger.info("Local HikariDataSource: " + System.identityHashCode(HikariDataSource.class));
...

If the two class objects have different hashCodes, they are not the same class. In which case you will have to investigate whether the JNDI instance is registered in the "global JNDI context". If it is, that datasource can be shared across web app instances, and it is not appropriate for your web app to unilaterally shut it down.

UPDATE: Sorry I missed it. Re-reading your question, my guess was correct. Your original error:

java.lang.ClassCastException: com.zaxxer.hikari.HikariDataSource cannot be cast to
    com.zaxxer.hikari.HikariDataSource

is a clear indication that there are two classloaders that have loaded two separate instances of the HikariDataSource class. The first is the Jetty classloader (JNDI), and the second is your web application classloader.

This indicates that the pool is shared across web applications and you probably should not try to shut it down from your application context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM