3

In my OSGi environment I am trying to preload a database driver for further usage. Normally, this can be done like that:

Class.forName("com.mysql.jdbc.Driver");

After that, a connection can be created. However, if I use that in OSGi under Felix, he says that the class cannot be found (ClassNotFoundException) and the connection cannot be created. But when I do something like that (try-catch is omitted):

com.mysql.jdbc.Driver d = new com.mysql.jdbcDriver
Class.forName("com.mysql.jdbc.Driver");

Then everything works fine and the connection is created. However, this is not very pretty because the driver class cannot be exchanged.

Is there a way to load the class with the first method? I assume that I have to provide the correct class loader. But where do I get that from?

The MySQL driver is provided as an OSGi wrapper bundle.

palacsint
  • 28,416
  • 10
  • 82
  • 109
Nico Schertler
  • 32,049
  • 4
  • 39
  • 70
  • There is never a need to load a class dynamic with Class.forName if you have the class name in your source. Dynamic class loading should ONLY be used if you get your class name through a runtime mechanism. – Peter Kriens Mar 06 '12 at 07:47

2 Answers2

4

How exactly do you create your bundle manifest? If you use tools to automatically resolve the OSGi import statements of your bundle, they will fail on the first method since they do not recognize a simple string as a package dependency. The second method expresses the dependency as a hard Java dependency, so it's recognized by the tooling which adds the required OSGi import statement (and thus by the OSGi runtime to the classpath of your bundle).

So for your first method to work you must add the dependency to the package com.mysql.jdbc to the OSGi import statements of your bundle. How this is achieved is tool specific, Bnd uses an Import-Statement configuration parameter.

Heri
  • 2,114
  • 14
  • 13
3

Everything @Heri said in his answer was correct. However if you want to introduce more flexibility into this system, use OSGi Services.

You want to make a database connection but you don't want to tightly couple your code to the specific database or JDBC driver. Why not write a small JDBC wrapper bundle that publishes a javax.sql.DataSource service? Your logic bundle can then bind to the service when it wants to query the database, and it needn't know anything about the physical database connection.

Note that the JDBC wrapper bundle would need to know about a specific JDBC driver, however it would be an extremely thin bundle and you could produce alternative wrappers for each of the drivers that you might wish to use.

Neil Bartlett
  • 23,743
  • 4
  • 44
  • 77