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