Bug 62670

Summary: driverManagerProtection in JreMemoryLeakPreventionListener results in java.sql.SQLException: No suitable driver found
Product: Tomcat 8 Reporter: Padmanarayanan <srp.naren>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: 8.5.x-trunk   
Target Milestone: ----   
Hardware: All   
OS: All   
Attachments: index.jsp file - can be dropped in any example webapps

Description Padmanarayanan 2018-09-02 03:15:51 UTC
Created attachment 36128 [details]
index.jsp file - can be dropped in any example webapps

Tomcat shows "java.sql.SQLException: No suitable driver found for jdbc:postgresql://localhost:5432/postgres ..." (applies to other drivers too) when the driver class is not explicitly loaded using Class.forName("...")

The DriverManager (https://docs.oracle.com/javase/8/docs/api/java/sql/DriverManager.html) spec states that this is not required (The jdbc4+ drivers use service loaders to register themselves)

This seems to be because of driverManagerProtection in JreMemoryLeakPreventionListener. When this flag is set to 'false' in conf/server.xml, the database connection works as expected. 

The bug was observed when postgresql-42.2.2.jar was placed in CATALINA_HOME/lib or in CATALINA_HOME/webapps/examples/WEB-INF/lib/
Comment 1 Michael Osipov 2018-09-02 09:31:16 UTC
A JDBC driver should never be placed in WEB-INF/lib/. So in this case it would be an invalid issue. The other one might be misuse.
Comment 2 Mark Thomas 2018-09-02 10:26:01 UTC
(In reply to Michael Osipov from comment #1)
> A JDBC driver should never be placed in WEB-INF/lib/.

Of course it can. Such use is perfectly valid.
Comment 3 Michael Osipov 2018-09-02 10:33:36 UTC
(In reply to Mark Thomas from comment #2)
> (In reply to Michael Osipov from comment #1)
> > A JDBC driver should never be placed in WEB-INF/lib/.
> 
> Of course it can. Such use is perfectly valid.

Are you certain, isn't the driver pinned into memory by the DriverManager when the webapp is undeployed? There are zillion of discussions about this in Stackoverflow.

If so, this (http://tomcat.apache.org/tomcat-9.0-doc/jndi-datasource-examples-howto.html#DriverManager,_the_service_provider_mechanism_and_memory_leaks) should be improved because this pops up once in a while on SO and other places.
Comment 4 Mark Thomas 2018-09-02 16:48:33 UTC
This is getting rather off-topic for this bug. I don't see anything in that guidance that needs changing. If you have suggested edits, I suggest you take them to the dev@ for the community to discuss them.
Comment 5 Mark Thomas 2018-09-02 17:24:00 UTC
Getting back to the original bug report...

The behaviour described is expected when a JDBC driver is packaged in WEB-INF/lib. The behaviour (and explanation for it) is documented here:
http://tomcat.apache.org/tomcat-9.0-doc/jndi-datasource-examples-howto.html

That default behaviour is not going to change.

The described behaviour when the driver is in CATALINA_HOME/lib is not expected. That needs further investigation.
Comment 6 Mark Thomas 2018-09-02 18:38:42 UTC
It is a class loader issue. When the service loader executes it uses the bootstrap class loader which does not include $CATALINA_HOME/lib

I'm not sure if this is something that has changed in the JRE or a long standing Tomcat bug. Not that it matters much in this case as it won't affect the fix.

The fix should be simple. If I don't get time to fix it today, I'll certainly have time tomorrow.
Comment 7 Padmanarayanan 2018-09-03 07:16:28 UTC
(In reply to Mark Thomas from comment #5)
> Getting back to the original bug report...
> 
> The behaviour described is expected when a JDBC driver is packaged in
> WEB-INF/lib. The behaviour (and explanation for it) is documented here:
> http://tomcat.apache.org/tomcat-9.0-doc/jndi-datasource-examples-howto.html
> 
> That default behaviour is not going to change.
> 
> The described behaviour when the driver is in CATALINA_HOME/lib is not
> expected. That needs further investigation.

Could you also clarify about the shared/endorsed lib?
Comment 8 Mark Thomas 2018-09-03 07:36:08 UTC
Sure. I can include that in the doc updates.
The short version is:
- endorsed (where the JRE still supports it) is effectively the same as the system class path
- using the shared loader (where it has been configured since it is not used by default) needs to be handled the same was as the web application class loader.
Comment 9 Mark Thomas 2018-09-03 09:42:02 UTC
Fixed in:
- trunk for 9.0.12 onwards
- 8.5.x for 8.5.34 onwards
- 7.0.x for 7.0.91 onwards