Enterprise Java

JPA 2 | EntityManagers, Transactions and everything around it

Introduction

One of the most confusing and unclear thing for me, as a Java Developer has been the mystery surrounding the Transaction Management in general and how JPA handles transaction management in particular. When does a transaction get started, when does it end, how entities are persisted, the persistence context and much more. Frameworks like Spring does not help in understanding the concepts either as they provide another layer of abstraction which makes thing difficult to understand. In today’s post, I will try to demystify some of the things behind JPA’s specification about Entity Management, its transaction specifications and how a better understanding of the concept help us design and code effectively. We will try to keep the discussion
 
technology and framework agonistic although we will look at both Java SE(where the Java EE container is not available) and Java EE based examples.

Basic Concepts

Before diving into greater details lets quickly walk through some basic classes and what they mean in JPA.

  1. EntityManager – A class that manages the persistent state(or lifecycle) of an entity.
  2. Persistence Unit – is a named configuration of entity classes.
  3. Persistence Context – is a managed set of entity instances. The entities classes are part of the Persistence Unit configurations.
  4. Managed Entities – an entity instance is managed if it is part of a persistence context and that Entity Manager can act upon it.

From bullet point one and three above, we can infer that an Entity Manager always manages a Persistence Context. And so, if we understand the Persistence Context, we will understand the EntityManager.

Details

EntityManager in JPA

There are three main types of EntityManagers defined in JPA.

  • Container Managed and Transaction Scoped Entity Managers
  • Container Managed and Extended Scope Entity Managers
  • Application Managed Entity Managers

We will now look at each one of them in slightly more detail.

Container Managed Entity Manager

When a container of the application(be it a Java EE container or any other custom container like Spring) manages the lifecycle of the Entity Manager, the Entity Manager is said to be Container Managed. The most common way of acquiring a Container Managed EntityManager is to use @PersistenceContext annotation on an EntityManager attribute. Heres an example to define an EntityManager.

public class EmployeeServiceImpl implements EmployeeService { 
    @PersistenceContext(unitName="EmployeeService") 
    EntityManager em; 

    public void assignEmployeeToProject(int empId, int projectId) { 
        Project project = em.find(Project.class, projectId); 
        Employee employee = em.find(Employee.class, empId); 
        project.getEmployees().add(employee); 
        employee.getProjects().add(project); 

    } 

In the above example we have used @PersistenceContext annotation on an EntityManager type instance variable. The PersistenceContext annotation has an attribute “unitName” which identifies the Persistence Unit for that Context.

Container Managed Entity Managers come in two flavors :

  1. Transaction Scoped Entity Managers
  2. Extended Scope Entity Managers

Note that the scope above really means the scope of the Persistence Context that the Entity Manager manages. It is not the scope of the EntityManager itself.

Lets look at each one of them in turn.

Transaction Scoped Entity Manager

This is the most common Entity Manager that is used in the applications. In the above example as well we are actually creating a Transaction Scoped Entity Manager. A Transaction Scoped Entity Manager is returned whenever a reference created by @PersistenceContext is resolved.

The biggest benefit of using Transaction Scoped Entity Manager is that it is stateless. This also makes the Transaction Scoped EntityManager threadsafe and thus virtually maintenance free. But we just said that an EntityManager manages the persistence state of an entity and the persistence state of an entity is part of the persistence context that get injected into the EntityManager. So how is the above statement on stateless holds ground?

The answer lies in the fact that all Container Managed Entity Managers depend on JTA Transactions. Every time an operation is invoked on an Entity Manager, the container proxy(the container creates a proxy around the entity manager while instantiating it ) checks for any existing Persistence Context on the JTA Transaction. If it finds one, the Entity Manager will use this Persistence Context. If it doesnt find one, then it will create a new Persistence Context and associates it with the transaction.

Lets take the same example we discussed above to understand the concept of entity managers and transaction creation.

public class EmployeeServiceImpl implements EmployeeService { 
    @PersistenceContext(unitName="EmployeeService") 
    EntityManager em; 

     public void assignEmployeeToProject(int empId, int projectId) { 
        Project project = em.find(Project.class, projectId); 
        Employee employee = em.find(Employee.class, empId); 
        project.getEmployees().add(employee); 
        employee.getProjects().add(project); 

     } 

 

In the above example the first line of assignEmployeeToProject method is calling a find method on the EntityManager. The call to find will force the container to check for an existing transaction. If a transaction exists( for example in case of Stateless Session Beans in Java EE, where the container guarantees that a transaction is available whenever a method on the bean is called) or not. If the transaction doesnt exist, it will throw Exception. If it exists, it will then check whether a Persistence Context exists. Since its the first call to any method of the EntityManager, a persistence context is not available yet. The Entity Manager will then create one and use it to find the project bean instance.

In the next call to find, the Entity Manager already has an associated Transaction as well as the Persistence Context associated with it. It uses the same transaction to find employee instance. By the end of 2nd line in the method both project and employee instance are managed. At the end of the method call, the transaction is committed and the managed instances of person and employee get persisted. Another thing to keep in mind is that when the transaction is over, the Persistence Context goes away.

Extended Scope Entity Manager

If and when you want the Persistence Context to be available beyond the scope of a method, you use the Entity Manager with extended scope.  The best way to understand the Extended scope Entity Manager is to take an example where the class needs to maintain some state(which is created as a result of some transactional request like myEntityManager.find(“employeeId”) and then using the employee) and share the state across its business methods.

Because the Persistence Context is shared between method calls and is used to maintain state, it is generally not Thread safe unless you are using them inside a Stateful session bean for which the container is responsible for making it thread safe. To reiterate, in case you are using Java EE Container, Extended Scope Entity Managers will be used inside a Stateful Session Bean( Class annotated with @Stateful) . If you decide to use it outside of the Stateful bean, the container does not guarantee you thread saftey and you have to handle that yourself. Same is the case if you are using third party containers like Spring.

Lets look at an example of Extended Scope Entity Manager in Java EE environment when using Stateful session beans.

Our goal in the example would be to create a business Class that has business methods working on an instance of LibraryUser Entity.  Lets call this business class LibraryUserManagementService that has a business interface UserManagementService. LibraryUserManagementService works on LibraryUsers entity instance . A Library can lend multiple books to the LibraryUser.

Heres an example of Stateful Session bean depicting the above scenario.

@Stateful 
public class LibraryUserManagementService implements UserManagementService { 
    @PersistenceContext(unitName="UserService") 
    EntityManager em; 
    LibraryUser user; 

    public void init(String userId) { 
        user = em.find(LibraryUser.class, userId); 
    } 

    public void setUserName(String name) { 
        user.setName(name); 
    } 

    public void borrowBookFromLibrary(BookId bookId) { 
        Book book = em.find(Book.class, bookId); 
        user.getBooks().add(book); 
        book.setLendingUser(user); 
    } 

    // ... 

    @Remove 
    public void finished() { 
    } 
} 

In the above scenario where we are working with a user instance, it is more natural to get an instance once and then work our way through it and only when we are done, we should persist the user instance. But, the problem is that the Entity Manager is Transaction Scoped. This means that init will run in its own transaction(thus having its own Persistence Context) and borrowBookFromLibrary will run in its own transaction. As a result, user object becomes unmanaged as soon as the init method ends.

To overcome exactly this sort of problem, we make use of PersistenceContextType.EXTENDED type Entity Manager.

Heres the modified example with PersistenceContextType EXTENDED that will work perfectly.

@Stateful 
public class LibraryUserManagementService implements UserManagementService { 
    @PersistenceContext(unitName="UserService" , type=PersistenceContextType.EXTENDED) 
    EntityManager em;

    LibraryUser user; 

    public void init(String userId) { 
        user = em.find(LibraryUser.class, userId); 
    } 

    public void setUserName(String name) { 
        user.setName(name); 
    } 

    public void borrowBookFromLibrary(BookId bookId) { 
        Book book = em.find(Book.class, bookId); 
        user.getBooks().add(book); 
        book.setLendingUser(user); 
    } 

    // ... 

    @Remove 
    public void finished() { 
    } 
}

In the above scenario, The PersistenceContext that manages the user instance is created at the Bean initialization time by the Java EE Container and is available until the finished method is called at which time the transaction is committed.

Application Scoped Entity Manager

An Entity Manager that is created not by the container, but actually by the application itself is an application scoped Entity Manager. To make the definition clearer, whenever we create an Entity Manager by calling createEntityManager on the EntityManagerFactory instance, we  actually are creating an application scoped Entity Manager. All the Java SE based applications actually use Application Scoped Entity Managers. JPA gives us a class Persistence that is used to ultimately create an Application Scoped Entity Manager.

Heres an example of how an application scoped EM can be created :

EntityManagerFactory emf = 
            Persistence.createEntityManagerFactory("myPersistenceUnit"); 
        EntityManager em = emf.createEntityManager(); 

Note that for creating an Application Scoped EntityManager, there needs to be a persistence.xml file in the META-INF folder of the application.

EntityManager can be created in two ways. One is already shown above. Another way to create EntityManager is to pass a set of properties as parameter to the
createEntityManagerFactory method.

EntityManagerFactory emf = 
            Persistence.createEntityManagerFactory("myPersistenceUnit" , myProperties); 
        EntityManager em = emf.createEntityManager();

If you are creating your own Application Managed Entity Manager, then make sure to close it everytime you are done with using it. This is required because you are now managing how and when the EntityManager should be created and used.

Transaction Management

Transactions are directly related to entities. Managing transactions essentially then would mean managing how entities lifecycle(create, update delete) is managed. Another key to understanding Transaction Management is to understand how Persistence Contexts interacts with transactions. It is worth noting that from an end user perspective, even though we work with an instance of EntityManager, the only role of EntityManager is to determine the lifetime of the Persistence Context. It plays no role in dictating how a Persistence Context should behave. To reiterate, Persistence Context is a managed set of Entity instances. Whenever a transaction begins, a Persistence Context instance gets associated with it. And when a Transaction ends(commits for example), the Persistence Context is flushed and get disassociated with the transaction.

There are two types of Transaction management types supported in JPA.

  • RESOURCE LOCAL Transactions
  • JTA or GLOBAL Transactions

Resource local transactions refer to the native transactions of the JDBC Driver whereas JTA transactions refer to the transactions of the JEE server. A Resource Local transaction involves a single transactional resource, for example a JDBC Connection. Whenever you need two or more resources(f or example a JMS Connection and a JDBC Connection) within a single transaction, you use  JTA Transaction.
Container Managed Entity Managers always use JTA transactions as the container takes care of transaction life cycle management and spawning the transaction across multiple transactional resources. Application Managed Entity Managers can use either Resource Local Transactions or JTA transactions.

Normally in JTA or global transaction, a third party transaction monitor enlists the different transactional resources within a transaction, prepares them for a commit and finally commits the transaction. This process of first preparing the resources for transaction(by doing a dry run) and then committing(or rolling back) is called a 2 phase commit.

Side Note about XA Protocol– In global transactions, a transaction monitor has to constantly talk to different transactional resources. Different transactional resources can speak different languages and thus may not be understandable to the transaction monitor. XA is a protocol specification that provides a common ground for the transaction monitor to interact with different transactional resources. JTA is a global transaction monitor specification that speaks XA and thus is able to manage multiple transactional resources. Java EE compliant servers has implementation for JTA built in. Other containers like Spring write their own or use others implementation(like Java Open Transaction Manager , JBoss TS etc) for supporting JTA or Global transactions.

Persistence Context, Transactions and Entity Managers

A Persistence Context can be associated with either single or multiple transactions and can be associated with multiple Entity Managers. A Persistence Context gets registered with a transaction so that persistence context can be flushed when a transaction is committed. The When a transaction starts, the Entity Manager looks for an active Persistence Context instance. If it is not available it creates one and binds it to the transaction. Normally the scope of the persistence context is tightly associated with the transaction. When a transaction ends, the persistence context instance associated with that transaction also ends. But sometime, mostly in the Java EE world, we require transaction propagation, which is the process of sharing a single persistence context between different Entity Managers within a single transaction.

Persistence Contexts can have two scopes:

  • Transaction Scoped Persistence Context
  • Extended Scoped Persistence Context

We have discussed transaction/extended scoped Entity Managers and we also know that Entity Managers can be transaction or extended scoped. The relation is not coincidental. A Transactional scoped Entity Manager creates a Transaction scoped Persistence Context. An Extended Scope Entity Manager uses the Extended Persistence Context. The lifecycle of the Extended Persistence Context is tied to the Stateful Session Bean in the Java EE environment.

Let’s briefly discuss these Persistence Contexts

Transaction Scoped Persistence Context

TSPC is created by the Entity Managers only when it is needed. Transaction scoped Entity Manager creates a TSPC only when a method on the Entity Manager is called for the first time. Thus the creation of Persistence Context is lazy. If there already exists a propagated Persistence Context, then the Entity Manager will use that Persistence Context.

Understanding of Persistence Context Propagation is important to identify and debug transaction related problems in your code. Let’s see an example of how a transaction scoped persistence context is propagated.

ItemDAOImpl.java  :

public class ItemDAOImpl implements ItemDAO { 
    @PersistenceContext(unitName="ItemService") 
    EntityManager em; 

    LoggingService ls; 

    @TransactionAttribute()
    public void createItem(Item item) { 
        em.persist(item); 
        ls.log(item.getId(), "created item"); 
    } 

    // ... 
}  

LoggingService.java :

public class LoggingService implements AuditService { 
    @PersistenceContext(unitName="ItemService") 
    EntityManager em; 
    
    @TransactionAttribute()
    public void log(int itemId, String action) { 
        // verify item id is valid 
        if (em.find(Item.class, itemId) == null) { 
            throw new IllegalArgumentException("Unknown item id"); 
        } 
        LogRecord lr = new LogRecord(itemId, action); 
        em.persist(lr); 
    } 

} 

When createItem method of ItemDAOImpl is called, persist method is called on the entity manager instance. Let’s assume that this is the first call to the entity manager’s method. The Entity Manager will look for any propagated persistence context with Unit Name “ItemService”. It doesn’t find one because this is the first call to the entity manager. Thus it creates a new persistence context instance and attaches it to itself. It then goes on to persist the Item object. After the item object is persisted, we then call to log the item information that is just persisted. Note that the LoggingService has its own EnitityManager instance and the method log has the annotation @TransactionAttribute(which is not required if in Java EE envt and the bean is declared to be an EJB).
Since the TransactionAttribute has a default TransactionAttributeType of REQUIRED, the Entity Manager in the LoggingService will look for any Persistence Context that might be available from the pervious transaction. It finds one that was created inside the createItem method of the ItemDAOImpl and uses the same one. That is why, even though the actual item is not yet persisted to the Database(because the transaction has not yet been committed), the entity manager in LoggingService is able to find it because the Persistence Context has been propagated from the ItemDAOImpl to the LoggingService.

Extended Persistence Context

Whereas Transaction Scoped Persistence Context is created one for every transaction(in case of non propagation), the Extended Persistence Context is created once and is used by all the transactions within the scope of the class that manages the lifecycle of the Extended Persistence Context. In case of Java EE, it is the Stateful Session bean that manages the lifecycle of the extended Persistence context.  The creation of Stateful Session bean is EAGER. In case of Container Managed Transactions, it is created as soon as a method on the class is called. In case of Application managed Transaction it is created when userTransaction.begin() is invoked.

Summary

A lot of things have been discussed in this blog post, Entity Managers, Transaction Management, Persistence Context , how all these things interact and work with each others.

We discussed differences between Container Managed and Application Managed Entity Managers, Transaction Scoped and Extended scope Persistence Context, Transaction propagation. Most of the material for this blog is a result of reading the wonderful book :  Pro JPA 2 . I would recommend reading it if you want more indepth knowledge of how JPA works.
 

Anuj Kumar

Anuj is working as a Senior S/W Engineer in Netherlands. He is a Sun Certified Java Professional with experience in design and development of mid/large scale Java applications. He is the creator of EasyTest Framework(https://github.com/EaseTech) which is a Data Driven Testing Framework for Java.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

6 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Manjunath Anand
Manjunath Anand
9 years ago

Hi Anuj,

Absolutely wonderful explanation. Just the thing that I wanted. Very precise explanation of key concepts which are mostly misunderstood. Thanks a lot for sharing this information and wishing you the very best.

Regards,
Manjunath Anand

Allan Jun Li
Allan Jun Li
9 years ago

In Extended Scope Entity Manager section, last paragraph, you mentioned transaction commit, that’s a bit confusing I reckon. It kind of implies that the transaction stays open during all those method calls and only commits when finished method is called for SFSB. I’m sure you know that’s not the case.

Anuj Kumar
9 years ago

Hi Allan,
There is one line missing from the java code depicted in Extended Scope Entity Manager’s @Remove method :

em.persist();

I hope that clears up some thing.

Allan Jun Li
Allan Jun Li
9 years ago
Reply to  Anuj Kumar

Actually, that’s more confusing, why do you call em.persist(), which object are you persisting, you didn’t create any new entity in any of your methods.

Anuj Kumar
9 years ago

Indeed you are correct. Theres no need to call persist as theres no new entity being created in my code. I was referencing the code I had when I wrote the blog.
What probably I should have clarified is that even after the entity is out of transaction it is still considered a managed entity. And only when the finish method is called, the entity becomes detached from the Persistence Context and is thus no more a managed entity.

Thanks for pointing that out. I will update the Blog.

Do let me know if you have any more comments.

Allan Jun Li
Allan Jun Li
9 years ago
Reply to  Anuj Kumar

That’s very clear now.

I’m suggesting to think of Entity Manager as a reference to the Persistence Context. In the case of transaction propagation and extended scope, we just have multiple references pointing to the same Persistence Context.

Back to top button