Thursday, August 2, 2007

Managing JPA EntityManager lifecycle

Managing EntityManager lifecycle when using JPA in a non enterprise environment (e.g. Tomcat) is a custom task you must take care of by yourself for you don't have the IoC (Dependence Injection) of a Java EE 5 to manage the EntityManager lifecycle. It happened the same when we discussed the EntityManagerFactory lifecycle in a previous post. Therefore, in this situation, you should consider the right scope of the EntityManager to use.

In order to decide your best approach, you need to keep in mind that:

  1. An EntityManager is not a heavyload object.
  2. It's not safe to traverse lazy-loaded relationships once the EntityManager is closed (This situation will change as of JPA 2.0).

Because of the first issue, there is no need to use the same EntityManger longer than needed, so there is neither room for application scope nor session scope. In addition to the first issue, note that you can't use an EntityManager instance for the whole application lifecycle (application scope) for the EntityManager is not Thread-safe.

Only two scopes are left:

  • Method scope (i.e. instantiate/destroy one EntityManager in each business method).
  • Request scope.

Using EntityManager with method scope


You create and destroy the EntityManager instance within a business method.
Be careful to ensure the EntityManger is always closed. When dealing with transactions it could be a little tricky as it was commented in this post.

Dealing with this scope is easy, here is a sample:
public void aBusinessMethod() {

EntityManagerFactory emf = ... ;
EntityManager em = emf.createEntityManager();
try {
...
} finally {
em.close();
}
}
However, this method scope is not enough for every situation. There could be some scenarios where you'll need a wide scope, such as the following situations:

  • When transactions spread multiple business methods.
  • Need to traverse lazy-loaded relationships outside a method (e.g. in a JSF page).

In these scenarios you can choose to keep one EntityManager for the whole life of a HTTP request as we are about to describe.

Before stepping further into the request scope strategy, you can think of a little workaround in order to avoid using the latter (this workaround is not my favorite alternative). It is based on forcing eagerly the loading of relationships of entities and can be useful when you need to traverse them once the EntityManager has been closed. One of such a typical scenario is traversing a relationship from within a JSF page.

Loading eagerly relationships

As a reminder, the JPA relationships that by default are lazily loaded are: OneToMany and ManyToMany.

Loading eagerly these relationships can be done in two different ways:

  • Changing the domain model
  • Explicit loading of relationships

The first one is referring to explicitly use the parameter fetch of the JPA annotation @OneToMany or @ManyToMany as in the sample:

@OneToMany(fetch=FetchType.EAGER)

The problem with this solution is that you define a requirement in your domain model instead of solving the problem just when you really need it.

Loading explicitly relationships can be done at first sight by invoking the method on the entity that get access to the collection of entities, however this is not very reliable: for instance, when we traverse a OneToMany relationship with Hibernate EM as the JPA engine, the returned collection (proprietary implementation) has not loaded its entities at all. In spite of returning a collection, its elements are not loaded till you really access each one (or invoke the size() method of the collection to force this loading)!

Using EntityManager with request scope


This is a one EntityManager per HTTP request strategy with the following features:

  • Creation on demand of the EntityManager.
  • Lazy closing of the EntityManager.

We'll provide an on-demand creation of the EntityManager instance to use within the request service. So if the EntityManager is not needed for a given request, it won't be create at all!

The main benefit of this scope is derived from the delayed closing of the EntityManager (it will last as long as a HTTP request is in process). Every queried entity will be managed till the end of the request and therefore during the presentation phase (the render phase in JSF for instance). This allows you to traverse lazy loaded relationships in a transparent manner: you no longer have to force the loading of relationships as commented before (they will be loaded only if they are traversed: on demand).

Another benefit is the possibility to share the EntityManager instance among several business methods within a request (with no need to pass the EntityManager as parameter). This is not a limitation, in case you would need more than one EntityManager instance you'll be able to bypass this utility and create directly an EntityManager instance yourself.

Transparent Design for an EntityManager with a lazy closing behavior

As a requirement, our approach will be transparent from a client perspective.That is, the client code should not change in order to provided this behavior (this way, you can easily adapt your web application). This is the typical client code using the EntityManager inside a method:
EntityManagerFactory emf = ...
EntityManager em = emf.createEntityManager();
try {
...
} finally {
em.close();
}
In order to provide this transparency, we'll create proxies for the EntityManagerFactory and EntityManager classes. The following UML class diagram, based on the Proxy Pattern, shows abstract proxies and the concrete classes:
Instead of creating one class for every proxy we have chose to create an abstract proxy class to be used as a generic multi-purpose base class, and we have provided the actual proxy as a concrete class extended from the the abstract proxy.

You can take a look to the EntityManagerFactoryProxy class:
abstract class EntityManagerFactoryProxy implements EntityManagerFactory {

protected final EntityManagerFactory delegate;

protected EntityManagerFactoryProxy(EntityManagerFactory emf) {

this.delegate = emf;
}

public EntityManager createEntityManager() {

return delegate.createEntityManager();
}

public EntityManager createEntityManager(Map map) {

return delegate.createEntityManager(map);
}

public boolean isOpen() {

return delegate.isOpen();
}

public void close() {

delegate.close();
}
}
The EntityManagerProxy class (not shown here, see complete source from resources) is created likewise.

The ScopedEntityManagerFactory class is just a factory for LazyCloseEntityManager. And LazyCloseEntityManager class acts in behalf of the client to override the EntityManager.close() method in order to delay calling the close method of its delegate (actual EntityManager).

Binding Thread and EntityManager

Our design is based on a property all Application Servers must ensure: for a given request, the ServletRequestListener's methods and Serlvet's service method are executed in the same thread (regardless of the use of a thread pool to serve requests).

Taking advantage from this issue, we're going to create a request listener whose responsibility is just to close the EntityManager bound to to the request thread (if it was created previously created).
In order to delay the closing of the actual EntityManager we'll encapsulate it in an LazyCloseEntityManager (transparent proxy) (whose close() method will be overridden) and we´ll bind the latter to the current request thread so that the actual EntityManager will be closed later by the request listener when the request service ends.

Binding the EntityManager to the current thread can be done easily using a ThreadLocal object.

The class responsible for creating LazyCloseEntityManager is ScopedEntityManagerFactory and so the one who use ThreadLocal. when a client asks for an EntityManager managed ScopedEntityManagerFactory will look up first in its ThreadLocal object. If the current thread asking for the EntityManager has already used it, No other EntityManger will be created, otherwise, ScopedEntityManagerFactory will create a new LazyCloseEntityManager and will bind it to the thread for future uses.

Somehow ScopedEntityManagerFactory should be notified when the HTTP request finishes for it must forget the LazyCloseEntityManager bound to its ThreadLocal object.
One way to do so in a no coupled fashion is through a listener. ScopedEntityManagerFactory will implement LazyCloseListener in order to be notified by the LazyCloseEntityManager.

Finally the HTTP request listener is responsible for closing eventually the LazyCloseEntityManager and notifying of this event.

The following UML class diagram exposes these ideas:
As a facility, we'll show some of the core classes that implements this design.
We'll start with the factory of LazyCloseEntityManager instances, that is ScopedEntityManagerFactory. This is the only class using the ThreadLocal class. Note it is notified when each LazyCloseEntityManager instance is really closed.
public class ScopedEntityManagerFactory extends EntityManagerFactoryProxy
implements LazyCloseListener {

private final ThreadLocal<LazyCloseEntityManager> threadLocal;

protected ScopedEntityManagerFactory(EntityManagerFactory emf) {

super(emf);
this.threadLocal = new ThreadLocal<LazyCloseEntityManager>();
}

public EntityManager createEntityManager(Map map) {

LazyCloseEntityManager em = threadLocal.get();
if (em == null) {
em = new LazyCloseEntityManager(super.createEntityManager(map));
createEntityManager(em);
}
return em;
}

public EntityManager createEntityManager() {

LazyCloseEntityManager em = threadLocal.get();
if (em == null) {
em = new LazyCloseEntityManager(super.createEntityManager());
createEntityManager(em);
}
return em;
}

private void createEntityManager(LazyCloseEntityManager em) {

threadLocal.set(em);
em.setLazyCloseListener(this);
}

protected LazyCloseEntityManager getEntityManager() {

return threadLocal.get();
}

public void lazilyClosed() {

threadLocal.set(null);
}
}
Below you can see the LazyCloseEntityManager class. Note this class is a wrapper for the Actual EntityManager: It is created by ScopedEntityManagerFactory (through a ThreadLocal) and used by the HTTP request listener PersistenceAppRequestListener:
public class LazyCloseEntityManager extends EntityManagerProxy {

private LazyCloseListener listener;

public LazyCloseEntityManager(EntityManager delegate) {

super(delegate);
}

public void setLazyCloseListener(LazyCloseListener listener) {

this.listener = listener;
}

public LazyCloseListener getLazyCloseListener() {

return listener;
}

@Override
public void close() {
}

protected void lazyClose() {

super.close();
if (listener != null) listener.lazilyClosed();
}
}

The important thing to highlight is that the real close() method has no effect: in case a client code invoke this method, it has nothing to do. lazyClose() method is the one who close the actual EntityManager and is invoked by the HTTP request listener as you can see next.

Here is the HTTP request listener. Note it only closes the LazyCloseEntityManager bound to the current thread.

public class PersistenceAppRequestListener implements ServletRequestListener {

public void requestInitialized(ServletRequestEvent evt) {
}

public void requestDestroyed(ServletRequestEvent evt) {

PersistenceManager pm = PersistenceManager.getInstance();

if (pm instanceof ScopedPersistenceManager) {
LazyCloseEntityManager em = ((ScopedEntityManagerFactory)pm
.getEntityManagerFactory()).getEntityManager();

if (em != null)
em.lazyClose();
}
}
}

Client code using the request scope EntityManager


The only requirement (in addition to include the library jar file) for a client web application to use the request scope EntityManager is:

  • Define a web listener.
  • Determine the name of the Persistence Unit to use (optional).

Both modifications must be done in your web.xml deployment descriptor archive.

Configuring the web.xml archive

The name of the Persistence Unit that you want for this utility to use can be define as an init parameter in the deployment descriptor file web.xml:
<context-param>
<param-name>es.claro.persistence.PERSISTENCE_UNIT</param-name>
<param-value>MyPersistenceUnit</param-value>
</context-param>
Alternatively, you can define the name of the Persistence Unit programmatically by using this code:
PersistenceManager.setPersistenceUnit("MyPersistenceUnit");
If no Persistence Unit name is define neither within the web.xml archive nor using this code, an default name is assumed, that is "DefaultPU".

You also need to explicitly define a HTTP listener in the deployment descriptor file web.xml as follows:
<listener>
<description>Listener for managing EntityManager with request scope</description>
<listener-class>es.claro.persistence.PersistenceAppRequestListener</listener-class>
</listener>
Actually, this listener acts as a request listener and as a servlet context listener.
From an user perspective, this is the listener which lazily close the EntityManager of the current HTTP request, so it would be fatal to forget to define this listener.

Sample code

The only class to know is PersistenceManager.
Through this singleton, you can create the EntityManagerFactory instance needed to begin to work with JPA (What you'll obtain from PersistenceManager won't be actually an EntityManagerFactory object but a proxy subclass of this class).

Below is a sample code using this approach:
EntityManagerFactory emf = PersistenceManager.getInstance().getEntityManagerFactory();
EntityManager em = emf.createEntityManager();
try {
EntityTransaction t = em.getTransaction();
try {
t.begin();
...
t.commit();
} finally {
if (t.isActive()) em.getTransaction().rollback();
}
} finally {
em.close();
}
Note that this client code is the same for method scope, so switching between a scoped and non-scoped EntityManager strategy is completely transparent to the client code!

Simplifying client code

An optional enhancement to this design can be done.
Just to add PersistentManager.getScopedEntityManager() as as shortcut method.

By using this method in client code, closing the EntityManager each time you use it can be avoid
EntityManager em = PersistenceManager.getInstance().getScopedEntityManager();

try {
em.getTransaction().begin();
...
em.getTransaction().commit();
} finally {
if (em.getTransaction().isActive()) em.getTransaction().rollback();
}
Note this code is just trivial if no transaction is involved.

A little drawback for coding this way is that you no longer can switch between scoped and non-scoped EntityManager strategy without changing the client code!

Resources


The whole source code of the request scope entity manager has been developed with Netbeans and hosted as a little open source project at Google Code, so you can access both the source code as well as a jar file with the library ready to use.