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:
- An EntityManager is not a heavyload object.
- 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 relationshipsAs 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 archiveThe 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 codeThe 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 codeAn 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.