I happily used DBCP and DBCP2 with Spring for over a decade.  I am now trying 
to migrate from Java 8 to Java 11 and hit a terrible snag, described below:


*       My apps dynamically load the classpath from a tree of folder that 
contains many JARs.  Yes, I can change this model in the future but for now I 
need to migrate many apps quickly and that means keeping this design.

*       The old techniques to do the above broke starting in Java 9, so I must 
now use a custom classloader.  That was easy to write, and I set it with 
thread.setContextClassLoader(myClassloader).  From that point on in "vanilla" 
Java my apps find the classes fine as all the needed libraries are in the 
classpath.

*       But I define my DBCP2 DataSource in a Spring context.xml file.   This 
is where things break.

o   I get a ClassNotFoundException for org.apache.commons.pool2.ObjectPool when 
loaded indirectly by the Spring bean specified with 
class="org.apache.commons.dbcp2.BasicDataSource".

o   Curiously, I can successfully load the class manually with 
myClassloader.loadClass("org.apache.commons.pool2.ObjectPool") in my code just 
fine, confirming that it is properly on the classloader's classpath.

*       My conclusion (maybe erroneous) is that Spring is reverting to the 
system classloader instead of using myClassloader when loading classes, because 
at the time of execution (and exception) the commons-pool2 JAR is only known to 
myClassloader, not the system classloader.

I suspect that the core of this problem is more about Java 11 or even Spring 
than DBCP2.  But as most applications that rely on DBCP2 do it through Spring, 
a lot of us are migrating out of Java 8, and this issue cripples those 
DBCP2-reliant applications... I am hoping that there is a well-known solution 
and someone here will be kind enough to share it.

Thank you in advance.

Reply via email to