001: /**
002: * EasyBeans
003: * Copyright (C) 2006 Bull S.A.S.
004: * Contact: easybeans@ow2.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: CMTRequiredTransactionInterceptor.java 1970 2007-10-16 11:49:25Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.ow2.easybeans.transaction.interceptors;
025:
026: import static javax.transaction.Status.STATUS_ACTIVE;
027: import static javax.transaction.Status.STATUS_MARKED_ROLLBACK;
028:
029: import javax.ejb.EJBException;
030: import javax.ejb.TransactionRolledbackLocalException;
031: import javax.transaction.NotSupportedException;
032: import javax.transaction.RollbackException;
033: import javax.transaction.SystemException;
034: import javax.transaction.Transaction;
035:
036: import org.ow2.easybeans.api.EasyBeansInvocationContext;
037: import org.ow2.util.log.Log;
038: import org.ow2.util.log.LogFactory;
039:
040: /**
041: * Defines an interceptor for method using the REQUIRED attribute.
042: * @author Florent Benoit
043: */
044: public class CMTRequiredTransactionInterceptor extends
045: AbsTransactionInterceptor {
046:
047: /**
048: * Logger.
049: */
050: private Log logger = LogFactory
051: .getLog(CMTRequiredTransactionInterceptor.class);
052:
053: /**
054: * Constructor.<br>
055: * Acquire the transaction manager.
056: */
057: public CMTRequiredTransactionInterceptor() {
058: super ();
059: }
060:
061: /**
062: * Execute transaction as specified with the REQUIRED attribute.
063: * @param invocationContext
064: * context with useful attributes on the current invocation
065: * @return result of the next invocation (to chain interceptors)
066: * @throws Exception
067: * if interceptor fails
068: * @see <a href="http://www.jcp.org/en/jsr/detail?id=220">EJB 3.0
069: * specification ?12.6.2.2</a>
070: */
071: @Override
072: public Object intercept(
073: final EasyBeansInvocationContext invocationContext)
074: throws Exception {
075: logger.debug("Calling Required TX interceptor");
076:
077: // Get current transaction
078: Transaction transaction;
079: try {
080: transaction = getTransactionManager().getTransaction();
081: } catch (SystemException se) {
082: throw new EJBException(
083: "Cannot get the current transaction on transaction manager.",
084: se);
085: }
086:
087: logger.debug("Transaction found = {0}", transaction);
088:
089: /*
090: * If the client invokes the enterprise bean's method while the client
091: * is not associated with a transaction context, the container
092: * automatically starts a new transaction before delegating a method
093: * call to the enterprise bean business method.
094: */
095: boolean startedTransaction = false;
096: if (transaction == null) {
097: try {
098: getTransactionManager().begin();
099: startedTransaction = true;
100: } catch (NotSupportedException nse) {
101: throw new EJBException(
102: "Transaction Manager implementation does not support nested transactions.",
103: nse);
104: } catch (SystemException se) {
105: throw new EJBException(
106: "Cannot call begin() on the transaction manager.",
107: se);
108: }
109: }
110: // else
111: /*
112: * If a client invokes the enterprise bean's method while the client is
113: * associated with a transaction context, the container invokes the
114: * enterprise bean's method in the client's transaction context.
115: */
116: boolean gotBusinessException = false;
117: try {
118: return invocationContext.proceed();
119:
120: } catch (Exception e) {
121: gotBusinessException = true;
122:
123: // Chapter 14.3.1
124: // Runs in the context of the client
125: if (!startedTransaction) {
126: handleContextClientTransaction(invocationContext, e);
127: } else {
128: // Container's transaction
129: handleContextContainerTransaction(invocationContext, e);
130: }
131: // Shouldn't come here
132: return null;
133: } finally {
134: if (!gotBusinessException) {
135:
136: // only do some operations if transaction has been started
137: // before
138: // invoking the method.
139: if (startedTransaction) {
140:
141: // sanity check.
142: Transaction transactionAfter = null;
143: try {
144: transactionAfter = getTransactionManager()
145: .getTransaction();
146: } catch (SystemException se) {
147: throw new EJBException(
148: "Cannot get the current transaction on transaction manager.",
149: se);
150: }
151:
152: if (transactionAfter == null) {
153: throw new RuntimeException(
154: "Transaction disappeared.");
155: }
156:
157: /*
158: * The container attempts to commit the transaction when the
159: * business method has completed. The container performs the
160: * commit protocol before the method result is sent to the
161: * client.
162: */
163: try {
164: switch (getTransactionManager().getStatus()) {
165: case STATUS_ACTIVE:
166: getTransactionManager().commit();
167: break;
168: case STATUS_MARKED_ROLLBACK:
169: getTransactionManager().rollback();
170: break;
171: default:
172: throw new RuntimeException(
173: "Unexpected transaction status"
174: + getTransactionManager()
175: .getStatus());
176: }
177: } catch (RollbackException e) {
178: throw new TransactionRolledbackLocalException(
179: "Could not commit transaction", e);
180: } catch (Exception e) {
181: throw new EJBException("Container exception", e);
182: }
183: }
184: }
185: }
186:
187: }
188:
189: }
|