I've tried the suggested code in a J2EE Application Server Context (in particular Tomcat 7) and I've noticed this message
{code:title=Tomcat Log |borderStyle=solid} SEVERE: The web application [/testContext] appears to have started a thread named [Resource Destroyer in BasicResourcePool.close()] but has failed to stop it. This is very likely to create a memory leak. {code}
Looking in the source code of c3p0 (version 0.9.1 but in version 0.9.2.1 is always the same..) I've found an explanation
From com.mchange.v2.resourcepool.BasicResourcePool - part of method close(boolean)
{code:title=com.mchange.v2.resourcepool.BasicResourcePool.java |borderStyle=solid}
public synchronized void close( boolean close_checked_out_resources ) {
........
Thread resourceDestroyer = new Thread("Resource Destroyer in BasicResourcePool.close()") { public void run() { for (Iterator ii = cleanupResources.iterator(); ii.hasNext() ;) { try { Object resc = ii.next(); //System.err.println("Destroying resource... " + resc);
destroyResource( resc, true ); } catch (Exception e) { if (Debug.DEBUG) { //e.printStackTrace(); if ( logger.isLoggable( MLevel.FINE ) ) logger.log( MLevel.FINE, "BasicResourcePool -- A resource couldn't be cleaned up on close()", e ); } } } } }; .....
} {code}
I discovered that a part of procedure is performed by a Thread and this ends up with the SEVERE message reported. In an environment of ServletContext redeploy I prefer to avoid this error message so I just add a
Thread.sleep(2000) //2 sec
statement to the suggested code just to give time to the close procedure.
{code:title=workaround |borderStyle=solid} private static boolean closeSessionFactoryIfC3P0ConnectionProvider(SessionFactory factory) { boolean done = false; if(factory instanceof SessionFactoryImpl) { SessionFactoryImpl sf = (SessionFactoryImpl)factory; ConnectionProvider conn = sf.getConnectionProvider(); if(conn instanceof C3P0ConnectionProvider) { ((C3P0ConnectionProvider)conn).close(); try { Thread.sleep(2000); //Let give it time...it is enough?...probably.... } catch (InterruptedException e) { e.printStackTrace(); } done = true; } } factory.close(); return done; } {code}
It is a "not-normal" workaround but works...
|