Project: Birt
Bug 279026 JDBCDriverManager fails to find Drivers in application ClassLoader in J2EE
Reported: 2009-06-03 16:45:32 | Status: verified fixed

Build ID: M20080911-1700 Steps To Reproduce: 1.Include driver class JAR files in your WEB-INF/lib directory 2.Configure your report to use the driver 3.Try to run the report through the ViewerServlet More information: PLEASE NOTE: I understand BIRT's documented method of including JDBC drivers, but in this case the JDBC driver is a custom driver that is loaded with my application -- loading it via "loadExtraDriver" method of JDBCDriverManager is not acceptable since it would create a definition of the same class, but with a different (hidden) class loader. The new class instance would have different static fields than the original one that is visible to the J2EE application and would not be accessible to the J2EE application -- nor would the new driver class instance have access to other classes in the J2EE application that have already been loaded and initialized. That said, here is the issue.... The JDBCDriverManager class relies on the system class loader to find driver files. This can be seen in this snippet of code from JDBCDriverManager.findDriver(...) Class driverClass = null; try { driverClass = Class.forName( className ); // Driver class in class path logger.info( "Loaded JDBC driver class in class path: " + className ); } catch ( ClassNotFoundException e ) { ..... As an alternative, this could be more friendly to J2EE applications (and other applications that leverage the Thread context class loader) by doing the following: Class driverClass = null; try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); if (loader == null) { loader = this.getClass().getClassLoader(); } driverClass = Class.forName( className, true, loader ); .... By trying to make use of the thread's context class loader and then falling back to the class's class loader you strongly increase the chance of finding a driver class that the user would like you to find. In our case we have a custom driver that is loaded in the same class loader as the J2EE application, but is not available on the system class loader. Putting another copy of the driver out there in the plugins directory is not an option since then we would get a second instance of the same class, but this time in a different class loader, and the second class instance would have its own set of static fields that would not be affected by previous settings made to those fields by the J2EE application. What's worse, if the hidden class loader used does not use the appliction's class loader as a parent, then the newly initialized driver class could trigger other dependent classes to load also as duplicate class definitions. Please modify JDBCDriverManager to incorporate this simple change that will go a long way to increasing usability of BIRT with all JDBC drivers.

Files changed in fix:
data/org.eclipse.birt.report.data.oda.jdbc/src/org/eclipse/birt/report/data/oda/jdbc/JDBCDriverManager.java