Title: JPAProject

JPA

The Aries JPA project will make it easy for JPA persistence providers such as Apache OpenJPA to be used in an OSGi environment and will provide container managed persistence for the Blueprint container.

For more information, check out section "127 JPA Service Specification Version 1.0" in the "OSGi Service Platform Enterprise Specification, Release 4, Version 4.2" available for public download from the OSGi Alliance .

Developing an Aries JPA project is very easy and can be achieved with simple steps described in the "Creation of a JPA project using Maven" section. First, however it is useful to understand some of the basic concepts.

Persistence bundles

The Aries JPA container provides managed JPA support in an OSGi framework for OSGi persistence bundles. A persistence bundle is an OSGi bundle with three special characteristics:

  • It contains one or more JPA mapped classes (Entity classes, Mapped superclasses and Embeddables)
  • It contains a JPA persistence descriptor describing one or more persistence units
  • The bundle manifest contains the header Meta-Persistence:

The value of the Meta-Persistence: header is a comma separated list of locations where JPA persistence descriptors can be found. If the header value is empty then a default of META-INF/persistence.xml is used. (This behaviour is taken from the JPA service specification).

For example:

Meta-Persistence:

means that META-INF/persistence.xml will be searched for. For non standard locations:

Meta-Persistence: persistence/myPu.xml, pUnit.jar!/someFolder/anotherPu.xml

means that the locations "persistence/myPu.xml" (relative to the root of the bundle), and "someFolder/anotherPu.xml" (relative to the root of pUnit.jar, which is in the root of the bundle) will be searched.

The Aries JPA container

The Aries JPA container consists of four main pieces, the two most important of which are the API bundle and the container bundle.

The Aries JPA API bundle

The Aries JPA container API bundle is not the JPA API, it is a set of interfaces for interacting with the Aries JPA container. Clients are unlikely to use this API, but you may need it if you are building your own runtime. This bundle also defines the interfaces that the Aries JPA container bundles use to talk to each other, as a result it is a mandatory dependency of all of the other Aries JPA container bundles.

The Aries JPA container bundle

The Aries JPA container bundle provides basic support for application managed JPA. It is responsible for locating and parsing persistence descriptors. Any persistence units found will be processed and used to create EntityManagerFactory services, which will be registered on behalf of the persistence bundle when it starts.

The EntityManagerFactory services will be registered with the following properties:

osgi.unit.name - this is the name of the persistence unit
osgi.unit.provider - this is the class name of the JPA PersistenceProvider that was used to create the EntityManagerFactory
org.apache.aries.jpa.container.managed - this property will be set to true, indicating this is a managed EntityManagerFactory.

Useful notes:

  • Older versions of the Aries JPA container (below 0.4) do not support classpath scanning or load-time weaving, this means that you must list all of your entity classes in your persistence descriptor, and that you must pre-enhance your entities. This restriction does not apply to versions newer than 0.4 when running on OSGi frameworks implementing version 4.3 of the OSGi specification.

  • You should never call close on the EntityManagerFactory service. This call will be made by the container when the persistence bundle is removed or refreshed. If you do close the EntityManagerFactory service then it will be closed for all users of the service.

The Aries JPA container context bundle

This bundle provides managed persistence context support. In order to function it requires the Aries JPA container bundle to be running as it makes use of the managed EntityManagerFactory services.

This bundle also depends on the presence of a JTA service specification implementation, as it makes use of the TransactionSynchronizationRegistry service.

It is unlikely that clients will use this bundle directly. To actually use managed persistence contexts a client should use blueprint to inject one.

The Aries JPA container blueprint integration bundle

This bundle provides a blueprint custom namespace for persistence unit and persistence context injection. To inject persistence units the Aries JPA container bundle is required. To inject persistence contexts the Aries JPA container context bundle is also required.

Example blueprint follows showing the full breadth of allowable injection syntax:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" 
  xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.1.0">

  <!-- Inject a persistence unit called "myUnit" using the bean property "setEmf" -->
  <bean id="unit">
    <jpa:unit property="emf" unitname="myUnit" />
  </bean>

  <!-- Inject an unnamed persistence unit using the bean property "setEmf2" -->
  <bean id="unitNoName">
    <jpa:unit property="emf2" />
  </bean>

  <!-- Inject a persistence unit with name "" using the bean property "setEmf3" -->
  <bean id="emptyUnitName">
    <jpa:unit property="emf3" unitname="" />
  </bean>

  <!-- Inject a persistence context for the unit called "myUnit" using the bean property "setEm" -->
  <bean id="context">
    <jpa:context property="em" unitname="myUnit"/>
  </bean>

  <!-- 
      Inject an Extended persistence context for an unnamed persistence unit that is constructed
      passing in the supplied properties and injected using the bean property "setEm" 
  -->
  <bean id="contextWithProps">
    <jpa:context property="em" type="EXTENDED">
      <map>
        <entry key="one" value="eins" />
        <entry key="two" value="zwo" />
      </map>
    </jpa:context>
  </bean>

  <!-- Inject a persistence unit called "myUnit" using constructor injection -->
  <bean id="withUnitArg">
    <jpa:unit unitname="myUnit"/>
  </bean>

  <!-- Inject a persistence context using the unit called "myUnit" using constructor injection -->
  <bean id="withContextArg">
    <jpa:context unitname="myUnit"/>
  </bean>

  <!-- Inject a persistence unit called "myUnit" using constructor injection and argument index 0 -->
  <bean id="withIndexedUnitArg">
    <jpa:unit index="0" unitname="myUnit"/>
  </bean>

  <!-- Inject a persistence context using the unit called "myUnit" using constructor injection and argument index 1 -->
  <bean id="withIndexedContextArg">
    <jpa:context index="1" unitname="myUnit"/>
  </bean>
</blueprint>

This blueprint namespace can be used by any blueprint bundle (not just the persistence bundle), and as the injection occurs via the service registry your blueprint will not start until the relevant JPA resources are available there.

Creation of a JPA project using Maven

The first step consist in to create a maven module and make the following modifications to allow to deploy it as OSGI bundle on the platform and reference where the persistence XML file must loaded by the classpath to allow to the JPA container to configure the project accordingly.

Step 1 : Module

Every jar deployed on an OSGI platform must be adapted to be conform to OSGI standard. That means that the maven packaging which is defined as the default value must be defined to bundle

<groupId>org.apache.aries.samples.blog</groupId>
<artifactId>org.apache.aries.samples.blog.persistence.jpa</artifactId>
<name>Apache Aries blog sample persistence</name>
<packaging>bundle</packaging>

and that you must configure the maven-bundle-plugin (http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html) to generate the MANIFEST.MF file required by OSGI platform.

Remark : the modification to be made (packages to be imported or exported depends on your project setting)

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <configuration>
        <instructions>
            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
            <Private-Package>org.apache.aries.samples.blog.persistence.jpa.*</Private-Package>
            <Export-Package>!org.apache.aries.samples.blog.persistence.jpa.*</Export-Package>
        </instructions>
    </configuration>
</plugin>

To allow the Aries JPA Container to setup your persistence layer (akka : instantiate the entityFactory with the information provided into the persistence.xml file), an additional modification must be made in your pom.xml file to package this file into the META-INF directory

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <configuration>
        <instructions>
            <Meta-Persistence>META-INF/persistence.xml</Meta-Persistence>
            ...
        </instructions>
    </configuration>
</plugin>

When this step is done, your pom.xml file is ready to be used to package and install your bundle into the maven repository and next into a OSGI container (Apache Felix, Apache Karaf, Eclipse Equinox)

Step 2 : Adapt the persistence file

We will not cover how to define the different parameters of the persistence file but present you what you should modify to deploy it on non J2EE platform, which is the case by definition for OSGI kernel. Curiously, there is only one think to modify and it concerns the access to the datasource. In J2EE world, we use JNDI as registry mecahnism to registry the datasource with a key used to find it from applications. JNDI is not supported like that in OSGI world but OSGI EE specification has made a proposition to provide a similar mechanism that Aries JNDI project covers (http://aries.apache.org/modules/jndiproject.html).

To access to the datasource, you must provide within the or depending if you use a JTA transaction manager or not.

<persistence-unit name="ReportIncident" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>

<jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/reportincidentdb)</jta-data-source>

With J2EE applications, you simply use the jdbc key with the name of the datasource associated (jdbc/reportincidentdb). As OSGI uses a different mechanism, we must define two parameters, the "osgi:service" wich will allow to find from the OSGI Service registry (aka proxy) the interface "javax.sql.DataSource" and the name of the service "osgi.jndi.service.name", which is a filter property, with its jndi name associated.

The other tags of the xml file are defined according to JPA specification

Step 3 : Define the services and expose them

The last step consist in to use Annotations and Injection mechanism to let the Aries JPA container to create the entity Manager with the classes of your DAO layer and add Transactional aspect into the methods. This way of work allows to complety embed existing projects into ARIES sphere without modifications

Here are the modifications to do in the blueprint xml file located under OSGI-INF/blueprint

<bean id="incidentDAO"
    class="org.apache.camel.example.reportincident.dao.impl.IncidentDAOImpl">
    <tx:transaction method="*" value="Required" /> (1)
    <jpa:context property="entityManager" unitname="ReportIncident" /> (2)
</bean>

<service ref="incidentDAO"
    interface="org.apache.camel.example.reportincident.dao.IncidentDAO">
</service>

<!-- DataSource Derby -->
<bean id="dataSourceDerby" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" />
    <property name="url" value="jdbc:derby:/temp/reportincident;create=true" />
    <property name="username" value="" />
    <property name="password" value="" />
</bean>

<!-- Expose DataSource as JNDI reference -->
<service ref="dataSourceDerby" interface="javax.sql.DataSource">
   <service-properties>
     <entry key="osgi.jndi.service.name" value="jdbc/reportincidentdb"/> (3)
   </service-properties>
</service>

(1) The <tx:transaction> tag allows to inject in your DAO layer the transactional aspect and using the following symbol "*", Aries Transaction manager will create for each method a session to begin / commit or rollback a transaction in your class The scope of the transaction can be defined using the attribute value.
(2) The JPA context is created using <jpa:context>. The entityManager (which corresponds to the property of your DAO class) will be injected using the property="entityManager". The reference to your unit name (defined in the persistence.xml file) is passed with the attribute unitname. file.
(3) The <service> allows to expose an interface on the OSGI Registry Service using as key the name of the interface ("javax,sql.Datasource"). The <service-properties> will let to define a property that we will use to retrieve the datasource from the registry

Step 4 : Package the solution

To package and deploy the solution, execute a "maven clean install" instruction and deploy your project into your favorite OSGI platform. Depending in which OSGI container you plan to deploy your projects, the bundles (Aries JPA, OpenJPA, Aries Transaction, ....) to be used will be different and you will have to identify them. The Aries samples project provides you a list of bundles and you can use them as a starting point to create your first project.