2

I have the simplest JDBC program to read data from a DB2 (or other configured) instance. When I attempt to run it from Eclipse OR from the command line, the connect fails, throwing a SQLexception

 Class.forName(jdbcDriverClassName).newInstance();

The class.forName fails, using com.ibm.db2.jcc.DB2Driver. I configured Eclipse to point to the same driver that DBVisualizer uses (both as a boot library and for the project). The program uses the same connect string that DBVisualizer uses. DBVisualizer isn't having any trouble.

Ouptut w/full stack (note the FQN for the driver is not null):

                   V-- !null driver name --V
Attempting to load com.ibm.db2.jcc.DB2Driver
ERROR:java.lang.ExceptionInInitializerError: null
java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at com.ibm.db2.jcc.DB2Driver.class$(DB2Driver.java:58)
at com.ibm.db2.jcc.DB2Driver.<clinit>(DB2Driver.java:61)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at com.onlineretailer.ecomm.dumporder.DumpOrder.main(DumpOrder.java:79)
Caused by: java.lang.NullPointerException
at com.ibm.db2.jcc.am.ib.i(ib.java:490)
at com.ibm.db2.jcc.am.ib.<clinit>(ib.java:420)
... 7 more

I also tried adding the .newInstance() to the end of the class.forName() and it continues to execute the same behavior.

Thanks to everyone for your time and input!

Alexx
  • 3,572
  • 6
  • 32
  • 39

3 Answers3

4
SQLException: No suitable driver found for jdbc:db2:...

This exception has only 2 possible causes:

  1. The JDBC driver is unknown with DriverManager. I.e. the JDBC driver has not registered itself properly by DriverManager#registerDriver().

  2. The JDBC URL is unknown for any of the JDBC drivers registered with DriverManager. I.e. the Driver#acceptsURL() hasn't returned true for any of the registered drivers.

Your JDBC driver class name is perfectly fine. Your JDBC URL is perfectly fine.

A well designed JDBC driver registers itself with DriverManager in a static {} initializer block which get executed upon Class#forName(). However, older versions of the IBM DB2 JDBC driver registers itself in the constructor instead. For those broken drivers you need to call newInstance() afterwards as well.

Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance();

See also:


Update as per your question update, the newInstance() did the trick. It however leads to a new problem:

Caused by: java.lang.NullPointerException
at com.ibm.db2.jcc.am.ib.i(ib.java:490)
at com.ibm.db2.jcc.am.ib.<clinit>(ib.java:420)

It turns out to be another bug in the DB2 JDBC Driver itself. Upgrade it.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    @BalusC: There is a third cause: registered driver was loaded by a wrong classloader. – axtavt May 24 '11 at 18:22
  • @axtavt: nice one :) That would have been a terrible classloader hierarchy. I only don't think that OP runs a heavy Java EE application with multiple classloaders. – BalusC May 24 '11 at 18:24
  • @axtavt: thanks. I think perhaps I'm running into the third cause. The driver JARs are now in the system classpath, in every classpath possible, and the error still occurs. The reason I posted is because i've done more than my fair share of jdbc programming in the past, and why it would work for DBVis and not for me is what left me scratching my head. – Alexx May 25 '11 at 17:28
  • @Alexx: so, calling `newInstance()` afterwards doesn't solve it? What DB2 JDBC driver version exactly are you using? – BalusC May 25 '11 at 17:38
  • @BalusC: sadly, it did not. (I'd seen that also in another post - perhaps it was you (-:) I have also tried including the license JAR in the CP, in case this was a spurious error of sorts. (db2jcc_license_cu.jar) I am uncertain of the difference between the two JARs distributed by IBM and what DBVis is utilizing. – Alexx May 25 '11 at 18:05
  • As a *test*, try replacing the `Class#forName()` line by `DriverManager.registerDriver(new DB2Driver());`. – BalusC May 25 '11 at 18:06
  • Wait, I see in your updated question code that you're totally suppressing the `Throwable e`. Don't do that, rethrow it or do at least `e.printStackTrace()`. This way the *real* problem becomes clear -if any. – BalusC May 25 '11 at 18:07
  • Thanks for the reminder (didn't encounter this trouble with the other db so I'd genericized my error handling). I'll update with the full stack. Much more informative – Alexx May 25 '11 at 18:15
  • OK. This appears to be a Java security issue? https://www-304.ibm.com/support/docview.wss?uid=swg1IY78176 – Alexx May 25 '11 at 18:25
  • @BalusC: I truly do appreciate all of your assistance. When I unmasked the exception the originally reported one still continues to be thrown, only after the ExceptionInInitializerError. The same error is thrown and same stack is reported for `Class.forName(jdbcDriverClassName).newInstance()`,`Class.forName(jdbcDriverClassName)`, or `DriverManager.registerDriver(new DB2Driver())`. – Alexx May 25 '11 at 20:28
  • The first one is fine, the second one should be the right way but apparently doesn't work for the particular JDBC driver (as your initial problem stated), the third was just for test to naildown the problem better. Right now, I really can't be of more help than recommending to upgrade the JDBC driver to a newer version. Any `RuntimeException` is basically a bug (a developer's mistake) in the code and since the JDBC driver code is completely out of your control... – BalusC May 25 '11 at 20:36
1

You need to load driver too in your jvm , using Class.forName() You need to load following driver

com.ibm.db2.jcc.DB2Driver 

Here is how it fully look like

String databaseURL = "jdbc:derby:net://localhost:1527/sample";
// Load DB2 Driver for JDBC class
Class.forName("com.ibm.db2.jcc.DB2Driver");
// Set user and password properties
Properties properties = new Properties();
properties.put("user", "APP");
properties.put("password", "APP");
properties.put("retreiveMessagesFromServerOnGetMessage", "true");
// Get a connection
Connection conn = DriverManager.getConnection(databaseURL, properties); 

Reference

jmj
  • 237,923
  • 42
  • 401
  • 438
  • Thanks, I have that line prior to the call to getConnection: private static final String jdbcDriverClassName = "com.ibm.db2.jcc.DB2Driver"; ...Class.forName(jdbcDriverClassName); – Alexx May 24 '11 at 17:44
  • Print the whole stack trace. That error message is less information than what's available. – duffymo May 24 '11 at 17:45
  • So it should be working now , or is there any trouble still ?> – jmj May 24 '11 at 17:45
  • You need to add [`jdbc db2 driver jar`](https://www-304.ibm.com/support/docview.wss?uid=swg21363866) in your class path too – jmj May 24 '11 at 17:54
  • Ack. stackoverflow just barfed on my edits. I will have to update later. – Alexx May 24 '11 at 17:58
  • I have edited your post , its better now. As I said in my previous comment you need to add driver jar too :) – jmj May 24 '11 at 18:00
0

"No suitable driver" usually means that the connection URL isn't correct for the JAR you're using.

duffymo
  • 305,152
  • 44
  • 369
  • 561