views:

482

answers:

2

I'm confused about class visibility in OSGi. I'm running Apache Felix and loading the following bundles:

  • the antlr, asm, jpa and core bundles from eclipselink
  • an OSGi-fied jar for javax.persistence 1.99
  • an OSGi-fied jar with the com.mysql.jdbc driver
  • a bundle of my own that contains annotated entity classes and a persistence.xml
  • another bundle of my own that calls Persistence.createEntityManagerFactory(String, Map)

Now, what I'm confused about is which bundle must be able to see the MySQL driver. I thought this would be the bundle creating the EntityManagerFactory, but I get ClassNotFound errors when I import in that manifest. Next, I tried importing it from the eclipselink jpa bundle's manifest, but wrong again. Only when I import it from the manifest of the bundle containing the persistence unit (entity classes and persistence.xml), it works.

So, seemingly the database driver is looked up by the clasloader for the PU's bundle, but that doesn't make sense to me. What's going on?

I can't seem to find a straightforward documentation for this. These slides give some hints, but aren't exactly comprehensive.

+2  A: 

I'm familiar with the OSGi classpath issues around Hibernate and JDBC and I can give you my reasoning on what's happening based on the slides you linked to.

I'm assuming you've added the JDBC driver entry to the persistence.xml inside your PU bundle?

EclipseLink is using the extender pattern to do work on the PU bundle's behalf. The extender is listening for bundles starting, checking if they have a persistence.xml and then doing the work of setting it up. It expects the PU bundle to import all the types you may reference in the persistence.xml, including the JDBC driver.

Think about it. The EclipseLink bundle won't import every known JDBC driver (and it shouldn't) - only your bundles can know which database driver they need, so it's reasonable to expect your PU bundle to import the JDBC driver class.

You shouldn't need to modify the manifests of the 3rd-party libraries if they are already OSGi-ified, such as EclipseLink.

hbunny
I'm passing the driver as a property to createEntityManagerFactory, but I guess it's the same thing? Somehow this seems weird to me. Shouldn't it be the persistence provider that handles all db specific stuff?
Hanno Fietz
All the persistence provider requires is a DB driver that can handle the JDBC interface. That way you keep the coupling between bundles low. The choice of which DB to use is application-specific, so it should be part of your code/config. This is the basic pattern with OSGi: interfaces are used as the contract and some bundle provides the domain or application-specific implementation.
hbunny
+1  A: 

I found this pdf to be quite informative regarding classloading: http://www.martinlippert.org/events/WJAX2008-ClassloadingTypeVisibilityOSGi.pdf

Houtman