Using JPA to write database applications in an OSGi Container (e.g. Felix or Adobe AEM, CQ5)

Many projects might require access to databases and although you’re free to do it any way you like, many prefer the JPA (Java Persistence API) for its ease of use as a pluggable Object Relational Mapping (ORM) API. Using this in a normal servlet container or JEE container might be taken for granted with implementations such as Hibernate, Eclipselink already being there for the developer to just use without having to worry if there is any more setup or gotchas the container has. For those running in a container such as Apache Felix (e.g. users of Adobe CQ5/AEM) or another OSGi container, there are some steps before one can do this. The following is my experience doing this with Eclipselink and Gemini JPA.

So let’s say we’d like to do our JPA development like this:

1. Have a separate bundle for the Entity classes which includes the persistence unit.

2. Have bundles for OSGi services we write to be able to get access to an EntityManager instance whenever they need to

3. We do not want to put in any hardcoded database settings in the persistence.xml. Ideally we’d like the database settings to be managed by the data source pool.

For those in AEM, the data source pool is a service in the OSGi console (/system/console/configMgr) where you can setup a pool with JDBC connection settings (it’s called the Day Commons JDBC Connection Pool). Provided you have uploaded the driver already as an OSGi bundle, you can put settings here such as the JDBC driver, db string, etc. So one thing that isn’t documented (or at least I couldn’t find this) is that if you want that data source to be registered as a JNDI resource, you need to give the data source name with at least a “:” such as

java:comp/env/myDS

If you name it myDS, it is not going to be available like that and that is required for later on. If you’re not using AEM and need to do this in Felix, you can look into setting up a javax.sql.DataSource yourself and registering with a JNDI bundle yourself.

Now, once you’ve got this data source pool registered, the second step is to get all the dependent libraries for JPA and the implementation you choose. I had a requirement to use Eclipselink. The bundles I installed that worked (this was tricky) where:

1. org.eclipse.gemini.jpa_1.2.0.M1.jar (not available via maven so I had to install this manually)

2. org.osgi.enterprise 5.0.0

3. org.eclipse.persistence : javax.persistence 2.1.0

4. org.eclipse.peristence : org.eclipse.persistence.jpa 2.5.2

5. org.eclipse.persistence : org.eclipse.persistence.core 2.5.2

6. org.eclipse.persistence : org.eclipse.persistence.asm 2.5.2

7. org.eclipse.perisstence : org.eclipse.persistence.antlr 2.5.2

Once you have these installed, you can start preparing a bundle with your Entity classes and your persistence classes. I won’t go into writing how to write an Entity class here as I’m assuming you already know how to use JPA. For the persistence.xml file, put it in src/main/resources/META-INF and it goes something like this:

<persistence-unit name="my-pu" transaction-type="RESOURCE_LOCAL">

<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

<non-jta-data-source>java:comp/env/myDS</non-jta-data-source> <!-- remember the JNDI data source name? That goes here -->

<class>my.entity.class.MyEntity</class> <!-- your entity class here -->

</persistence-unit>

Once you install this bundle as an OSGi bundle, two things should happen. The Gemini JPA container will look for the JNDI data source and try an instantiate a PersistenceProvider and an EntityManagerFactory per persistence unit bundle. So first check is to to go /system/console/services and check there are these services:

1. javax.persistence.spi.PersistenceProvider

2. At least one javax.persistence.EntityManagerFactory

If these are active, you know your can now start using that and development db access code.

In order to instantiate an EntityManager from the EntityManagerFactory, you need to get a hold of it first. In the declarative service, use:

@Reference(target=("osgi.unit.name=my-pu")) 
private EntityManagerFactory entityManagerFactory; //replace my-pu with your persistence unit name that you specified in persistence.xml

Once you’ve got this, you can call

EntityManager entityManager = entityManagerFactory.createEntityManager();

try {

//do your db access

} finally {

    entityManager.close();

    entityManager = null;

}

Once in a while you might see that your database access service classes don’t have their dependencies met. This would most likely be a problem with your database connection settings. Go to the Day Commons JDBC Connection pool and check your db settings and data source name. Once you save, unfortunately, you will have to restart the Gemini bundle again so that the container picks up those settings and restarts the persistence unit bundles.

And that’s it. There might be other ways to do this using the Hibernate bundles but I haven’t looked into this. This seemed the way of least resistance where I had the container manage the EntityManagerFactory as a service.

– Sarwar Bhuiyan

Advertisements
Using JPA to write database applications in an OSGi Container (e.g. Felix or Adobe AEM, CQ5)

7 thoughts on “Using JPA to write database applications in an OSGi Container (e.g. Felix or Adobe AEM, CQ5)

    1. Mani says:

      Gemini bundle is not getting active in felix console, though there’s no dependency issue. It’s in Installed state.

    1. Mani says:

      Thanks Sarwar, The issue got fixed as it had dependency on jpa-jpql bundle. Now everything works fine as you’ve mentioned, Thanks. One thing that seems to be a concern is whenever the persistence bundle (having entity classes, persistence.xml)gets installed, am getting below issue.
      Have you come across this issue?

      *** FATAL ERROR *** ServicesUtil – Failed to create proxy for EMFBuilder service
      :
      28.06.2015 16:45:12.325 *ERROR* [OsgiInstallerImpl] ERROR: EventDispatcher: Erro
      r during dispatch. (java.lang.RuntimeException: ServicesUtil – Failed to create
      proxy for EMFBuilder service: )
      java.lang.RuntimeException: ServicesUtil – Failed to create proxy for EMFBuilder
      service:

  1. Sarwar Bhuiyan says:

    Mani, not sure. I don’t have access to this code anymore but for some reason I’m not remembering the jpa-jpql dependency. Which bundle showed this error?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s