Prerequisite is to have a correctly wrapped DataSource or DataSourceFactory like described above.
The next thing is to create a bundle for the JPA Entities. For the most part, this works like in JEE. The entities need to be correctly annotated and a persistence.xml should be put into META-INF/persistence. The main thing to keep in mind for OSGi is to add a special Manifest header Meta-Persistence: META-INF/persistence.xml which marks the bundle as containing a persistence unit and points to the location of the persistence.xml.
Aries JPA will monitor all bundles in state Starting and Active for the Meta-Persistence header above. It will then scan the persistence.xml and create a matching EntityManagerFactory and also an EntityManager as an OSGi service.
These services can then be leveraged in a second bundle that uses JPA to access the entities. The easiest way to do this is to leverage the blueprint-maven-plugin. It scans the classes for CDI/JEE annotations and creates a blueprint xml from them. The skeleton of a class using JPA would look like this:
@Singleton
@Transactional
public class BookRepositoryImpl {
@PersistenceContext(unitName="ebook")
EntityManager em;
}
@Singleton
marks the class as a bean to be listed in the
blueprint.xml. This is the major difference to CDI where it is not
needed to mark beans in a special way.
@Transactional
can be used on class or method level. An annotation on
method level overrides the same on class level. By default, this will define a
transaction of type TxType.Required. This is the
typical type for methods that change JPA entities. It defines that the method will join
a transaction if one exists, or create a new one if needed. For methods that only read
data, the TxType.Supports can be used. It allows the
method to participate in a transaction but also to run without. For a full description
of the annotation, set the JTA 1.2 specification.
@PersistenceContext
defines that the variable should be injected with the
EntityManager of the named persistence unit. Aries
JPA takes care of creating thread safe EntityManager
that can be used like in JEE. The lifecycle of the EntityManager is bound to an OSGi Coordination. By default, the coordination
spans that outermost call marked with @Transactional
. This is important as
the EntityManager itself is not thread safe, so Aries
JPA internally needs to bind one instance to a thread but also needs to make sure the
EntityManager is relatively short lived to avoid
class loading problems in case of bundle restarts.
The user can also create a Coordination manually using the CoordinatorService. In the ebook example, this is done using a CXF interceptor that creates the coordination on the CXF level when a request is received and only ends it when the serialization is done. This makes the EntityManager available during serialization and allows to lazily load entities without the problem of having detached entities.