KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_ejb > container > JMessageEndpointProxy


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999 Bull S.A.
4  * Contact: jonas-team@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: JMessageEndpointProxy.java,v 1.15 2005/04/28 16:52:59 benoitf Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.jonas_ejb.container;
27
28 import java.lang.reflect.InvocationHandler JavaDoc;
29 import java.lang.reflect.InvocationTargetException JavaDoc;
30 import java.lang.reflect.Method JavaDoc;
31 import java.lang.reflect.Proxy JavaDoc;
32
33 import javax.ejb.MessageDrivenBean JavaDoc;
34 import javax.ejb.EJBException JavaDoc;
35 import javax.resource.ResourceException JavaDoc;
36 import javax.resource.spi.IllegalStateException JavaDoc;
37 import javax.transaction.xa.XAResource JavaDoc;
38
39 import org.objectweb.jonas_ejb.deployment.api.MethodDesc;
40
41 import org.objectweb.transaction.jta.TransactionManager;
42 import org.objectweb.util.monolog.api.BasicLevel;
43
44 /**
45  * Generic interposed class for Message Endpoints This class presents these
46  * interfaces, depending on object reached: MessageDrivenContext interface to
47  * the bean instance
48  * @author Philippe Coq, Philippe Durieux
49  * @author Christophe Ney (Easier Enhydra integration)
50  */

51 public class JMessageEndpointProxy implements InvocationHandler JavaDoc {
52
53     protected JMdbEndpointFactory bf = null;
54
55     protected JMessageEndpoint ep = null;
56
57     protected MessageDrivenBean JavaDoc mdb = null;
58
59     protected TransactionManager tm = null;
60
61     boolean b4Delivery = false;
62
63     int msgCount = 0;
64
65     // RequestCtx associated to the thread
66
// Thread specific data
67
private transient static ThreadLocal JavaDoc requestCtx = new ThreadLocal JavaDoc();
68
69     /**
70      * constructor
71      * @param bf The MDB Endpoint Factory
72      * @param sess The JMS Session
73      * @param mdb The Message Driven Bean
74      * @param thpool The Thread Pool
75      */

76     public JMessageEndpointProxy(JMdbEndpointFactory bf, MessageDrivenBean JavaDoc mdb, JMessageEndpoint ep) {
77         this.bf = bf;
78         this.mdb = mdb;
79         this.ep = ep;
80         // keep these locally for efficiency.
81
tm = bf.getTransactionManager();
82     }
83
84     // ------------------------------------------------------------------
85
// InvocationHandler implementation
86
// ------------------------------------------------------------------
87

88     public Object JavaDoc invoke(Object JavaDoc obj, Method JavaDoc method, Object JavaDoc[] aobj) throws Throwable JavaDoc, NoSuchMethodException JavaDoc,
89             ResourceException JavaDoc, Exception JavaDoc {
90         RequestCtx rctx = null;
91         String JavaDoc methodName = method.getName();
92         Object JavaDoc ret = null;
93         Throwable JavaDoc invokeEx = null;
94
95         if (TraceEjb.isDebugJms()) {
96             TraceEjb.mdb.log(BasicLevel.DEBUG, "Calling " + methodName + " on " + this);
97         }
98         if (ep.released) {
99             throw new IllegalStateException JavaDoc("Endpoint is in a released state and must be reactivated before using");
100         }
101         // Object methods
102
if ("equals".equals(methodName)) {
103             Object JavaDoc obj1 = null;
104             if (Proxy.isProxyClass(aobj[0].getClass())) {
105                 obj1 = (Object JavaDoc) Proxy.getInvocationHandler(aobj[0]);
106             } else {
107                 obj1 = aobj[0];
108             }
109             ret = new Boolean JavaDoc(this.equals(obj1));
110         } else if ("hashCode".equals(methodName)) {
111             ret = new Integer JavaDoc(this.hashCode());
112         } else if ("toString".equals(methodName)) {
113             ret = this.toString();
114         } else if ("afterDelivery".equals(methodName)) {
115             if (!b4Delivery) {
116                 throw new IllegalStateException JavaDoc(methodName + " called w/o call to beforeDelivery");
117             }
118             b4Delivery = false;
119             msgCount = 0;
120             rctx = (RequestCtx) requestCtx.get();
121             try {
122                 if (rctx.mustCommit && ep.getXAResource() != null) {
123                     rctx.currTx.delistResource(ep.getXAResource(), XAResource.TMSUCCESS);
124                 }
125                 bf.postInvoke(rctx);
126             } catch (Exception JavaDoc e) {
127                 TraceEjb.logger.log(BasicLevel.ERROR, "exception on postInvoke: ", e);
128                 throw new RuntimeException JavaDoc(e);
129             }
130         } else if ("beforeDelivery".equals(methodName)) {
131
132             if (TraceEjb.isDebugJms()) {
133                 TraceEjb.mdb.log(BasicLevel.DEBUG, "beforeDelivery called");
134             }
135             if (b4Delivery) {
136                 throw new IllegalStateException JavaDoc(methodName + " called w/o call to afterDelivery");
137             }
138             if (bf.isTxBeanManaged()) {
139                 throw new IllegalStateException JavaDoc(methodName + " cannot be called when using bean managed transactions");
140             }
141             if (tm.getTransaction() != null) {
142                 throw new IllegalStateException JavaDoc(methodName + " cannot be called when using an imported transaction");
143             }
144             msgCount = 0;
145             // retrieve intented method name passed in parameter
146
Object JavaDoc obj1 = null;
147             if (Proxy.isProxyClass(aobj[0].getClass())) {
148                 obj1 = (Object JavaDoc) Proxy.getInvocationHandler(aobj[0]);
149             } else {
150                 obj1 = aobj[0];
151             }
152             Method JavaDoc intentedTargetMethod = (Method JavaDoc) obj1;
153             String JavaDoc intentedTargetMethodName = intentedTargetMethod.getName();
154
155             if (TraceEjb.isDebugJms()) {
156                 TraceEjb.mdb.log(BasicLevel.DEBUG, "intentedTargetMethodName=" + intentedTargetMethodName);
157             }
158             try {
159                 if (TraceEjb.isDebugJms()) {
160                     TraceEjb.mdb.log(BasicLevel.DEBUG, "before preInvoke");
161                 }
162                 rctx = bf.preInvoke(getTxAttr(intentedTargetMethod));
163                 // JCA 1.5 ?12.5.6 mentions that beforeDelivery and afterDelivery
164
// must be called from a single thread of control.
165
// so the RequestCtx is stored in thread specific data for next
166
// use in afterDelivery call and intended method call.
167
requestCtx.set(rctx);
168                 b4Delivery = true;
169                 if (rctx.mustCommit && ep.getXAResource() != null) {
170
171                     rctx.currTx.enlistResource(ep.getXAResource());
172                     if (TraceEjb.isDebugJms()) {
173                         TraceEjb.mdb.log(BasicLevel.DEBUG, "enlistResource Ok");
174                     }
175                 }
176             } catch (Exception JavaDoc e) {
177                 TraceEjb.logger.log(BasicLevel.ERROR, "preInvoke failed: ", e);
178                 throw new RuntimeException JavaDoc(e);
179             }
180             if (TraceEjb.isDebugJms()) {
181                 TraceEjb.mdb.log(BasicLevel.DEBUG, "beforeDelivery ended");
182             }
183         } else if ("release".equals(methodName)) {
184             bf.releaseEndpoint(ep);
185         } else {
186             msgCount++;
187
188             if (!b4Delivery) {
189                 boolean isImportedTx = tm.getTransaction() != null;
190                 rctx = bf.preInvoke(getTxAttr(method));
191                 // JCA 1.5 ?12.5.9
192
// if txRequired && imported tx, use the source managed Tx
193
// and ignore the XAResource
194
if (rctx.mustCommit) {
195                     if (!isImportedTx) {
196
197                         if (ep.getXAResource() != null) {
198                             rctx.currTx.enlistResource(ep.getXAResource());
199                         }
200                     } else {
201                         rctx.mustCommit = false;
202                     }
203                 }
204                 bf.checkSecurity(null);
205             } else if (msgCount > 1) {
206                 throw new IllegalStateException JavaDoc("Unable to deliver multiple messages");
207             } else {
208                 rctx = (RequestCtx) requestCtx.get();
209             }
210             try {
211                 if (TraceEjb.isDebugJms()) {
212                     TraceEjb.mdb.log(BasicLevel.DEBUG, "Before invoke");
213                 }
214                 ret = method.invoke(mdb, aobj);
215                 if (TraceEjb.isDebugJms()) {
216                     TraceEjb.mdb.log(BasicLevel.DEBUG, "After invoke");
217                 }
218             } catch (InvocationTargetException JavaDoc ite) {
219                 Throwable JavaDoc t = ite.getTargetException();
220                 if (t instanceof RuntimeException JavaDoc) {
221                     if (rctx != null) {
222                         rctx.sysExc = new EJBException JavaDoc((RuntimeException JavaDoc) t);
223                     }
224                 } else {
225                     if (rctx != null) {
226                         rctx.sysExc = t;
227                     }
228                 }
229                 invokeEx = rctx.sysExc;
230                 TraceEjb.logger.log(BasicLevel.ERROR, "error thrown by an enterprise Bean", t);
231             } catch (Throwable JavaDoc ex) {
232                 //ex.printStackTrace();
233
if (rctx != null) {
234                     rctx.sysExc = ex;
235                 }
236                 invokeEx = ex;
237
238                 TraceEjb.logger.log(BasicLevel.ERROR, "error thrown by an enterprise Bean", ex);
239             } finally {
240                 if (!b4Delivery) {
241                     try {
242                         if (!bf.isTxBeanManaged() && rctx.mustCommit && ep.getXAResource() != null) {
243                             rctx.currTx.delistResource(ep.getXAResource(), XAResource.TMSUCCESS);
244                         }
245                         bf.postInvoke(rctx);
246                     } catch (Exception JavaDoc e) {
247                         TraceEjb.logger.log(BasicLevel.ERROR, "exception on postInvoke: ", e);
248                         if (invokeEx == null) {
249                             invokeEx = e;
250                         }
251                     }
252                 } else {
253                     // Reset message count if not using after/before delivery
254
msgCount = 0;
255                 }
256             }
257         }
258         if (invokeEx != null) {
259             TraceEjb.logger.log(BasicLevel.ERROR, "Exception raised: ", invokeEx);
260             throw invokeEx;
261         }
262         if (TraceEjb.isDebugJms()) {
263             TraceEjb.mdb.log(BasicLevel.DEBUG, "ret="+ret);
264         }
265         return ret;
266     }
267
268     private int getTxAttr(Method JavaDoc m) {
269         int ret = MethodDesc.TX_NOT_SUPPORTED;
270         try {
271             ret = bf.isDeliveryTransacted(m) ? MethodDesc.TX_REQUIRED : MethodDesc.TX_NOT_SUPPORTED;
272         } catch (NoSuchMethodException JavaDoc nsme) {
273         }
274         return ret;
275     }
276 }
277
278
Popular Tags