Search code examples
javajpajakarta-eetransactionsentitymanager

Will an EntityManager with context type TRANSACTION in a Singleton join an external bean-managed transaction?


Suppose I have a Singleton bean with an EntityManager in it. The singleton also specifies (on method or class level) a transaction attribute REQUIRED. The entity manager is obtained via an @PersistenceContext injection which specifies persistence context type TRANSACTION. For all intents and purposes, if a method on this singleton is invoked with an existing transaction, the entity manager should join the transaction or possibly provide an already existing one linked to that transaction via proxy. If such a method is invoked outside of a transaction a new transaction will be started for the duration of the method invocation.

Now suppose we have a second bean which uses bean-managed transactions and injects the singleton. If it explicitly starts a user transaction and then invokes a method on the singleton, will the entity manager in that method join that user transaction? Will the jump from bean-managed to container-managed transaction context even work? I know the other way around doesn't and forms a barrier.

The singleton class:

@Singleton
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class PersistenceSingleton {

    @PersistenceContext(unitName = "test", type = PersistenceContextType.TRANSACTION)
    private EntityManager em;

    public void doStuff() {

        // perform actions with the entity manager that imply changes in the database

    }

}

The bean with user transactions (might as well be stateless or stateful):

@Singleton
@TransactionManagement(TransactionManagementType.BEAN)
public class PersistenceFacade {

    @EJB
    private PeristenceSingleton ps;

    @Resource
    private UserTransaction userTx;

    public void doStuff() {
        userTx.begin();
        ps.doStuff();
        userTx.commit();
    }

}

Does the transaction started in method doStuff() of the PersistenceFacade get taken into account when invoking doStuff() on the PersistenceSingleton? Does the entity manager automatically join the transaction and behave as expected from transaction isolation during concurrent access?


Solution

  • UserTransaction is used for changing the default transaction demarcation but we still control the JTA transactions.

    https://www.javacodegeeks.com/2013/03/types-of-entity-managers-application-managed-entitymanager.html says:

    If you have UserTransaction you can start demarcating what is to be executed within the transaction. Notice that you’re still controlling the JTA transactions

    so The persistence context propagation rule will be applied for UserTransaction demarcation.

    pro JPA book says:

    When a method is invoked on the transaction-scoped entity manager, it must first see whether there is a propagated persistence context. If one exists, the entity manager uses this persistence context to carry out the operation. All subsequent transaction-scoped entity manager operations, in this component or any other, will thereafter use this newly created persistence context. This behavior works independently of whether container-managed or bean-managed transaction demarcation has been used.

    the answer to your questions is yes(first question)

    Does the entity manager automatically join the transaction and behave as expected from transaction isolation during concurrent access?

    entity manager checks the existence of a propagated persistence context and uses it.