4. JTA - JohnyzHub/EJB3x GitHub Wiki

Transaction properties:

Atomicity
Group of operations involved in a transaction should be performed as a single unit.
meaning, either all the operations are success or none of them.
Consistency
After the successful completion of the transaction, the data in db should be consistent,
meaning it should pass all defined constraints(such as keys, data types etc).
Isolation
The intermediate state of a transaction is invisible to other transactions.
meaning, external transactions should not see uncommitted data of the current transaction.
Durability
After the successful completion of the transaction, changes to data must be persist and should not be undone, even in the event of a system failure.


Commit Types

Single-Phase Commit
is a transaction that involves only a single resource(database).
Two Phase Commit
When a global transaction involves multiple databases, the changes to these resources must all be committed or rolled back at the same time. That is, when the transaction ends, the transaction manager contacts a coordinator--also known as a two-phase commit engine--to either commit or roll back all changes to all included databases. Two phase commit follows below two steps, before final commit of the transaction:
Prepare
Each resource manager is notified that a commit is about to be issued.
Commit
After receiving success/failure notifications from resource managers, the transaction manager contacts two phase commit engine(eg.oracle db) to either commit or rollback the changes to all the included databases.

Refer fig 9.4 of Beginning Java EE 7

Transaction types:

Resource_Local
Restricted to a single resource manager(db connection).
Entity manger is managed by the bean in java standalone environment.
EntityTransaction
This interface is used to control transactions on resource-local entity managers
JTA (Container Managed Transaction)
Supports distributed transactions.
In both CMT and BMT, the entity managers are controlled by JTA, if they reside in Java EE environment.
  • CMT : The transactions are managed by JTA with implicit commit.

  • BMT : The transactions are managed by JTA with explicit commit.

Implicit commit
The EJB container takes care to auto commit any transaction that it begins (when a method is called) will be concluded when the method returns back to the caller.
Explicit commit
The bean developer takes the burden of beginning and ending of a transaction and may call multiple methods explicitly during that time before concluding with an explicit call to either commit or rollback.

for BMP vs CMP: please refer jpa-concepts

@PersistenceContext
PersistenceContext is a managed set of entity instances from a single persistence unit. At any point of time, many persitencecontexts may be actively associated with any given peristence unit but a persistence context can be associated with at most one transaction context. Hence, only one persistence context from a given persistence unit can be actively associated with a transaction context.A persistence context is propagated through method calls so that entities in a persistence unit can see each other's intermediate state, through their common persistence context, whenever they are associated with the same transaction context. Within an application thread, EJB container is free to dissociate one persistence context from the thread and associate a new persistence context from the same persistence unit to satisfy transaction isolation boundaries. When EJB Container does this, the newly associated persistence context wouldn't able to see the intermediate changes made to any entities associated with the suspended persistence context.

Please refer page#382 from Beginning EJB in Java EE 8

The rule of thumb for the persistence context propagation is that the persistence context propagates as the JTA transaction propagates.

For more details refer section# JTA Transaction Management starting at Page#202 from Pro JPA2 in Java EE 8

@PersistenceContextType

  • Transaction(default) :: This creates persistence context when transaction is created and destroyed with transaction ends and all the entities that were managed by the entity manager becomes detached.means, it bounds to the life of a transaction. This is lazy initialization.
  • Extended :: This applies only to the stateful bean and bounds to the life of the bean.meaning that it persists from one transaction to the next, and allows associated entities to remain managed even after the transaction in which they were created has ended. The persistence context will be closed by the EJB container only when stateful bean instance is destroyed. This is eager initialization.

@SynchronizationType

  • Synchronized : Persistence context is automatically synchronized with the current transaction.
    This is the default value to the CMT session beans.
  • Unsynchronized: Persistence context must be explicitly joined to the current transaction.
    An unsynchronized persistence context regardless of whether joined or not, would never propagated to synchronized one.

EntityManager.joinTransaction() - Indicate to the entity manager that a JTA transaction is active and join the persistence context to it. For more details, Refer Join Transaction

Few notes on synchronization type:

  • Regardless of whether the persistence context has been joined to the transaction or not, the unsynchronized persistence context will be propagated when JTA transaction is propagated.
  • An unsynchronized persistence context regardless of whether it is joined or not, is never propagated into a synchronized one.

Persistence Context Collision:
The below situations may cause context collision and results IllegalStateException

  • A bean with transaction type persistence context makes a call to a stateful session bean with extended type.
    • The work around is to use Requires_New in the current method, so incoming transaction is suspended.
  • A stateful session bean instantiates another stateful session bean when both have extended type persistence context but different synchronization type.
    The work around is
    • either use Requires_New as mentioned in the above bullet point, so the incoming transaction will be suspended and the current bean's extended persistence context will be activated.
    • or have both the beans set with same synchronization type. In this case, the persistence context will be inherited and the child bean use the incoming transaction without causing persistence collision.


MDB supports only required and not_supported attributes.
TransactionAttribute doesn't apply to Bean managed transaction and results exception.

@DatasourceDefinition

@TransactionManagement

  • TransactionManagementType.Container(Default) - Container Managed Transaction
  • TransactionManagementType.Bean -- Bean managed transaction.
CMT Transaction Attributes
@TransactionAttribute
Applies to methods and fields.
  • Required (default) - Business method will be executed inside a transaction context.
    If the transaction not available a new transaction will be created.

  • Mandatory - Business method should be executed inside a transaction context.
    If the transaction does not available an exception will be raised.

  • Requires_New - Business method will always be executed inside a new transaction.
    The current transaction (if exist) will be temporarily suspended before the method invocation, and resumes after the method completion.

  • Supports - Method execution should be inside the client's transaction context, method will be executed without a transaction context if no transaction available.

  • Not_Supported - The method execution will always be outside transaction context, irrespective of the existence of the transaction.
    The current transaction (if exist) will be temporarily suspended before the method invocation, and resumes. after the method completion.

  • Never - The method execution must not be performed inside a transaction context. An exception will be raised if invoked inside a transaction.

    Check the detailed tabular form given in page#297 of Beginning Java EE 7

A good usecase for Not_Supported is, If a query that results list of entities is executed inside the transaction boundary the persistence provider takes efforts to convert the resulted entities into managed beans. If the application doesn't need these entities as managed beans that means if these resulted beans are for read-only purpose and no updates are intended, then this logic can be wrapped inside a method with NOT_SUPPORTED transaction attribute. This will cause the query to be executed outside the transaction boundary and the resulted entities will be left detached.


There are two ways to inform the container to rollback the transaction in case of failure.

  • SessionContext.setRollbackOnly() - Sets the flag for the container to perform rollback at the completion of transaction, in case of failure.
  • by throwing an exception.
    • When an application exception is marked for rollback true.
      Eg: @ApplicationException(rollback=true)
    • When system exception is thrown.
@Transactional
provides ability to declaratively control transaction boundaries on CDI managed beans at class and method level. This mechanism acts similar to EJB CMT.
If an attempt is made to call any method of the UserTransaction interface from within the scope of a bean or method annotated with @Transactional and @Transactional.TxType other than NOT_SUPPORTED or NEVER, an IllegalStateException must be thrown.

  • TxType - one of TransactionAttribute values
  • rollbackOn - rollbacks transaction on a set of declared exceptions.
  • donotrollbackon - do not perform rollback on a set of declared exceptions.
Bean Managed Transaction
UserTransaction
Get access of user transaction using @Resource or SessionContext and perform operations such as begin, commit and rollback.
Obtaining UserTransaction using EJBContext interface
  • Session bean : SessionContext.getUserTransaction()
  • MDB : messageDrivenContext.getUserTransaction()

Different ways of creating instance of entity manager

Container Managed transaction in Enterprise Environment:
EJB
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class SimpleEJB {
@PersistenceContext(unitName="PersistenceUnit",
              type=PersistenceContextType.TRANSACTION)             
private EntityManager em;
}

CDI

@Transactional
public class SimpleCDI {
@PersistenceContext(unitName="PersistenceUnit")             
private EntityManager em;
}

Bean Managed transaction in Enterprise Environment

EJB

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class SimpleEJB {
@PersistenceContext(unitName="PersistenceUnit")             
private EntityManager em;
@Resource
private UserTransaction ut;
public void method() {
ut.begin();
-----
em.persist(entity);
-----
ut.commit();
------
}
}

CDI

public class SimpleCDI {
@PersistenceUnit(unitName="PersistenceUnit")             
private EntityManagerFactory emf;
private EntityManager em = emf.createEntityManager();
}

Standard Environment:

private EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersistenceUnit");
private EntityManager em = emf.createEntityManager();
⚠️ **GitHub.com Fallback** ⚠️