KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > AbstractTxInterceptor


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb.plugins;
23
24 import java.io.PrintWriter JavaDoc;
25 import java.io.StringWriter JavaDoc;
26
27 import java.rmi.RemoteException JavaDoc;
28 import java.rmi.ServerException JavaDoc;
29 import java.rmi.NoSuchObjectException JavaDoc;
30 import java.lang.reflect.Method JavaDoc;
31
32 import javax.transaction.TransactionManager JavaDoc;
33 import javax.transaction.TransactionRolledbackException JavaDoc;
34 import javax.transaction.SystemException JavaDoc;
35 import javax.transaction.Transaction JavaDoc;
36 import javax.transaction.Synchronization JavaDoc;
37 import javax.transaction.RollbackException JavaDoc;
38
39 import javax.ejb.EJBException JavaDoc;
40 import javax.ejb.NoSuchEntityException JavaDoc;
41 import javax.ejb.NoSuchObjectLocalException JavaDoc;
42 import javax.ejb.TransactionRolledbackLocalException JavaDoc;
43 import javax.ejb.TimedObject JavaDoc;
44 import javax.ejb.Timer JavaDoc;
45
46 import org.jboss.invocation.Invocation;
47 import org.jboss.invocation.InvocationType;
48 import org.jboss.tm.TxUtils;
49
50 /**
51  * A common superclass for the transaction interceptors.
52  * <p/>
53  * The only important method in this class is invokeNext which is incharge
54  * of invoking the next interceptor and if an exception is thrown, it must
55  * follow the rules in the EJB 2.0 specification section 18.3. These
56  * rules specify if the transaction is rolled back and what exception
57  * should be thrown.
58  *
59  * @author <a HREF="mailto:osh@sparre.dk">Ole Husgaard</a>
60  * @author <a HREF="mailto:dain@daingroup.com">Dain Sundstrom</a>
61  * @version $Revision: 37459 $
62  */

63 abstract class AbstractTxInterceptor
64         extends AbstractInterceptor
65 {
66
67    /** A reference to {@link javax.ejb.TimedObject#ejbTimeout}. */
68    protected static final Method JavaDoc ejbTimeout;
69    static
70    {
71       try
72       {
73          ejbTimeout = TimedObject JavaDoc.class.getMethod("ejbTimeout", new Class JavaDoc[]{Timer JavaDoc.class});
74       }
75       catch (Exception JavaDoc e)
76       {
77          throw new ExceptionInInitializerError JavaDoc(e);
78       }
79    }
80
81    /**
82     * Local reference to the container's TransactionManager.
83     */

84    protected TransactionManager JavaDoc tm;
85
86    public void create() throws Exception JavaDoc
87    {
88       super.create();
89       tm = getContainer().getTransactionManager();
90    }
91
92    /**
93     * This method calls the next interceptor in the chain.
94     * <p/>
95     * All Throwables are caught and divided into two groups: application
96     * exceptions and system exceptions. Application exception are simply
97     * rethrown. System exceptions result in the transaction being marked
98     * for rollback only. If the transaction was not started by the container
99     * (i.e., it was inherited from the client) the system exception is wrapped
100     * in a TransactionRolledBack[Local]Exception.
101     *
102     * @param invocation The <code>Invocation</code> of this call.
103     * @param inheritedTx If <code>true</code> the transaction has just been started
104     * in this interceptor.
105     * @throws Exception if an exception occures in the interceptor chain. The
106     * actual exception throw is governed by the rules in the EJB 2.0
107     * specification section 18.3
108     */

109    protected Object JavaDoc invokeNext(Invocation invocation, boolean inheritedTx)
110            throws Exception JavaDoc
111    {
112       InvocationType type = invocation.getType();
113       try
114       {
115          if (type == InvocationType.REMOTE || type == InvocationType.LOCAL || type == InvocationType.SERVICE_ENDPOINT)
116          {
117             // register the Timer with the transaction
118
if (ejbTimeout.equals(invocation.getMethod()))
119                registerTimer(invocation);
120
121             return getNext().invoke(invocation);
122          }
123          else
124          {
125             return getNext().invokeHome(invocation);
126          }
127       }
128       catch (Throwable JavaDoc e)
129       {
130          // if this is an ApplicationException, just rethrow it
131
if (e instanceof Exception JavaDoc &&
132                  !(e instanceof RuntimeException JavaDoc || e instanceof RemoteException JavaDoc))
133          {
134             throw (Exception JavaDoc) e;
135          }
136
137          // attempt to rollback the transaction
138
Transaction JavaDoc tx = invocation.getTransaction();
139          if (tx == null)
140          {
141             // Look for a hanging active user transaction that we should mark rollback
142
try
143             {
144                tx = tm.getTransaction();
145                if (TxUtils.isActive(tx) == false)
146                   tx = null;
147             }
148             catch (Exception JavaDoc ex)
149             {
150                log.warn("Unable to determine transaction context", ex);
151             }
152          }
153          if (tx != null)
154          {
155             try
156             {
157                tx.setRollbackOnly();
158             }
159             catch (SystemException JavaDoc ex)
160             {
161                log.error("SystemException while setting transaction " +
162                        "for rollback only", ex);
163             }
164             catch (IllegalStateException JavaDoc ex)
165             {
166                log.error("IllegalStateException while setting transaction " +
167                        "for rollback only", ex);
168             }
169          }
170
171          // is this a local invocation
172
boolean isLocal =
173                  type == InvocationType.LOCAL ||
174                  type == InvocationType.LOCALHOME;
175
176          // if this transaction was NOT inherited from the caller we simply
177
// rethrow the exception, and LogInterceptor will handle
178
// all exception conversions.
179
if (!inheritedTx)
180          {
181             if (e instanceof Exception JavaDoc)
182             {
183                throw (Exception JavaDoc) e;
184             }
185             if (e instanceof Error JavaDoc)
186             {
187                throw (Error JavaDoc) e;
188             }
189
190             // we have some funky throwable, wrap it
191
if (isLocal)
192             {
193                String JavaDoc msg = formatException("Unexpected Throwable", e);
194                throw new EJBException JavaDoc(msg);
195             }
196             else
197             {
198                ServerException JavaDoc ex = new ServerException JavaDoc("Unexpected Throwable");
199                ex.detail = e;
200                throw ex;
201             }
202          }
203  
204          // to be nice we coerce the execption to an interface friendly type
205
// before wrapping it with a transaction rolled back exception
206
Throwable JavaDoc cause;
207          if (e instanceof NoSuchEntityException JavaDoc)
208          {
209             NoSuchEntityException JavaDoc nsee = (NoSuchEntityException JavaDoc) e;
210             if (isLocal)
211             {
212                cause = new NoSuchObjectLocalException JavaDoc(nsee.getMessage(),
213                        nsee.getCausedByException());
214             }
215             else
216             {
217                cause = new NoSuchObjectException JavaDoc(nsee.getMessage());
218
219                // set the detil of the exception
220
((NoSuchObjectException JavaDoc) cause).detail =
221                        nsee.getCausedByException();
222             }
223          }
224          else
225          {
226             if (isLocal)
227             {
228                // local transaction rolled back exception can only wrap
229
// an exception so we create an EJBException for the cause
230
if (e instanceof Exception JavaDoc)
231                {
232                   cause = e;
233                }
234                else if (e instanceof Error JavaDoc)
235                {
236                   String JavaDoc msg = formatException("Unexpected Error", e);
237                   cause = new EJBException JavaDoc(msg);
238                }
239                else
240                {
241                   String JavaDoc msg = formatException("Unexpected Throwable", e);
242                   cause = new EJBException JavaDoc(msg);
243                }
244             }
245             else
246             {
247                // remote transaction rolled back exception can wrap
248
// any throwable so we are ok
249
cause = e;
250             }
251          }
252          
253          // We inherited tx: Tell caller we marked for rollback only.
254
if (isLocal)
255          {
256             if (cause instanceof TransactionRolledbackLocalException JavaDoc)
257             {
258                throw (TransactionRolledbackLocalException JavaDoc) cause;
259             }
260             else
261             {
262                throw new TransactionRolledbackLocalException JavaDoc(cause.getMessage(),
263                        (Exception JavaDoc) cause);
264             }
265          }
266          else
267          {
268             if (cause instanceof TransactionRolledbackException JavaDoc)
269             {
270                throw (TransactionRolledbackException JavaDoc) cause;
271             }
272             else
273             {
274                TransactionRolledbackException JavaDoc ex =
275                        new TransactionRolledbackException JavaDoc(cause.getMessage());
276                ex.detail = cause;
277                throw ex;
278             }
279          }
280       }
281    }
282
283    private void registerTimer(Invocation invocation)
284            throws RollbackException JavaDoc, SystemException JavaDoc
285    {
286       Timer JavaDoc timer = (Timer JavaDoc) invocation.getArguments()[0];
287       Transaction JavaDoc transaction = invocation.getTransaction();
288       if (transaction != null && timer instanceof Synchronization JavaDoc)
289          transaction.registerSynchronization((Synchronization JavaDoc) timer);
290    }
291
292    private String JavaDoc formatException(String JavaDoc msg, Throwable JavaDoc t)
293    {
294       StringWriter JavaDoc sw = new StringWriter JavaDoc();
295       PrintWriter JavaDoc pw = new PrintWriter JavaDoc(sw);
296       if (msg != null)
297       {
298          pw.println(msg);
299       }
300       t.printStackTrace(pw);
301       return sw.toString();
302    }
303 }
304
Popular Tags