Container vs Application Managed EntityManager

22 January 2015
By Gonçalo Marques
In this article we will cover Container vs Application Managed EntityManager (Persistence Context) and its relationship with JTA or RESOURCE LOCAL transaction management.

Persistence Context and Entity Manager

The Persistence Context and the Entity Manager are two core concepts of the Java Persistence API (JPA). In short:

  • The Persistence Context is responsible for JPA entity management: When an application loads an entity from the database, the entity is in fact stored in the Persistence Context, so the entity becomes managed by the Persistence Context. Any further change made over that same entity will be monitored by the Persistence Context.

    The Persistence Context will also flush changed entities to the database when appropriate. When a transaction commits, the associated Persistence Context will also flush any eventual pending changes to the Database. These are some of the operations that are handled by the Persistence Context.

  • The Entity Manager is an interface for the application to interact with the Persistence Context.

There are two distinct types of Persistence Context: Container Managed and Application Managed.

The Container Managed Persistence Context - as the name states - is managed by the enterprise container. The container is responsible for Persistence Context injection into enterprise components, and is also responsible for its disposal at the end of the current transaction.

The Application Managed Persistence Context is managed by the application: The application is responsible for Persistence Context creation and disposal. The application is also required to ensure that the application created Persistence Context is aware of any eventual ongoing transaction.

In the next sections we will see how these two distinct types of Persistence Context interact with the available types of Transaction Management: JTA and Resource Local.

As a side note to this article, an Application Managed Persistence Context scope is always EXTENDED (see JPA EXTENDED Persistence Context).

Container Managed Persistence Context

A Container Managed Persistence Context is injected into an enterprise component by using the @PersistenceContext annotation:


@PersistenceContext
EntityManager entityManager;

The enterprise container is responsible for ensuring that the Persistence Context is aware of any ongoing transaction. It will also propagate the Persistence Context between distinct enterprise components. Example: An EJB calls another EJB that shares the same transaction of the first one. If they both declare a container managed Persistence Context, the container will make sure that the Persistence Context is propagated between the distinct EJBs.

A Container Managed Persistence Context may only be used with JTA:


<persistence-unit name="persistenceUnit" transaction-type="JTA">
  <jta-data-source>jdbc/dataSource</jta-data-source>
  <class>test.domain.TestEntity</class>
</persistence-unit>

This is valid for both Container Managed Transaction (CMT) and Bean Managed Transaction (BMT) components:

Valid usage of Container Managed Persistence Context with CMT

@Stateless
public class TestServiceBean {

  @PersistenceContext
  private EntityManager entityManager;

  @Override
  public void test() {
    TestEntity entity = new TestEntity();
    entity.setDescription("test");
    entityManager.persist(entity);
  }

}

Since we are using CMT, the container will be responsible for ensuring that the method is executed within the boundaries of an active transaction. The container will also make sure that the injected Persistence Context - which is container managed - is aware of the current active transaction. When the transaction is ready for commit, the Persistence Context will automatically flush any changes to the database.

Valid usage of Container Managed Persistence Context with BMT

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class TestServiceBean {

  @PersistenceContext
  private EntityManager entityManager;

  @Resource
  private UserTransaction userTransaction;

  public void test() throws Exception {
    TestEntity entity = new TestEntity();
    entity.setDescription("test");

    userTransaction.begin();
    entityManager.persist(entity);
    userTransaction.commit();
  }

}

Now we are using declarative bean transaction management (note the @TransactionManagement annotation). The EJB will interact with the JTA Transaction Manager through the UserTransaction interface in order to begin, commit or rollback an arbitrary transaction.

Since the Persistence Context is container managed - and JTA aware as we have seen before - it will automatically be aware of the JTA transaction that is started by the EJB. during transaction commit the Persistence Context will flush any changes to the database.

As we have seen earlier, a container managed Persistence Context may only be used with JTA. This means that the following configuration - Resource Local transaction management - is invalid for a container managed Persistence Context:


<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
  <non-jta-data-source>jdbc/dataSource</non-jta-data-source>
  <class>test.domain.TestEntity</class>
</persistence-unit>

We may not inject a Persistence Context configured as RESOURCE_LOCAL using the @PersistenceContext annotation (once again, a RESOURCE_LOCAL Persistence Context may not be container managed).

Application Managed Persistence Context

An Application Managed Persistence Context - as the name states - is managed by the application. The application is responsible for the context creation and disposal.

An EntityManagerFactory is injected into enterprise components by the means of the @PersistenceUnit annotation. The enterprise component is then able to fetch an EntityManager instance from the EntityManagerFactory and use it in order to interact with the Persistence Context.

The application managed Persistence Context may be used with both JTA and Resource Local transaction management.

First we will see the Resource Local transaction management scenario. Consider that our persistence context is configured as RESOURCE_LOCAL:


<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
  <non-jta-data-source>jdbc/dataSource</non-jta-data-source>
  <class>test.domain.TestEntity</class>
</persistence-unit>

Since we are using Resource Local transaction management, the application must manage the transaction completely by itself. This means that the application must get an instance of EntityTransaction from the EntityManager and proceed with the usual transactional instructions, as seen in the following example:

Application Managed Persistence Context with Resource Local transaction management

@Stateless
public class TestServiceBean {

  @PersistenceUnit
  private EntityManagerFactory entityManagerFactory;

  public void test() {

    TestEntity entity = new TestEntity();
    entity.setDescription("test");

    EntityManager entityManager = entityManagerFactory.createEntityManager();
    EntityTransaction entityTransaction = entityManager.getTransaction();

    entityTransaction.begin();
    entityManager.persist(entity);
    entityTransaction.commit();

    entityManager.close();

  }

}

The application must fetch the transaction instance from the Entity Manager itself and execute the usual transaction demarcation instructions (begin/commit/rollback). The Persistence Context must be closed by the application.

It is not possible for a Resource Local Persistence Context to interact with a JTA transaction (as expected).

Finally we will now see how an Application Managed Persistence Context may be used with JTA. For this we must configure our Persistence Context as JTA:


<persistence-unit name="persistenceUnit" transaction-type="JTA">
  <jta-data-source>jdbc/dataSource</jta-data-source>
  <class>test.domain.TestEntity</class>
</persistence-unit>

The application managed Persistence Context may be used with Container Managed Transaction (CMT):

Valid Application Managed Persistence Context usage with CMT

@Stateless
public class TestServiceBean {

  @PersistenceUnit
  private EntityManagerFactory entityManagerFactory;

  public void test() {

    TestEntity entity = new TestEntity();
    entity.setDescription("test");

    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.persist(entity);
    entityManager.close();

  }

}

Since we are using CMT, the container will ensure that an active transaction exists during the EJB method execution. The Persistence Context is created within the active transaction, and since it is JTA aware, it will automatically join the current transaction.

Note that we also need to close the application managed Persistence Context at the end.

The application managed Persistence Context may also be used with Bean Managed Transaction (BMT):

Valid Application Managed Persistence Context usage with BMT

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class TestServiceBean {

  @Resource
  private UserTransaction userTransaction;

  @PersistenceUnit
  private EntityManagerFactory entityManagerFactory;

  public void test() throws Exception {

    TestEntity entity = new TestEntity();
    entity.setDescription("test");

    userTransaction.begin();

    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.persist(entity);

    userTransaction.commit();

    entityManager.close();

  }

}

In BMT the application must interact with the JTA transaction manager through the UserTransaction interface. Since the EntityManager is created after userTransaction.begin() it means that an active transaction exists during the Persistence Context creation. Since the Persistence Context is JTA aware, it will automatically join the current active transaction.

What if we happen to create the EntityManager before starting the transaction? Like the following example:

Application Managed Persistence Context created before the JTA transaction

public void test() throws Exception {

  TestEntity entity = new TestEntity();
  entity.setDescription("test");

  EntityManager entityManager = entityManagerFactory.createEntityManager();

  userTransaction.begin();
  entityManager.persist(entity);

  // Changes will NOT be commited
  userTransaction.commit();

  entityManager.close();

}

In this case, the pending changes in the Persistence Context will not be persisted to the database. The EntityManager was created before any active transaction existed, and since the Persistence Context is application managed it will not automatically join a transaction that is started after the Persistence Context creation itself.

In order for this to happen, the application must instruct the Persistence Context to join the current transaction:

Application Managed Persistence Context joining the JTA transaction

public void test() throws Exception {

  TestEntity entity = new TestEntity();
  entity.setDescription("test");

  EntityManager entityManager = entityManagerFactory.createEntityManager();

  userTransaction.begin();

  // Join active transaction
  entityManager.joinTransaction();

  entityManager.persist(entity);

  // Changes will be commited
  userTransaction.commit();

  entityManager.close();

}

Now the Persistence Context will join the previously created transaction and consequently the pending changes will be persisted in the database.

As a final note it is worth to say that in a JTA Application Managed Persistence Context we may not interact with the EntityTransaction. The EntityTransaction is to be used exclusively by the Application Managed Resource Local Persistence Context. This means that the following will fail in a JTA Persistence Context:


// Will fail in a JTA Persistence Context
EntityTransaction transaction = entityManager.getTransaction();

Related Articles

Comments

About the author
Gonçalo Marques is a Software Engineer with several years of experience in software development and architecture definition. During this period his main focus was delivering software solutions in banking, telecommunications and governmental areas. He created the Bytes Lounge website with one ultimate goal: share his knowledge with the software development community. His main area of expertise is Java and open source.

GitHub profile: https://github.com/gonmarques

He is also the author of the WiFi File Browser Android application: