Search code examples
osgiosgi-bundlejbossfusekarafblueprint-osgi

OSGi ClassNotFoundException while loading Database Driver


I know this is a common problem, but creating a new thread just in case if some one is stuck like me even after trying some of the options already explained in documentions.

I have deployed an osgi bundle (Say Bundle B) which have all the code related to Data layer access. Basically when a service method from this bundle is accessed, it creates a JDBC connection for the very first time only, by loading the driver. The Driver is deployed as another wrapped bundle of sqljdbc 4.0. (Say Bundle C)

Now I have Bundle TestApp (Say Bundle A) which creates an instance the above said service method from Bundle B. So the flow here is Bundle A code creates an instance of Bundle B's exported service which in turn access Bundle C's Driver class.

Caused by: java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver not found by DataServices [417]
        at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1556)
        at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:77)
        at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1993)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:264)

The individual classloader is making the probelm here, but how to overcome is the situation here for me. I tried adding DynamicImport-Package to bundles A, B, tried creating a Fragment bundle as expained here https://gist.github.com/rotty3000/1291842 but still the same exception. Continues.

If anyone came across such an issue, it would be a great help if you could give me a step by step approach to get rid of this issue.

Thank you in advance and Happy new year of all.


Solution

  • The Driver approach is not working well in OSGi. Instead use a DataSource. See example at msdn. You can simply create a datasource using new. This avoids any classloading problems.

    If you want to decouple from the actual DB provider then you can use the OSGi jdbc spec which defines that db providers should expose a DataSourceFactory that can create a DataSource for you.

    Pax-jdbc supports this spec for a big range of db providers. It allows has a pax-jdbc-config module that allows to create a DataSource as an OSGi service using just a config. So in you code you can just inject the service and are done. Additionally pax-jdbc-config also can take care of pooling and making the DataSource XA aware. So it produces a fully production ready DataSource.