1
2
3
4
5
6
7
8
9
10
11 package org.mule.impl;
12
13 import org.mule.MuleManager;
14 import org.mule.config.ExceptionHelper;
15 import org.mule.impl.internal.notifications.ExceptionNotification;
16 import org.mule.impl.message.ExceptionMessage;
17 import org.mule.providers.NullPayload;
18 import org.mule.transaction.TransactionCoordination;
19 import org.mule.umo.MessagingException;
20 import org.mule.umo.TransactionException;
21 import org.mule.umo.UMOEvent;
22 import org.mule.umo.UMOEventContext;
23 import org.mule.umo.UMOException;
24 import org.mule.umo.UMOMessage;
25 import org.mule.umo.UMOTransaction;
26 import org.mule.umo.endpoint.UMOEndpoint;
27 import org.mule.umo.endpoint.UMOEndpointURI;
28 import org.mule.umo.endpoint.UMOImmutableEndpoint;
29 import org.mule.umo.lifecycle.Initialisable;
30 import org.mule.umo.lifecycle.InitialisationException;
31 import org.mule.umo.lifecycle.LifecycleException;
32 import org.mule.umo.routing.RoutingException;
33
34 import java.beans.ExceptionListener;
35 import java.util.Iterator;
36 import java.util.List;
37
38 import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
39 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
40 import org.apache.commons.logging.Log;
41 import org.apache.commons.logging.LogFactory;
42
43
44
45
46
47
48
49
50 public abstract class AbstractExceptionListener implements ExceptionListener, Initialisable
51 {
52
53
54
55 protected transient Log logger = LogFactory.getLog(getClass());
56
57 protected List endpoints = new CopyOnWriteArrayList();
58
59 protected AtomicBoolean initialised = new AtomicBoolean(false);
60
61 public List getEndpoints()
62 {
63 return endpoints;
64 }
65
66 public void setEndpoints(List endpoints)
67 {
68 for (Iterator iterator = endpoints.iterator(); iterator.hasNext();)
69 {
70 addEndpoint((UMOEndpoint) iterator.next());
71 }
72 }
73
74 public void addEndpoint(UMOEndpoint endpoint)
75 {
76 if (endpoint != null)
77 {
78 endpoint.setType(UMOEndpoint.ENDPOINT_TYPE_SENDER);
79 endpoints.add(endpoint);
80 }
81 }
82
83 public boolean removeEndpoint(UMOEndpoint endpoint)
84 {
85 return endpoints.remove(endpoint);
86 }
87
88 public void exceptionThrown(Exception e)
89 {
90 fireNotification(new ExceptionNotification(e));
91
92 Throwable t = getExceptionType(e, RoutingException.class);
93 if (t != null)
94 {
95 RoutingException re = (RoutingException) t;
96 handleRoutingException(re.getUmoMessage(), re.getEndpoint(), e);
97 return;
98 }
99
100 t = getExceptionType(e, MessagingException.class);
101 if (t != null)
102 {
103 MessagingException me = (MessagingException) t;
104 handleMessagingException(me.getUmoMessage(), e);
105 return;
106 }
107
108 t = getExceptionType(e, LifecycleException.class);
109 if (t != null)
110 {
111 LifecycleException le = (LifecycleException) t;
112 handleLifecycleException(le.getComponent(), e);
113 if (RequestContext.getEventContext() != null)
114 {
115 handleMessagingException(RequestContext.getEventContext().getMessage(), e);
116 }
117 else
118 {
119 logger.info("There is no current event available, routing Null message with the exception");
120 handleMessagingException(new MuleMessage(NullPayload.getInstance()), e);
121 }
122 return;
123 }
124
125 handleStandardException(e);
126 }
127
128 protected Throwable getExceptionType(Throwable t, Class exceptionType)
129 {
130 while (t != null)
131 {
132 if (exceptionType.isAssignableFrom(t.getClass()))
133 {
134 return t;
135 }
136
137 t = t.getCause();
138 }
139
140 return null;
141 }
142
143
144
145
146
147
148
149
150
151 public final synchronized void initialise() throws InitialisationException
152 {
153 if (!initialised.get())
154 {
155 doInitialise();
156 initialised.set(true);
157 }
158 }
159
160 protected void doInitialise() throws InitialisationException
161 {
162 logger.info("Initialising exception listener: " + toString());
163 for (Iterator iterator = endpoints.iterator(); iterator.hasNext();)
164 {
165 UMOEndpoint umoEndpoint = (UMOEndpoint) iterator.next();
166 umoEndpoint.initialise();
167 }
168 }
169
170
171
172
173
174
175 protected void markTransactionForRollback()
176 {
177 UMOTransaction tx = TransactionCoordination.getInstance().getTransaction();
178 try
179 {
180 if (tx != null)
181 {
182 tx.setRollbackOnly();
183 }
184 }
185 catch (TransactionException e)
186 {
187 logException(e);
188 }
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206 protected void routeException(UMOMessage message, UMOImmutableEndpoint failedEndpoint, Throwable t)
207 {
208 UMOEndpoint endpoint = getEndpoint(t);
209 if (endpoint != null)
210 {
211 try
212 {
213 logger.error("Message being processed is: " + (message == null ? "null" : message.toString()));
214 UMOEventContext ctx = RequestContext.getEventContext();
215 String component = "Unknown";
216 UMOEndpointURI endpointUri = null;
217 if (ctx != null)
218 {
219 if (ctx.getComponentDescriptor() != null)
220 {
221 component = ctx.getComponentDescriptor().getName();
222 }
223 endpointUri = ctx.getEndpointURI();
224 }
225 else if (failedEndpoint != null)
226 {
227 endpointUri = failedEndpoint.getEndpointURI();
228 }
229 ExceptionMessage msg;
230 msg = new ExceptionMessage(getErrorMessagePayload(message), t, component, endpointUri);
231
232 UMOMessage exceptionMessage;
233 if (ctx == null)
234 {
235 exceptionMessage = new MuleMessage(msg);
236 }
237 else
238 {
239 exceptionMessage = new MuleMessage(msg, ctx.getMessage());
240 }
241 UMOEvent exceptionEvent = new MuleEvent(exceptionMessage, endpoint, new MuleSession(
242 exceptionMessage, new MuleSessionHandler()), true);
243 exceptionEvent = RequestContext.setEvent(exceptionEvent);
244 endpoint.send(exceptionEvent);
245
246 if (logger.isDebugEnabled())
247 {
248 logger.debug("routed Exception message via " + endpoint);
249 }
250
251 }
252 catch (UMOException e)
253 {
254 logFatal(message, e);
255 }
256 }
257 else
258 {
259 markTransactionForRollback();
260 }
261 }
262
263 protected Object getErrorMessagePayload(UMOMessage message)
264 {
265 try
266 {
267 return message.getPayloadAsString();
268 }
269 catch (Exception e)
270 {
271 logException(e);
272 logger.info("Failed to read message payload as string, using raw payload");
273 return message.getPayload();
274 }
275 }
276
277
278
279
280
281
282
283
284
285
286
287 protected UMOEndpoint getEndpoint(Throwable t)
288 {
289 if (endpoints.size() > 0)
290 {
291 return (UMOEndpoint) endpoints.get(0);
292 }
293 else
294 {
295 return null;
296 }
297 }
298
299
300
301
302
303
304 protected void logException(Throwable t)
305 {
306 UMOException umoe = ExceptionHelper.getRootMuleException(t);
307 if (umoe != null)
308 {
309 logger.error(umoe.getDetailedMessage());
310 }
311 else
312 {
313 logger.error("Caught exception in Exception Strategy: " + t.getMessage(), t);
314 }
315 }
316
317
318
319
320
321
322
323
324
325 protected void logFatal(UMOMessage message, Throwable t)
326 {
327 logger.fatal(
328 "Failed to dispatch message to error queue after it failed to process. This may cause message loss."
329 + (message == null ? "" : "Logging Message here: \n" + message.toString()), t);
330 }
331
332 public boolean isInitialised()
333 {
334 return initialised.get();
335 }
336
337
338
339
340
341
342
343
344 protected void fireNotification(ExceptionNotification notification)
345 {
346 MuleManager.getInstance().fireNotification(notification);
347 }
348
349
350
351
352
353
354
355
356
357
358
359 public abstract void handleMessagingException(UMOMessage message, Throwable e);
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374 public abstract void handleRoutingException(UMOMessage message, UMOImmutableEndpoint endpoint, Throwable e);
375
376
377
378
379
380
381
382
383
384
385
386
387
388 public abstract void handleLifecycleException(Object component, Throwable e);
389
390
391
392
393
394
395 public abstract void handleStandardException(Throwable e);
396 }