Yes, got caught by PooledConnection.class.getClassLoader() which tries to
load the driver from tomcat/lib first (common.loader actually) so if you
put your driver there it will work in your case. Stays the bug when the
driver is only in the webapp.


Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le mar. 30 juil. 2019 à 13:30, Clemens Wyss DEV <clemens...@mysign.ch> a
écrit :

> > recent tomcat version
>
> 9.0.22 has the same class loading code as 8.5.35
>
>
> https://jar-download.com/artifacts/org.apache.tomcat/tomcat-jdbc/9.0.22/source-code/org/apache/tomcat/jdbc/pool/PooledConnection.java
>
>                     driver = (java.sql.Driver)
>
>                         ClassLoaderUtil.*loadClass*(
>
>                             poolProperties.getDriverClassName(),
>
>                             PooledConnection.*class*.getClassLoader(),
>
>                             Thread.*currentThread*
> ().getContextClassLoader()
>
>                         ).getConstructor().newInstance();
>
>
>
>
>
> *Von:* Romain Manni-Bucau <rmannibu...@gmail.com>
> *Gesendet:* Montag, 29. Juli 2019 09:35
> *An:* Tomcat Developers List <dev@tomcat.apache.org>
> *Betreff:* Re: PooledConnection#connectUsingDriver,
> Thread.currentThread().getContextClassLoader() is null
>
>
>
> Can you give a try on a more recent tomcat version? Seems it works with
> master version since the tomcat-jdbc module classloader is tried first
> before the tccl?
>
> Tested with:
>
>
>
> *public class *PooledConnectionTest {
>     @Test
>     *public void *avoidNPEWhenTcclIsNull() *throws *SQLException {
>         *final *PoolProperties poolProperties = *new *PoolProperties();
>         poolProperties.setDriverClassName(*"org.h2.Driver"*);
>         poolProperties.setUsername(*"sa"*);
>         poolProperties.setPassword(*""*);
>         
> poolProperties.setUrl(*"jdbc:h2:mem:PooledConnectionTest_avoidNPEWhenTcclIsNull"*);
>         poolProperties.setMaxIdle(1);
>         poolProperties.setMinIdle(1);
>         poolProperties.setInitialSize(1);
>         poolProperties.setMaxActive(1);
>
>         ensureDataSourceIsValid(poolProperties);
>
>         *final *Thread thread = Thread.*currentThread*();
>         *final *ClassLoader testLoader = thread.getContextClassLoader();
>         thread.setContextClassLoader(*null*);
>         *try *{
>             ensureDataSourceIsValid(poolProperties);
>         } *finally *{
>             thread.setContextClassLoader(testLoader);
>         }
>     }
>
>     *private void *ensureDataSourceIsValid(*final *PoolProperties 
> poolProperties) *throws *SQLException {
>         *final *DataSource dataSource = *new *DataSource(poolProperties);
>         *try *(*final *Connection connection = dataSource.getConnection()) {
>             *assertTrue*(connection.isValid(5));
>         } *finally *{
>             dataSource.close();
>         }
>     }
> }
>
>
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> <https://rmannibucau.metawerx.net/> | Old Blog
> <http://rmannibucau.wordpress.com> | Github
> <https://github.com/rmannibucau> | LinkedIn
> <https://www.linkedin.com/in/rmannibucau> | Book
> <https://www.packtpub.com/application-development/java-ee-8-high-performance>
>
>
>
>
>
> Le lun. 29 juil. 2019 à 07:36, Clemens Wyss DEV <clemens...@mysign.ch> a
> écrit :
>
> https://bz.apache.org/bugzilla/show_bug.cgi?id=63612
>
>
> > with a small project reproducing it?
>
> Unfortunately not easily extractable/reproducible
>
> Maybe :
>
> th = new Thread() {
> @Override
>
> public void run() {
> « do something that requires a connection from the pool »
>
> }
> } ;
> th.set getContextClassLoader( null ) ;
> th.run() ;
>
>
>
> *Von:* Romain Manni-Bucau <rmannibu...@gmail.com>
> *Gesendet:* Donnerstag, 25. Juli 2019 08:06
> *An:* Tomcat Developers List <dev@tomcat.apache.org>
> *Betreff:* Re: PooledConnection#connectUsingDriver,
> Thread.currentThread().getContextClassLoader() is null
>
>
>
>
>
> Le jeu. 25 juil. 2019 à 07:46, Clemens Wyss DEV <clemens...@mysign.ch> a
> écrit :
>
> < mais c'était rapide 😉 >
> >+1
> should/can I file a bug?
>
>
>
> Guess so, with a small project reproducing it?
>
>
>
>
> > init at bootstrap the pool (initial size) to ensure it is in one tomcat
> classloader
> how would you achieve this? By setting «initialSize» to «maxSize» in
> PoolProperties?
>
>
>
> 1 should be sufficient, however tomcat-jdbc (vs dbcp2 for instance) loads
> it per connection and not once for all the pool (
> https://github.com/apache/tomcat/blob/master/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java#L196)
> which is likely 1. Bad for perf but moreover 2. Buggy if the classloader
> changes between usages of a connection in apps. Loader, driver should be
> loaded once and potentially the datasource be duplicated per app if needed
> (driver in the app) IMHO. This would also fix your NPE transitively ;).
>
>
>
>
>
>
>
>
> ----------------------------------------------------------
> Von: Romain Manni-Bucau <rmannibu...@gmail.com>
> Gesendet: Donnerstag, 25. Juli 2019 07:30
> An: Tomcat Developers List <dev@tomcat.apache.org>
> Betreff: Re: PooledConnection#connectUsingDriver,
> Thread.currentThread().getContextClassLoader() is null
>
> +1, there is no real other option AFAIK until you init at bootstrap the
> pool (initial size) to ensure it is in one tomcat classloader.
>
> Le jeu. 25 juil. 2019 à 07:08, Clemens Wyss DEV <mailto:
> clemens...@mysign.ch> a écrit :
> I tried posting this in the tomcat-users-ml, but I guess it rather fits
> here:
> ----------------------------------------------------------
> Context:
> Debian GNU/Linux 9 \n \l
> java version 1.8.0_162
> Tomcat 8.5.35
>
> From time to time we are facing the follwing exception (call stack):
> ...
> Caused by: java.sql.SQLException: Unable to load class:
> org.mariadb.jdbc.Driver from ClassLoader:http://java.net
> .URLClassLoader@4c873330;ClassLoader:null
>         at
> org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292)
>         at
> org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212)
>         at
> org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736)
>         at
> org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668)
>         at
> org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:198)
>         at
> org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:132)
>         at org.apache.torque.Torque.getConnection(Torque.java:924)
>         ... 53 common frames omitted
> Caused by: java.lang.ClassNotFoundException: Unable to load class:
> org.mariadb.jdbc.Driver from ClassLoader:http://java.net
> .URLClassLoader@4c873330;ClassLoader:null
>         at
> org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56)
>         at
> org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280)
>         ... 59 common frames omitted
> Caused by: java.lang.ClassNotFoundException: Classloader is null
>         at
> org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:40)
>         ... 60 common frames omitted
>
> According to the code (in PooledConnection# connectUsingDriver)
> Thread.currentThread().getContextClassLoader() returns null
>
> Googling for " Thread.currentThread().getContextClassLoader() is null" the
> common demoniator seems to be `getContextClassLoader can be null`. If this
> is true there should be
> a) a null-check in PooledConnection# connectUsingDriver
> b) if null, then there should be a fallback-Classloader (the system class
> laoder?)
>
> WDYT ?
>
> Or any ideas why the given exception pops up from time to time
>
> Thx
> Clemens
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: mailto:dev-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: mailto:dev-h...@tomcat.apache.org
>
>

Reply via email to