Bug 48214 - JDBC DriverManager: no suitable driver found after context reload
Summary: JDBC DriverManager: no suitable driver found after context reload
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 6
Classification: Unclassified
Component: Catalina (show other bugs)
Version: unspecified
Hardware: PC All
: P2 regression (vote)
Target Milestone: default
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-11-17 07:22 UTC by Rainer Frey
Modified: 2010-07-19 13:11 UTC (History)
0 users



Attachments
Web Application that shows this behavior (3.33 KB, application/octet-stream)
2009-11-17 07:22 UTC, Rainer Frey
Details
Servlet Source of Test Case (1.77 KB, text/plain)
2009-11-17 07:24 UTC, Rainer Frey
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Rainer Frey 2009-11-17 07:22:55 UTC
Created attachment 24550 [details]
Web Application that shows this behavior

This occurs with 6.0 Trunk, built from SVN yesterday (2009-11-16):

I have a Servlet that's loaded on 
startup and does following in its init() method:

try
{
        Class.forName( driver );
}
catch( ClassNotFoundException x )
{
        log( x.toString(), x );
}
Connection con = null;
try
{
        con = DriverManager.getConnection( url, user, pass );
        log( "connection established: " + con.toString() );
}
catch( SQLException x )
{
        log( x.toString(), x );
        throw new ServletException( x.toString(), x );
}

After starting Tomcat, I get the following expected output:

Nov 16, 2009 1:56:11 PM org.apache.catalina.core.ApplicationContext log
INFO: DBTestServlet: connection established: 
org.postgresql.jdbc4.Jdbc4Connection@17ec9f7
Nov 16, 2009 1:56:12 PM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()

But when reloading the context, I get the following 
exception:

Nov 16, 2009 1:56:32 PM org.apache.catalina.core.ApplicationContext log
SEVERE: DBTestServlet: java.sql.SQLException: No suitable driver found for 
jdbc:postgresql://127.0.0.1/inxmail
java.sql.SQLException: No suitable driver found for 
jdbc:postgresql://127.0.0.1/inxmail
        at java.sql.DriverManager.getConnection(DriverManager.java:602)
        at java.sql.DriverManager.getConnection(DriverManager.java:185)
        at com.inxmail.test.DBTestServlet.init(DBTestServlet.java:49)
        at javax.servlet.GenericServlet.init(GenericServlet.java:212)

I tested with Java 6 (1.6.0_17) and JDBC 3 and 4 Drivers for Oracle 
(ojdbc1.4.jar from Oracle 10, ojdbc6 from Oracle 11) as well as PostgreSQL.

Attached is a minimal webapp that exhibits this behavior. DB connection
configuration is in /META-INF/context.xml. Also attached is the full source of
the servlet.

This webapp works in 6.0.20.
Comment 1 Rainer Frey 2009-11-17 07:24:28 UTC
Created attachment 24551 [details]
Servlet Source of Test Case
Comment 2 Mark Thomas 2009-12-21 06:13:16 UTC
The problem you are seeing is a result of where you have placed the driver class, how DriverManager works internally and what Tomcat now does to prevent memory leaks.

Your driver class is in CATALINA_HOME/lib so will be loaded by Tomcat's common class loader. The sequence of events is:

- Tomcat starts
- Your app starts
- Your servlet is loaded and init() runs
- The driver class is loaded due to the Class.forName() call
- The common class loader loads the class
- The class is registered with DriverManager but as DriverManager uses the context class loader, it is registered against your web application
- The app runs for a while
- The app is reloaded
- Tomcat spots that DriverManager has registered the JDBC driver against the webapp class loader
- Tomcat unregisters the JDBC driver to prevent a memory leak
- Your app restarts
- Your servlet is loaded and init() runs
- The driver class is not loaded since it was loaded by the common class loader and is, therefore, still available
- No class is loaded, so no driver is registered with DriverManager
- init() fails when DriverManager can't find the driver

There are many ways to fix this. The simplest are:
- use a context listener to explicitly call DriverManager.register and deregister()
- move the JDBC driver to WEB-INF/lib

Tomcat 7 logs a message when unregistering the JDBC driver that provides a useful clue as to what is going on. Tomcat 6 doesn't do that. I'll propose the necessary changes for inclusion in Tomcat 6.
Comment 3 Mark Thomas 2009-12-21 09:16:22 UTC
There was a bug here. It has been fixed in trunk and proposed for 6.0.x
Comment 4 Mark Thomas 2009-12-21 11:13:57 UTC
This has been fixed in 6.0.x and will be in 6.0.21 onwards.
Comment 5 Anton 2010-07-18 16:16:09 UTC
Tomcat has this bug for version 64-bit Itanium Windows. I guess you didn't commit fix for this version.
Comment 6 Anton 2010-07-18 17:15:32 UTC
This bug displayed after start a context. I tried get connection to external mssql database in my web application and java had an exception "No suitable driver":

org.apache.commons.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'jdbc:inetdae7a:serverName?database=dbName&charset=Cp1251'
Comment 7 Mark Thomas 2010-07-19 13:11:59 UTC
re comment #5 - The fix was platform neutral.

re comment #6 That isn't a bug, that is user error. Please use the users list for assistance.

Restoring the status of this bug to resolved.