2

If the project is re-deployed through netbeans on tomcat 7 then I get errors like

java.lang.IllegalStateException
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1600)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
    at com.mchange.v2.resourcepool.BasicResourcePool.checkIdleResources(BasicResourcePool.java:1481)
    at com.mchange.v2.resourcepool.BasicResourcePool.access$2000(BasicResourcePool.java:32)
    at com.mchange.v2.resourcepool.BasicResourcePool$CheckIdleResourcesTask.run(BasicResourcePool.java:1964)
    at java.util.TimerThread.mainLoop(Timer.java:512)
    at java.util.TimerThread.run(Timer.java:462)
Exception in thread "Timer-5" java.lang.NoClassDefFoundError: com/mchange/v2/resourcepool/BasicResourcePool$AsyncTestIdleResourceTask
    at com.mchange.v2.resourcepool.BasicResourcePool.checkIdleResources(BasicResourcePool.java:1481)
    at com.mchange.v2.resourcepool.BasicResourcePool.access$2000(BasicResourcePool.java:32)
    at com.mchange.v2.resourcepool.BasicResourcePool$CheckIdleResourcesTask.run(BasicResourcePool.java:1964)
    at java.util.TimerThread.mainLoop(Timer.java:512)
    at java.util.TimerThread.run(Timer.java:462)
Caused by: java.lang.ClassNotFoundException: com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
    ... 5 more

Today we got another strange error when we tried to re-deploy the project on tomcat 7

[5:07:02 PM] Nitin - Webscraper/Tester,Java/PHP developer: java.lang.NoClassDefFoundError: com/mchange/v2/lang/VersionUtils
 com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:104)
 com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65)
 com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:62)
 com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:531)
 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
 org.hibernate.connection.C3P0ConnectionProvider.getConnection(C3P0ConnectionProvider.java:78)
 org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
 org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
 org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:161)
 org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1700)
 org.hibernate.loader.Loader.doQuery(Loader.java:801)
 org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
 org.hibernate.loader.Loader.doList(Loader.java:2542)
 org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
 org.hibernate.loader.Loader.list(Loader.java:2271)

We have been getting such strange errors since quite some time now. When we try to debug, we find the classes already existing.

What I can think of is dangling c3p0 connection-pooling threads, which are either not destroyed properly on re-deploying, or may be having some active-connection executing or something similar.

Are there any best practices on how to re-deploy such a project which uses hibernate & c3p0 ? Is there some code that I have to write on contextDestroyed for proper closing of c3p0 threads ?

coding_idiot
  • 13,526
  • 10
  • 65
  • 116

2 Answers2

2

a few thoughts:

1) if you have set up your hibernate app's lifecycle to map to your web-app's lifecycle (definitely true if hibernate and c3p0 libs live in your web-app's lib directory, potentially true even if not), you absolutely do need to make sure that c3p0 pools are destroyed prior to application recycle, often meaning a contextDestroyed method. in hibernate-speak, it is the SessionFactory that wraps the Connection pool; make sure that your application's SessionFactory is close()ed when your app shuts down on hot redeploy. there should be a symmetry: either in contextInitialized or lazily upon a first request, your SessionFactory should be initialized. it should be destroyed on application shutdown.

2) the latest (still pre-release) version of c3p0 has some settings designed to reduce the likelihood of contamination between c3p0 Threads and objects derived from expired web-app ClassLoaders, especially if c3p0 is loaded by a non web-app specific ClassLoader (e.g. if c3p0 libs live in $CATALINA_HOME/lib rather than in a webapp lib directory). if you are willing to upgrade to a prerelease [latest now is c3p0-0.9.5-pre5], then try the following new config settings:

 c3p0.privilegeSpawnedThreads=true
 c3p0.contextClassLoaderSource=library

hope this helps!

Steve Waldman
  • 13,689
  • 1
  • 35
  • 45
  • I'm using [hibernate-c3p0 dependency](http://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0), that includes its' own dependent version of c3p0. Can I still upgrade in this scenario ? I guess then I'll have more than one c3p0 jars in the classpath, which is definitely not a good idea. – coding_idiot Nov 11 '13 at 15:57
  • no, definitely avoid having multiple versions lying around, especially in Tomcat. multiplying ClassLoaders are confusing enough. you'll want to force the transitive dependency to resolve to the newer c3p0, see e.g. http://stackoverflow.com/questions/3937195/maven-how-to-override-the-dependency-added-by-a-library (the details will depend upon how you build, but there should always be a way.) – Steve Waldman Nov 11 '13 at 17:00
  • Also note that hibernate-c3p0 uses the older c3p0:c3p0 artifact, while newer c3p0 builds use com.mchange:c3p0 (different groupIds). So, if you're going this route make sure to exclude the c3p0:c3p0 dependency from hibernate-c3p0 and declare a separate dependency to the newer com.mchange:c3p0. – Shane Mar 27 '14 at 16:46
2

I was also facing the same problem and I could see the below warning in my tomcat console

Jul 30, 2014 3:20:16 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads WARNING: The web application [/rmlcrm] appears to have started a thread named [C3P0PooledConnectionPoolManager[identityToken->1hge50p9311d8syo1hfjimz|19ddf1db]-HelperThread-#0] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method) com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:635)

I was reading a lot to find out a solution to this and came across the post Hibernate :OutOfMemoryError: PermGen space

One of the comment in the post by Nicholas Hemley suggested to add a custom ServletContextListener and explicitly close the C3P0 connections in contextDestroyed() method of the listener which will be executed when the application is un-deployed.

We did not use the code exactly as we did not want to hard-couple with C3P0. But we realized that we are not closing hibernate sessionFactory anywhere in our application. We added the code to close the hibernate session factory in contextDestroyed() of the ServletContextListener. Now we do not have the error and neither we get a warning in the tomcat console.

You may also want to read Hibernate : closing the session factory does not close the c3p0 connection pool

Community
  • 1
  • 1
Tarang Zilpe
  • 101
  • 5