package study.ejb2.transaction.cmt.stateful; import javax.ejb.SessionBean; import javax.ejb.SessionContext; import javax.ejb.SessionSynchronization; /** * When using CMT we need declared the attributes which will role * the behavior. * * The transaction attribute can be: * > Required * If the method is called with an existing transaction context, the method * runs in that transaction. Otherwise the Container will start a new one. * > RequiresNew * The method will always run with a new transaction. If the method is called * with an existing transaction context, the caller's transaction is suspended * until this method completes. * > Mandatory * The method requires an existing transaction. If the method is called without * an existing transaction context, the Container will throw an exception. * > Supports * Doesn't metter if the caller has or not a transaction context. If it has the * method runs in the same transaction, otherwise runs with an "unspecified * transaction context". * > NotSupported * Always runs with an "unspecified transaction context". If the caller has a * transaction, it will be suspended. * > Never * The method requires an "unspecified transaction context". If the method is * called with an existing transaction context, the Container will throw an * exception. * * The Container will rollback only if we tell to do it (calling setRollbackOnly) * or if we throw a system exception (unchecked - runtime), like EJBException. * * The interface SessionSynchronization allows the bean to have 3 new lifecycle * methods, those methods will be called when a transaction starts, ends and * commit/rollback. */ public class EjbStatefulDiceBean implements SessionBean, SessionSynchronization { private static final long serialVersionUID = -625509719560931198L; private SessionContext ctx; public void setSessionContext(SessionContext ctx) { System.out.println("setSessionContext"); this.ctx = ctx; } public void ejbCreate() { System.out.println("ejbCreate"); } public void ejbActivate() { System.out.println("ejbActive"); } public void ejbPassivate() { System.out.println("ejbPassivate"); } public void ejbRemove() { System.out.println("ejbRemove"); } /** * This method runs in a transactional state. If this beans will be deployed * as a Stateless Bean so it MUST start and finish the transaction in the same * method (only Entity Bean can start in one method and finish in another). */ public int rollDiceInAcid() { // tells to Container rolls back ctx.setRollbackOnly(); return (int) (Math.random() * 6) + 1; } /* * The following method are from SessionSynchronization, they extend the capability * of the bean to know when the transaction start, end and commit or rollback. * We can use only with Stateful Session Bean, because Stateful has state of a specific * client, so we can persiste or load data from database before or after the business * method (like ejbStore and ejbLoad of an Entity bean). */ /** * This method is called just after the transaction has started and before the business * method run. * Here we can do anything, we have a "meaningful transaction context". * @see javax.ejb.SessionSynchronization#afterBegin() */ public void afterBegin() { System.out.println("The transaction has started"); } /** * This method is called just before the transaction ends and after the business * method completes. * Here we can do anything, we still have a "meaningful transaction context". * @see javax.ejb.SessionSynchronization#beforeCompletion() */ public void beforeCompletion() { System.out.println("About to end the transaction"); } /** * This method is called after the transaction has ended either in a commit or rollback. * The given boolean indicates if the transaction was commited (when is true) or was * rolled back. * @see javax.ejb.SessionSynchronization#afterCompletion(boolean) */ public void afterCompletion(boolean committed) { System.out.println("Was committed? " + committed); } }