KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > easybeans > transaction > interceptors > AbsTransactionInterceptor


1 /**
2  * EasyBeans
3  * Copyright (C) 2006 Bull S.A.S.
4  * Contact: easybeans@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: AbsTransactionInterceptor.java 1114 2006-09-13 11:31:13Z benoitf $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.easybeans.transaction.interceptors;
27
28 import static javax.transaction.Status.STATUS_MARKED_ROLLBACK JavaDoc;
29
30 import java.lang.reflect.Method JavaDoc;
31 import java.util.Map JavaDoc;
32
33 import javax.ejb.ApplicationException JavaDoc;
34 import javax.ejb.EJBException JavaDoc;
35 import javax.ejb.EJBTransactionRolledbackException JavaDoc;
36 import javax.transaction.HeuristicMixedException JavaDoc;
37 import javax.transaction.HeuristicRollbackException JavaDoc;
38 import javax.transaction.RollbackException JavaDoc;
39 import javax.transaction.SystemException JavaDoc;
40 import javax.transaction.Transaction JavaDoc;
41 import javax.transaction.TransactionManager JavaDoc;
42
43 import org.objectweb.easybeans.api.EasyBeansInterceptor;
44 import org.objectweb.easybeans.api.EasyBeansInvocationContext;
45 import org.objectweb.easybeans.api.Factory;
46 import org.objectweb.easybeans.api.bean.EasyBeansSFSB;
47 import org.objectweb.easybeans.api.pool.Pool;
48 import org.objectweb.easybeans.api.pool.PoolException;
49 import org.objectweb.easybeans.log.JLog;
50 import org.objectweb.easybeans.log.JLogFactory;
51 import org.objectweb.easybeans.transaction.JTransactionManager;
52
53 /**
54  * Defines an abstract interceptor for transaction with common code used by all
55  * transaction interceptors.
56  * @author Florent Benoit
57  */

58 public abstract class AbsTransactionInterceptor implements EasyBeansInterceptor {
59
60     /**
61      * Logger.
62      */

63     private JLog logger = JLogFactory.getLog(AbsTransactionInterceptor.class);
64
65     /**
66      * Transaction manager.
67      */

68     private TransactionManager JavaDoc transactionManager = null;
69
70     /**
71      * Constructor.<br>
72      * Acquire the transaction manager.
73      */

74     public AbsTransactionInterceptor() {
75         this.transactionManager = JTransactionManager.getTransactionManager();
76     }
77
78     /**
79      * Defines the code used by the transaction interceptor on a given method.
80      * @param invocationContext context with useful attributes on the current
81      * invocation
82      * @return result of the next invocation (to chain interceptors)
83      * @throws Exception if interceptor fails
84      */

85     public abstract Object JavaDoc intercept(final EasyBeansInvocationContext invocationContext) throws Exception JavaDoc;
86
87     /**
88      * Gets the transaction manager.
89      * @return TM.
90      */

91     public TransactionManager JavaDoc getTransactionManager() {
92         return transactionManager;
93     }
94
95     /**
96      * Gets the application exception (if any) for the given invocation context
97      * and the given exception.<br />
98      * Note that a checked Exception is by default an application exception.
99      * @param invocationContext context that provides access to the Method
100      * object.
101      * @param e the exception to check
102      * @return the application exception object, else null.
103      */

104     protected ApplicationException JavaDoc getApplicationException(final EasyBeansInvocationContext invocationContext,
105             final Exception JavaDoc e) {
106         Map JavaDoc<String JavaDoc, ApplicationException JavaDoc> applicationExceptions = invocationContext.getFactory().getBeanInfo()
107                 .getApplicationExceptions();
108         ApplicationException JavaDoc appException = applicationExceptions.get(e.getClass().getName());
109         if (appException != null) {
110             return appException;
111         }
112         // If runtime exception, not an application by default
113
if (e instanceof RuntimeException JavaDoc) {
114             return null;
115         }
116         // Is it a checked Exception ?
117
Method JavaDoc method = invocationContext.getMethod();
118         if (method != null) {
119             Class JavaDoc[] exceptions = method.getExceptionTypes();
120             if (exceptions != null) {
121                 for (Class JavaDoc clazz : exceptions) {
122                     // Is an Exception but not a runtime exception
123
if (clazz.isInstance(e) && !(e instanceof RuntimeException JavaDoc)) {
124                         // Checked exception, so application exception with
125
// rollback = false (default)
126
return applicationExceptions.get("DEFAULT");
127                     }
128                 }
129             }
130         }
131         // Was not a checked exception.
132
return null;
133
134     }
135
136     /**
137      * Remove from the factory's pool the bean found in the current invocation
138      * context.
139      * @param invocationContext the context of the current invocation
140      * @throws PoolException if removal is failing
141      */

142     @SuppressWarnings JavaDoc("unchecked")
143     protected void discard(final EasyBeansInvocationContext invocationContext) throws PoolException {
144
145         Object JavaDoc target = invocationContext.getTarget();
146
147         // factory is a stateful factory ?
148
if (target instanceof EasyBeansSFSB) {
149             // Gets the factory
150
Factory factory = invocationContext.getFactory();
151
152             // get pool
153
Pool<EasyBeansSFSB, Long JavaDoc> pool = factory.getPool();
154
155             // Bean is a stateful bean
156
EasyBeansSFSB bean = (EasyBeansSFSB) invocationContext.getTarget();
157
158             // discard instance
159
pool.discard(bean);
160         } else {
161             logger.debug("Instance not discarded as it is not a stateful bean");
162         }
163
164     }
165
166     /**
167      * Marks the transaction for rollback.
168      */

169     protected void markTransactionRollback() {
170         // Look if there is a transaction
171
Transaction JavaDoc transaction;
172         try {
173             transaction = getTransactionManager().getTransaction();
174         } catch (SystemException JavaDoc se) {
175             throw new EJBException JavaDoc("Cannot get the current transaction on transaction manager.", se);
176         }
177         if (transaction != null) {
178             try {
179                 transactionManager.setRollbackOnly();
180             } catch (IllegalStateException JavaDoc e) {
181                 logger.warn("Cannot mark transaction as rollbackOnly", e);
182             } catch (SystemException JavaDoc e) {
183                 logger.warn("Cannot mark transaction as rollbackOnly", e);
184             }
185         }
186     }
187
188     /**
189      * Test if current transaction is with status STATUS_MARKED_ROLLBACK.
190      * @return true if status == STATUS_MARKED_ROLLBACK
191      */

192     protected boolean isMarkedRollbackOnly() {
193         try {
194             return (STATUS_MARKED_ROLLBACK == transactionManager.getStatus());
195         } catch (SystemException JavaDoc e) {
196             logger.warn("Cannot get transaction status", e);
197             return false;
198         }
199     }
200
201     /**
202      * Rollback the current transaction.
203      */

204     protected void rollback() {
205         try {
206             transactionManager.rollback();
207         } catch (IllegalStateException JavaDoc e) {
208             logger.warn("Cannot rollback the transaction", e);
209         } catch (SecurityException JavaDoc e) {
210             logger.warn("Cannot rollback the transaction", e);
211         } catch (SystemException JavaDoc e) {
212             logger.warn("Cannot rollback the transaction", e);
213         }
214     }
215
216     /**
217      * Commit the current transaction.
218      */

219     protected void commit() {
220         try {
221             transactionManager.commit();
222         } catch (IllegalStateException JavaDoc e) {
223             logger.warn("Cannot commit the transaction", e);
224         } catch (SecurityException JavaDoc e) {
225             logger.warn("Cannot commit the transaction", e);
226         } catch (HeuristicMixedException JavaDoc e) {
227             logger.warn("Cannot commit the transaction", e);
228         } catch (HeuristicRollbackException JavaDoc e) {
229             logger.warn("Cannot commit the transaction", e);
230         } catch (RollbackException JavaDoc e) {
231             logger.warn("Cannot commit the transaction", e);
232         } catch (SystemException JavaDoc e) {
233             logger.warn("Cannot commit the transaction", e);
234         }
235     }
236
237     /**
238      * Handle an exception for bean managed transaction.<br />
239      * See Chapter 14.3.1.
240      * @param invocationContext the context of the current invocation
241      * @param e the exception to handle
242      * @throws Exception when handling the exception.
243      */

244     protected void handleBeanManagedException(final EasyBeansInvocationContext invocationContext, final Exception JavaDoc e)
245             throws Exception JavaDoc {
246         ApplicationException JavaDoc applicationException = getApplicationException(invocationContext, e);
247
248         // it is an application exception
249
if (applicationException != null) {
250             // Re-throw AppException.
251
throw e;
252         }
253
254         // else, not an application exception :
255

256         // Log the exception or error.
257
logger.error("Bean Managed Transaction : Exception (not application exception) in business method", e);
258
259         // Mark for rollback a transaction that has been
260
// started, but not yet completed, by the instance.
261
markTransactionRollback();
262
263         // Discard instance.
264
try {
265             discard(invocationContext);
266         } catch (PoolException pe) {
267             throw new EJBException JavaDoc("Cannot discard the bean", pe);
268         }
269
270         // Throw EJBException to client.
271
throw new EJBException JavaDoc("Bean Managed Transaction : Business exception which is not an application exception", e);
272     }
273
274     /**
275      * Handle an exception that are in an unspecified transaction context.<br />
276      * See Chapter 14.3.1.
277      * @param invocationContext the context of the current invocation
278      * @param e the exception to handle
279      * @throws Exception when handling the exception.
280      */

281     protected void handleUnspecifiedTransactionContext(final EasyBeansInvocationContext invocationContext,
282             final Exception JavaDoc e) throws Exception JavaDoc {
283
284         ApplicationException JavaDoc applicationException = getApplicationException(invocationContext, e);
285
286         // it is an application exception
287
if (applicationException != null) {
288             // Re-throw AppException.
289
throw e;
290         }
291
292         // else, not an application exception :
293

294         // Log the exception or error.
295
logger.error("Exception (not application exception) in business method", e);
296
297         // Discard instance.
298
try {
299             discard(invocationContext);
300         } catch (PoolException pe) {
301             throw new EJBException JavaDoc("Cannot discard the bean", pe);
302         }
303
304         // Throw EJBException to client.
305
throw new EJBException JavaDoc("Business exception which is not an application exception", e);
306
307     }
308
309     /**
310      * Handle an exception and the transaction is the client transaction.<br />
311      * See Chapter 14.3.1.
312      * @param invocationContext the context of the current invocation
313      * @param e the exception to handle
314      * @throws Exception when handling the exception.
315      */

316     protected void handleContextClientTransaction(final EasyBeansInvocationContext invocationContext, final Exception JavaDoc e)
317             throws Exception JavaDoc {
318         ApplicationException JavaDoc applicationException = getApplicationException(invocationContext, e);
319
320         // An application exception ?
321
if (applicationException != null) {
322             /*
323              * Re-throw AppException. Mark the transaction for rollback if the
324              * application exception is specified as causing rollback.
325              */

326
327             // Mark the transaction for rollback.
328
if (applicationException.rollback()) {
329                 markTransactionRollback();
330             }
331
332             // rethrow
333
throw e;
334         }
335
336         // else, not an application exception :
337

338         // Log the exception or error.
339
logger.error("Exception (not application exception) in business method", e);
340
341         // Mark the transaction for rollback.
342
markTransactionRollback();
343
344         // Discard instance.
345
try {
346             discard(invocationContext);
347         } catch (PoolException pe) {
348             throw new EJBException JavaDoc("Cannot discard the bean", pe);
349         }
350
351         // Throw javax.ejb.EJBTransactionRolledbackException to
352
// client.
353
EJBTransactionRolledbackException JavaDoc transactionException = new EJBTransactionRolledbackException JavaDoc(
354                 "System exception, The transaction has been marked for rollback only");
355         transactionException.initCause(e);
356         throw transactionException;
357     }
358
359     /**
360      * Handle an exception and the transaction is the container transaction.
361      * Bean method runs in the context of a transaction that the container
362      * started immediately before dispatching the business method.<br />
363      * See Chapter 14.3.1.
364      * @param invocationContext the context of the current invocation
365      * @param e the exception to handle
366      * @throws Exception when handling the exception.
367      */

368     protected void handleContextContainerTransaction(final EasyBeansInvocationContext invocationContext,
369             final Exception JavaDoc e) throws Exception JavaDoc {
370
371         ApplicationException JavaDoc applicationException = getApplicationException(invocationContext, e);
372
373         // An application exception ?
374
if (applicationException != null) {
375             /*
376              * If the instance called setRollback-Only(), then rollback the
377              * transaction, and re-throw AppException.
378              */

379             if (isMarkedRollbackOnly()) {
380                 rollback();
381                 throw e;
382             }
383
384             /*
385              * Mark the transaction for rollback if the application exception is
386              * specified as causing rollback, and then re-throw AppException.
387              * Otherwise, attempt to commit the transaction, and then re-throw
388              * AppException.
389              */

390             if (applicationException.rollback()) {
391                 // TODO: rollback or mark rollback ??
392
rollback();
393             } else {
394                 commit();
395             }
396             throw e;
397         }
398         // else, not an application exception :
399
// Log the exception or error.
400
logger.error("Exception (not application exception) in business method", e);
401
402         // Rollback the container-started transaction.
403
rollback();
404
405         // Discard instance.
406
try {
407             discard(invocationContext);
408         } catch (PoolException pe) {
409             throw new EJBException JavaDoc("Cannot discard the bean", pe);
410         }
411
412         // Throw EJBException to client.
413
throw new EJBException JavaDoc("Exception in a business interface with REQUIRED TX attribute", e);
414
415     }
416 }
417
Popular Tags