1
2
3
4
5
6
7
8
9
10
11 package org.mule;
12
13 import org.mule.api.MuleContext;
14 import org.mule.api.MuleEvent;
15 import org.mule.api.MuleException;
16 import org.mule.api.MuleMessage;
17 import org.mule.api.construct.FlowConstruct;
18 import org.mule.api.construct.FlowConstructAware;
19 import org.mule.api.context.MuleContextAware;
20 import org.mule.api.endpoint.ImmutableEndpoint;
21 import org.mule.api.lifecycle.Disposable;
22 import org.mule.api.lifecycle.Initialisable;
23 import org.mule.api.lifecycle.InitialisationException;
24 import org.mule.api.lifecycle.Lifecycle;
25 import org.mule.api.lifecycle.Stoppable;
26 import org.mule.api.routing.OutboundRouter;
27 import org.mule.exception.AbstractMessagingExceptionStrategy;
28 import org.mule.message.DefaultExceptionPayload;
29 import org.mule.session.DefaultMuleSession;
30 import org.mule.transport.NullPayload;
31 import org.mule.util.ObjectUtils;
32
33 import org.apache.commons.lang.exception.ExceptionUtils;
34
35
36
37
38
39
40
41
42
43 public class RouteableExceptionStrategy extends AbstractMessagingExceptionStrategy implements FlowConstructAware, Lifecycle
44 {
45
46 private OutboundRouter router;
47
48 private boolean stopFurtherProcessing = true;
49
50
51
52
53 public MuleEvent handleException(Exception e, MuleEvent event)
54 {
55 int currentRootExceptionHashCode = 0;
56 int originalRootExceptionHashCode = 0;
57 MuleMessage msg = null;
58
59 StringBuffer logInfo = new StringBuffer();
60
61 try
62 {
63 logInfo.append("****++******Alternate Exception Strategy******++*******\n");
64 logInfo.append("Current Thread = " + Thread.currentThread().toString() + "\n");
65
66 if (event != null && event.getFlowConstruct() != null)
67 {
68 String serviceName = event.getFlowConstruct().getName();
69 logInfo.append("serviceName = " + serviceName + "\n");
70
71 int eventHashCode = event.hashCode();
72 logInfo.append("eventHashCode = " + eventHashCode + "\n");
73 }
74
75 if (event != null && event.isStopFurtherProcessing())
76 {
77 logInfo.append("MuleEvent stop further processing has been set, This is probably the same exception being routed again. no Exception routing will be performed.\n"
78 + e
79 + "\n");
80 event.getMessage().setPayload(NullPayload.getInstance());
81 event.getMessage().setExceptionPayload(new DefaultExceptionPayload(e));
82 return event;
83 }
84
85 Throwable root = ExceptionUtils.getRootCause(e);
86 currentRootExceptionHashCode = root == null ? -1 : root.hashCode();
87
88 msg = event == null ? null : event.getMessage();
89
90 if (msg != null)
91 {
92 int msgHashCode = msg.hashCode();
93 logInfo.append("msgHashCode = " + msgHashCode + "\n");
94
95 if (msg.getExceptionPayload() != null)
96 {
97 Throwable t = msg.getExceptionPayload().getRootException();
98 if (t != null && t.hashCode() == currentRootExceptionHashCode)
99 {
100 logInfo.append("*#*#*#*#*\n");
101 logInfo.append("This error has already been handeled, returning without doing anything: "
102 + e.getMessage()
103 + "\n");
104 logInfo.append("*#*#*#*#*\n");
105 originalRootExceptionHashCode = currentRootExceptionHashCode;
106 event.getMessage().setPayload(NullPayload.getInstance());
107 event.getMessage().setExceptionPayload(new DefaultExceptionPayload(e));
108 return event;
109 }
110 }
111
112 originalRootExceptionHashCode = msg.getIntProperty("RootExceptionHashCode", 0);
113
114 logInfo.append("Original RootExceptionHashCode: " + originalRootExceptionHashCode + "\n");
115 logInfo.append("Current RootExceptionHashCode: " + currentRootExceptionHashCode + "\n");
116
117 if (originalRootExceptionHashCode == 0)
118 {
119 msg.setIntProperty("RootExceptionHashCode", currentRootExceptionHashCode);
120 originalRootExceptionHashCode = currentRootExceptionHashCode;
121 }
122 else if (originalRootExceptionHashCode == currentRootExceptionHashCode)
123 {
124 logInfo.append("*#*#*#*#*\n");
125 logInfo.append("This error has already been handeled, returning without doing anything: "
126 + e.getMessage()
127 + "\n");
128 logInfo.append("*#*#*#*#*\n");
129 event.getMessage().setPayload(NullPayload.getInstance());
130 event.getMessage().setExceptionPayload(new DefaultExceptionPayload(e));
131 return event;
132 }
133 else
134 {
135 msg.setIntProperty("RootExceptionHashCode", currentRootExceptionHashCode);
136 }
137 }
138
139 logInfo.append(e.getMessage());
140
141 StackTraceElement[] st = e.getStackTrace();
142 for (int i = 0; i < st.length; i++)
143 {
144 if (st[i].getClassName().equals("org.mule.AlternateExceptionStrategy"))
145 {
146 logger.warn("*#*#*#*#*\n"
147 + "Recursive error in AlternateExceptionStrategy "
148 + e
149 + "\n"
150 + "*#*#*#*#*");
151 event.getMessage().setPayload(NullPayload.getInstance());
152 event.getMessage().setExceptionPayload(new DefaultExceptionPayload(e));
153 return event;
154 }
155 logger.debug(st[i].toString());
156 }
157 return super.handleException(e, event);
158 }
159 finally
160 {
161 if (event != null && this.stopFurtherProcessing) event.setStopFurtherProcessing(true);
162
163 if (msg != null && currentRootExceptionHashCode != 0
164 && currentRootExceptionHashCode != originalRootExceptionHashCode)
165 msg.setIntProperty("RootExceptionHashCode", currentRootExceptionHashCode);
166
167 logInfo.append("****__******Alternate Exception Strategy******__*******\n");
168 logger.debug(logInfo.toString());
169 }
170 }
171
172
173
174
175 public void handleMessagingException(MuleMessage message, Throwable t)
176 {
177 defaultHandler(message, t);
178 routeException(getMessageFromContext(message), (ImmutableEndpoint) null, t);
179 }
180
181
182
183
184 public void handleRoutingException(MuleMessage message, ImmutableEndpoint endpoint, Throwable t)
185 {
186 defaultHandler(message, t);
187 routeException(getMessageFromContext(message), endpoint, t);
188 }
189
190
191
192
193 public void handleLifecycleException(Object component, Throwable t)
194 {
195 logger.error("The object that failed is: \n" + ObjectUtils.toString(component, "null"));
196 handleStandardException(t);
197 }
198
199
200
201
202 public void handleStandardException(Throwable t)
203 {
204 handleTransaction(t);
205 if (RequestContext.getEvent() != null)
206 {
207 handleMessagingException(RequestContext.getEvent().getMessage(), t);
208 }
209 else
210 {
211 logger.info("There is no current event available, routing Null message with the exception");
212 handleMessagingException(new DefaultMuleMessage(NullPayload.getInstance(), muleContext), t);
213 }
214 }
215
216 protected void defaultHandler(MuleMessage message, Throwable t)
217 {
218 if (RequestContext.getEvent() != null && RequestContext.getEvent().getMessage() != null)
219 {
220 RequestContext.getEvent().getMessage().setExceptionPayload(new DefaultExceptionPayload(t));
221 }
222
223 if (message != null) message.setExceptionPayload(new DefaultExceptionPayload(t));
224 }
225
226 protected MuleMessage getMessageFromContext(MuleMessage message)
227 {
228 if (RequestContext.getEvent() != null)
229 {
230 return RequestContext.getEvent().getMessage();
231 }
232 else if (message != null)
233 {
234 return message;
235 }
236 else
237 {
238 return new DefaultMuleMessage(NullPayload.getInstance(), muleContext);
239 }
240 }
241
242
243
244
245 protected void routeException(MuleMessage msg, ImmutableEndpoint failedEndpoint, Throwable t)
246 {
247 MuleMessage contextMsg = null;
248 MuleEvent exceptionEvent = RequestContext.getEvent();
249 contextMsg = exceptionEvent == null ? msg : exceptionEvent.getMessage();
250
251 if (contextMsg == null)
252 {
253 contextMsg = new DefaultMuleMessage(NullPayload.getInstance(), muleContext);
254 contextMsg.setExceptionPayload(new DefaultExceptionPayload(t));
255 }
256
257 if (exceptionEvent == null)
258 {
259 exceptionEvent = new DefaultMuleEvent(contextMsg, failedEndpoint, new DefaultMuleSession(muleContext));
260 }
261
262
263 DefaultMuleMessage messageCopy = new DefaultMuleMessage(contextMsg.getPayload(), contextMsg, muleContext);
264
265
266 try
267 {
268 router.process(exceptionEvent);
269 }
270 catch (MuleException e)
271 {
272 logFatal(messageCopy, e);
273 }
274 }
275
276 public OutboundRouter getRouter()
277 {
278 return router;
279 }
280
281 public void setRouter(OutboundRouter router)
282 {
283 this.router = router;
284 }
285
286 public boolean isStopFurtherProcessing()
287 {
288 return stopFurtherProcessing;
289 }
290
291 public void setStopFurtherProcessing(boolean stopFurtherProcessing)
292 {
293 this.stopFurtherProcessing = stopFurtherProcessing;
294 }
295
296 public void setFlowConstruct(FlowConstruct flowConstruct)
297 {
298 if (router instanceof FlowConstructAware)
299 {
300 router.setFlowConstruct(flowConstruct);
301 }
302 }
303
304 @Override
305 public void setMuleContext(MuleContext context)
306 {
307 super.setMuleContext(context);
308 if (router instanceof MuleContextAware)
309 {
310 router.setMuleContext(context);
311 }
312 }
313
314 @Override
315 protected void doInitialise(MuleContext muleContext) throws InitialisationException
316 {
317 super.doInitialise(muleContext);
318 if (router instanceof Initialisable)
319 {
320 router.initialise();
321 }
322 }
323
324 @Override
325 public void dispose()
326 {
327 super.dispose();
328 if (router instanceof Disposable)
329 {
330 router.dispose();
331 }
332 }
333
334 public void stop() throws MuleException
335 {
336 if (router instanceof Stoppable)
337 {
338 router.stop();
339 }
340 }
341
342 public void start() throws MuleException
343 {
344 if (router instanceof Stoppable)
345 {
346 router.stop();
347 }
348 }
349 }