4. JTA - JohnyzHub/EJB3x GitHub Wiki
Transaction properties:
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. 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). The intermediate state of a transaction is invisible to other transactions.
meaning, external transactions should not see uncommitted data of the current transaction. 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
Each resource manager is notified that a commit is about to be issued. 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:
Entity manger is managed by the bean in java standalone environment. This interface is used to control transactions on resource-local entity managers
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.
for BMP vs CMP: please refer jpa-concepts
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.
-
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.
- When an application exception is marked for rollback true.
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.
Obtaining UserTransaction using EJBContext interface
- Session bean : SessionContext.getUserTransaction()
- MDB : messageDrivenContext.getUserTransaction()
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();