I've tried the suggested code in a J2EE Application Server Context (in particular Tomcat 7) and I've noticed this message
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.
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)
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();
destroyResource( resc, true );
}
catch (Exception e)
{
if (Debug.DEBUG)
{
if ( logger.isLoggable( MLevel.FINE ) )
logger.log( MLevel.FINE, "BasicResourcePool -- A resource couldn't be cleaned up on close()", e );
}
}
}
}
};
.....
}
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.
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); } catch (InterruptedException e) {
e.printStackTrace();
}
done = true;
}
}
return done;
}
It is a "not-normal" workaround but works...
|