When a transaction executes as part of a stateful session bean, the bean can receive synchronous notifications of the progress of the transaction using the SessionSynchronization
interface. While there is not a specific field or variable which indicates the state of a transaction when using CMT, the invocation of one of its interface methods implies the transaction's state.
One possible use of this technique is to synchronize the instance variables of the bean to their corresponding values in a database. In this recipe, we will examine how the interface works. In the next recipe, Understanding how the TransactionAttributeType affects transactions, we will demonstrate how CMT work with different transaction attribute type settings.
The steps for using the SessionSynchronization
interface include:
In order for a stateful session bean to become aware of the state of a transaction, it must implement the SessionSynchronization
interface. The methods of this interface include:
The afterBegin
method is invoked before the business method is invoked. Any special processing needed by the session bean may be performed at this time.
The beforeCompletion
method provides an opportunity for the session bean to rollback the transaction using the setRollbackOnly
method. The transaction is not rolled back at this time but the use of the method will eventually result in rolling back of the transaction.
The afterCompletion
method receives a Boolean value. A value of true is received when the transaction is committed. A value of false is received when the transaction is rolled back.
Modify the CityFacade
class to implement the SessionSynchronization
interface. Add println
statements to reflect the execution of the methods.
@Stateful @TransactionManagement(TransactionManagementType.CONTAINER) public class CityFacade extends AbstractFacade<City> implements SessionSynchronization { ... @Override public void afterBegin() throws EJBException, RemoteException { System.out.println(" CityFacade afterBegin"); } @Override public void beforeCompletion() throws EJBException, RemoteException { System.out.println("CityFacade beforeCompletion"); } @Override public void afterCompletion(boolean committed) throws EJBException, RemoteException { System.out.println("CityFacade afterCompletion "); } }
By default, each method of the CityFacade
requires a transaction. To illustrate the execution of the transaction, we will modify the remove
and findAll
methods of the AbstractFacade
class by adding println
methods showing when the methods are executed.
public void remove(T entity) { System.out.println("--- AbstractFacade remove - " + this.getClass().getSimpleName()); getEntityManager().remove(getEntityManager().merge(entity)); } public List<T> findAll() { System.out.println("--- AbstractFacade findAll - " + this.getClass().getSimpleName()); javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); cq.select(cq.from(entityClass)); return getEntityManager().createQuery(cq).getResultList(); }
In the PopulationServlet
, modify the processRequest
method and use the following code sequence for the body of the try block:
clearTables(); out.println("<html>"); out.println("<head>"); out.println("<title>Servlet PopulationServlet</title>"); out.println("</head>"); out.println("<body>");
Execute the PopulationServlet
. The browser output should be empty; however, the console window for the server should appear as follows. Notice the start and end of the transactions when the CityFacade's findAll
and remove
methods are invoked from within the clearTables
methods. Using the methods of the SessionSynchronization
interface clearly illustrates the use of transactions.
INFO: CityFacade afterBegin
INFO: --- AbstractFacade findAll - _CityFacade_Serializable
INFO: CityFacade beforeCompletion
INFO: CityFacade afterCompletion
INFO: CityFacade afterBegin
INFO: --- AbstractFacade remove - _CityFacade_Serializable
INFO: CityFacade beforeCompletion
INFO: CityFacade afterCompletion
When the servlet was executed, the clearTables
method was called. This method called the findAll
and remove
methods. As these two methods executed, the SessionSynchronization
interface methods were executed.
Within the findAll
and remove
methods, the getClass
method was executed against the Java keyword: this
. It returns a reference to a java.lang.Class
object for the current object. The getSimpleName
method returned a simple name which was then displayed.
18.220.152.139