4

I am using commons-dbcp to do connection pooling for a MySQL database in a small Spring webapp which is deployed as a WAR file to a local Tomcat 6.0.28 container (installed using the Ubuntu package manager) using the Sun 1.6 JDK. The deploy is done from Maven using tomcat-maven-plugin-1.1 with the goal tomcat:redeploy. The MySQL Connector/J jar is in the webapp's WEB-INF/lib directory.

The first time the webapp is loaded after Tomcat starts, everything works fine. However, when I redeploy the webapp, as Tomcat undeploys the webapp it complains that the JDBC driver was not unregistered.

code>SEVERE: The web application [/taskrun] registered the JBDC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Mar 11, 2011 11:29:46 AM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc

Then, when Tomcat restarts the webapp, it fails to connect to the database, complaining about no suitable driver:

org.apache.commons.dbcp.SQLNestedException: Cannot create JDBC driver of class 'com.mysql.jdbc.jdbc2.optional.MysqlDataSource' for connect URL 'jdbc:mysql://127.0.0.1:3306/testdb?autoReconnect=true'
    at org.apache.commons.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1452)
    at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1371)
    at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:113)
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:79)
    ... 14 more
Caused by: java.sql.SQLException: No suitable driver
    at java.sql.DriverManager.getDriver(DriverManager.java:279)
    at org.apache.commons.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1437)
    ... 18 more

Everything works fine if I manually restart Tomcat after the redeploy.

I know the MySQL driver registers itself with the DriverManager when the class is loaded, but the com.mysql.jdbc.Driver class doesn't seem to be reloaded when the webapp is redeployed. Is Tomcat's WebappClassLoader supposed to reload classes from the WEB-INF/lib directory when the webapp is reloaded or does it keep them in memory between deploys? Or do I have to re-register the MySQL driver myself after a deploy?

Also, I've seen plenty of posts suggesting moving the driver jar to Tomcat's commons/lib directory, but I would like to avoid dependencies external to my WAR file as much as possible.

Thank you in advance for any assistance.

matts
  • 6,738
  • 1
  • 33
  • 50

1 Answers1

2

Placing JDBC driver to WEB-INF/lib is usually bad idea. Normally JDBC drivers are shared between all deployed applications and in proper configuration they should be part of global Tomcat configuration (put it to Tomcat 'lib'). The driver shouldn't be redeployed every time you update your application unless you have very specific reasons to this.

Vladimir Kroz
  • 5,237
  • 6
  • 39
  • 50
  • Thank you so much! Have the jdbc driver in BOTH the WEB-INF/lib and the tomcat/shared was causing a conflict at runtime for my webapp. Your advice FINALLY fixed my problem! – hightechfool Nov 05 '13 at 20:21