I am confused on when it is necessary to use Class.forName(driverName).newInstance()
in Java for JDBC drivers, because sometimes things work just fine when I leave it out.
I remember hearing that it was no longer necessary, and haven't been using it, and things have been fine...mostly. Today, I was getting the: java.sql.SQLException: No suitable driver found...
error. I did some research, and it turns out only JDBC 4.0 drivers are automatically loaded. I've been using JTDS 1.3.1, which is JDBC 3.0.
After some experimenting, I found that there were two versions of JTDS 1.3.1 on the classpath, one in Tomcat's global lib
folder, and one in my webapp's lib
folder.
If I leave them both, I have to call Class.forName(driverName).newInstance()
for it to work correctly. What I'm wondering, is why does that solve the problem? If those two jars are the same, I don't know how it chooses the "correct" jar.
Also, if I take the jtds jar out of the webapp's lib
folder, how is the jar in the global lib
folder being found automatically if jtds 1.3.1 is not a JDBC 4.0 driver?
Although jTDS is not a JDBC 4 driver, it does contain the necessary services definition file (META-INF/services/java.sql.Driver
) defined in JDBC 4, so it is actually subject to automatic driver loading.
However, automatic driver loading only works for drivers on the initial class path. In the case of for example Tomcat, that are drivers in the lib
directory of Tomcat itself. Drivers in the WEB-INF/lib
folder are not subject to automatic driver loading.
I can't specifically answer why this results in problems when the driver is both in Tomcat lib
and in WEB-INF/lib
of your application, but likely this is a result of having multiple versions of the same classes on the class path causing the wrong classes or files to get loaded, breaking things.
As an aside, using newInstance()
is not necessary. It was sometimes recommended in the past (20-ish years ago) for either buggy drivers doing the registration in an instance initializer and/or buggy JVMs not running static initializers when using Class.forName
.