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 logException(e);
92
93 Throwable t = getExceptionType(e, RoutingException.class);
94 if (t != null)
95 {
96 RoutingException re = (RoutingException) t;
97 handleRoutingException(re.getUmoMessage(), re.getEndpoint(), e);
98 return;
99 }
100
101 t = getExceptionType(e, MessagingException.class);
102 if (t != null)
103 {
104 MessagingException me = (MessagingException) t;
105 handleMessagingException(me.getUmoMessage(), e);
106 return;
107 }
108
109 t = getExceptionType(e, LifecycleException.class);
110 if (t != null)
111 {
112 LifecycleException le = (LifecycleException) t;
113 handleLifecycleException(le.getComponent(), e);
114 if (RequestContext.getEventContext() != null)
115 {
116 handleMessagingException(RequestContext.getEventContext().getMessage(), e);
117 }
118 else
119 {
120 logger.info("There is no current event available, routing Null message with the exception");
121 handleMessagingException(new MuleMessage(NullPayload.getInstance()), e);
122 }
123 return;
124 }
125
126 handleStandardException(e);
127 }
128
129 protected Throwable getExceptionType(Throwable t, Class exceptionType)
130 {
131 while (t != null)
132 {
133 if (exceptionType.isAssignableFrom(t.getClass()))
134 {
135 return t;
136 }
137
138 t = t.getCause();
139 }
140
141 return null;
142 }
143
144
145
146
147
148
149
150
151
152 public final synchronized void initialise() throws InitialisationException
153 {
154 if (!initialised.get())
155 {
156 doInitialise();
157 initialised.set(true);
158 }
159 }
160
161 protected void doInitialise() throws InitialisationException
162 {
163 logger.info("Initialising exception listener: " + toString());
164 for (Iterator iterator = endpoints.iterator(); iterator.hasNext();)
165 {
166 UMOEndpoint umoEndpoint = (UMOEndpoint) iterator.next();
167 umoEndpoint.initialise();
168 }
169 }
170
171
172
173
174
175
176 protected void markTransactionForRollback()
177 {
178 UMOTransaction tx = TransactionCoordination.getInstance().getTransaction();
179 try
180 {
181 if (tx != null)
182 {
183 tx.setRollbackOnly();
184 }
185 }
186 catch (TransactionException e)
187 {
188 logException(e);
189 }
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207 protected void routeException(UMOMessage message, UMOImmutableEndpoint failedEndpoint, Throwable t)
208 {
209 UMOEndpoint endpoint = getEndpoint(t);
210 if (endpoint != null)
211 {
212 try
213 {
214 logger.error("Message being processed is: " + (message == null ? "null" : message.toString()));
215 UMOEventContext ctx = RequestContext.getEventContext();
216 String component = "Unknown";
217 UMOEndpointURI endpointUri = null;
218 if (ctx != null)
219 {
220 if (ctx.getComponentDescriptor() != null)
221 {
222 component = ctx.getComponentDescriptor().getName();
223 }
224 endpointUri = ctx.getEndpointURI();
225 }
226 else if (failedEndpoint != null)
227 {
228 endpointUri = failedEndpoint.getEndpointURI();
229 }
230 ExceptionMessage msg;
231 msg = new ExceptionMessage(getErrorMessagePayload(message), t, component, endpointUri);
232
233 UMOMessage exceptionMessage;
234 if (ctx == null)
235 {
236 exceptionMessage = new MuleMessage(msg);
237 }
238 else
239 {
240 exceptionMessage = new MuleMessage(msg, ctx.getMessage());
241 }
242 UMOEvent exceptionEvent = new MuleEvent(exceptionMessage, endpoint, new MuleSession(
243 exceptionMessage, new MuleSessionHandler()), true);
244 exceptionEvent = RequestContext.setEvent(exceptionEvent);
245 endpoint.send(exceptionEvent);
246
247 if (logger.isDebugEnabled())
248 {
249 logger.debug("routed Exception message via " + endpoint);
250 }
251
252 }
253 catch (UMOException e)
254 {
255 logFatal(message, e);
256 }
257 }
258 else
259 {
260 markTransactionForRollback();
261 }
262 }
263
264 protected Object getErrorMessagePayload(UMOMessage message)
265 {
266 try
267 {
268 return message.getPayloadAsString();
269 }
270 catch (Exception e)
271 {
272 logException(e);
273 logger.info("Failed to read message payload as string, using raw payload");
274 return message.getPayload();
275 }
276 }
277
278
279
280
281
282
283
284
285
286
287
288 protected UMOEndpoint getEndpoint(Throwable t)
289 {
290 if (endpoints.size() > 0)
291 {
292 return (UMOEndpoint) endpoints.get(0);
293 }
294 else
295 {
296 return null;
297 }
298 }
299
300
301
302
303
304
305 protected void logException(Throwable t)
306 {
307 UMOException umoe = ExceptionHelper.getRootMuleException(t);
308 if (umoe != null)
309 {
310 logger.error(umoe.getDetailedMessage());
311 }
312 else
313 {
314 logger.error("Caught exception in Exception Strategy: " + t.getMessage(), t);
315 }
316 }
317
318
319
320
321
322
323
324
325
326 protected void logFatal(UMOMessage message, Throwable t)
327 {
328 logger.fatal(
329 "Failed to dispatch message to error queue after it failed to process. This may cause message loss."
330 + (message == null ? "" : "Logging Message here: \n" + message.toString()), t);
331 }
332
333 public boolean isInitialised()
334 {
335 return initialised.get();
336 }
337
338
339
340
341
342
343
344
345 protected void fireNotification(ExceptionNotification notification)
346 {
347 MuleManager.getInstance().fireNotification(notification);
348 }
349
350
351
352
353
354
355
356
357
358
359
360 public abstract void handleMessagingException(UMOMessage message, Throwable e);
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375 public abstract void handleRoutingException(UMOMessage message, UMOImmutableEndpoint endpoint, Throwable e);
376
377
378
379
380
381
382
383
384
385
386
387
388
389 public abstract void handleLifecycleException(Object component, Throwable e);
390
391
392
393
394
395
396 public abstract void handleStandardException(Throwable e);
397 }