0

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.

Sandy
  • 35
  • 1
  • 6
  • What code do you have in your bundle (only show the relevant lines). What does it do at the point where the exception happens? – Christian Schneider Jan 16 '17 at 15:38
  • From Bundle A, PremiumService service = new PremiumServiceImpl(); From Bundle B PremiumServiceImpl, dao.getJdbcConnection(), which in turn calls Class.forName(), From Bundle C, sqljdbc4-4.jar which is a wrapped bundle – Sandy Jan 16 '17 at 16:58
  • When I debugged the application at this line Class.forName(driverClassName), the class loader was bundle class loader with bundle as bundle A's name and and while this line of code is in Bundle B (DataServices) project. Driver class name value also confirmed as correct. – Sandy Jan 16 '17 at 19:29

1 Answers1

1

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.

Christian Schneider
  • 19,420
  • 2
  • 39
  • 64
  • Thank you Christian, Let me will try this option. – Sandy Jan 17 '17 at 08:22
  • Pax-jdbc, I see a wide range of DB support, but can't see SQLServer. Is this where we have to go with Generic Driver Extender? – Sandy Jan 17 '17 at 09:41
  • There is a mssql module. https://github.com/ops4j/org.ops4j.pax.jdbc/tree/master/pax-jdbc-mssql . It is part of the releases since 0.6.0 – Christian Schneider Jan 17 '17 at 09:45
  • Thanks a lot Christian. The example at msdn worked for me. But I would like to try the pax-jdbc option also. Will give a try when I have some time since that has the advantages like pooling and XA – Sandy Jan 18 '17 at 11:36