OSGi and JEE – JPA

JEE perspective

As an application programmer, using JPA in a JEE container is as simple as injecting an EntityManager in your bean. In the back a lot of actions are performed by the JEE container:

  1. It takes care of creating EntityManagerFactory instances for the persistence units that are defined in the persistence.xml files. This is done with help of PersistenceUnitProvider implementations which are found via the Java service provider solution.
  2. It takes care of the thread-safety of the EntityManager instances that are injected into the beans. This because, by specification, an EntityManager instance cannot be shared by multiple threads.
  3. It takes care of transaction management.

JPA and OSGi

For OSGi, JPA interacton is specified in chapter 127 of the OSGi enterprise specification. To state it short: a persistence unit globally results in an EntityManagerFactory for the unit to become available as service in the OSGi service registry. Application programmers can look-up those services in the service registry, create EntityManagers from them and use those to perform persistence actions and dispose them afterwards.

There are however some complications:

  • The persistence.xml file may contain JNDI look-ups for the data sources to use. For JNDI a different chapter is present in the OSGi specification (chapter 126, implemented by an Aries project), but to state it simple: the way JNDI bootstrapping was designed is not compatible with the dynamic nature of OSGi. If I have time, I will create a different blog to explain this, but for now my statement is to forget JNDI in combination with OSGi. The alternative however means declaring the database properties in every persistence unit present, which isn’t clean either.
  • As indicated earlier, the application programmer can create an EntityManager instance, but is left with persistence unit local transactions. Although global transactions are described in chapter 123 of the OSGi enterprise specification, there is still a gap between the specification and day-to-day use.

JPA solutions for OSGi

There are a couple of solutions that allow JPA on OSGi via an implementation of the JPA chapter from the OSGi specification:

  • Gemini JPA is the eclipse implementation. It uses eclipselink as JPA provider and extends it to register an entity manager factory in the OSGi service registry.
  • Aries JPA is the implementation of the Apache Aries project. It uses OpenJPA as JPA provider.
  • The JPA part of the OSGi enroute project. Can use eclipselink and hibernate as persistence provider.

All of these solutions have their peculiarities:

  • Aries JPA seems to work only with a JPA 2.0 version (which disqualified it for me).
  • Aries JPA and Gemini JPA make use of JNDI for lookups of the data sources.
  • Gemini JPA uses (unnecessary?) wiring magic which makes it prone for starting order issues.
  • The JPA part of the enroute project does not allow for different data sources for different persistent units. Furthermore, it only allows JTA persistence units and requires an XA data source. It does however extend the JPA solution with EntityManager services that can be directly used via service look-ups.

Container perspective on JPA

As already indicated earlier, from a JEE container perspective, the main interface to JPA is delivered by the javax.persistence.spi.PersistenceProvider interface. This interface has actually two views for creating an javax.persistence.EntityManagerFactory:

  • A Standard Edition view, for standalone creation of an entity manager factory. This method just passes the name of the persistence unit and leaves it up to the provider to do the rest
  • A container view, for creation of entity manager factories in managed mode. This method needs a complete definition of a persistence unit, passed as an interface to the provider.

In OSGi, the second variant is the appropriate one to use: there is no way that the persistence provider is able to construct the persistence unit just by name.

The persistence unit definition, represented by an implementation of the javax.persistence.spi.PersistenceUnitInfo interface, is globally a mapping that conforms to the contents of a persistence.xml file (like data sources, mapping files, classes, etc.) with some additional methods to interact with the container. The latter methods are rather obscure, at least in an OSGi environment:

  • addTransformer() should add a class transformer that performs some kind of byte code weaving, meaning: adapt the classes when they are loaded. Although in OSGi something alike is present since recent version (probably as a result of the enterprise specification), I don’t like the practice at all. Especially, if you consider that persistence units may be re-loaded for example if the bundle is stopped and started, but the bundle classes remain loaded in the mean time.
  • getNewTempClassLoader() should return a class loader that can be used to temporary load classes that are not visible to the application and only used during creation of the entity manager factory. Sorry, but I don’t like this at all either: by definition class loaders have a delegation model, so why would one want this? My expectation is that this has to do with the byte code weaving of addTransformer(), but I am not sure.

In my opinion, the use of persistence providers that need the last two methods for normal operation should be reconsidered.

Chapter 127?

This all makes actually a (half-hearted) implementation of the OSGi enterprise chapter 127 relatively simple:

  • Make sure that the PersistenceProvider interface from a JPA implementation is exported via the OSGi service registry.
  • Track PersistenceProvider services and bundles containing the chapter 127 persistence header.
  • Parse the persistence definition files from the bundles and use them to create a EntityManagerFactory via the PersistenceProvider interface.
  • Register the factory with the service registry.

But that of course does not include transaction handling nor EntityManager injection.

And JNDI?

Earlier in this blog I indicated that I don’t like JNDI in OSGi. So, what about the data sources that are specified in the persistence definition files? These are according to the specification JNDI look-ups. For that the OSGi JNDI namespace indication as specified in the OSGi enterprise specification JNDI chapter can still be used. It is however not delegated to an OSGi JNDI implementation, but parsed by the JPA bundle itself (which is actually very simple to do). Therefore, just use the osgi:service/javax.sql.DataSource syntax to reference a data source that is available via a look-up in the OSGi registry.