View Javadoc

1   /*
2    * $Id: RouteableExceptionStrategy.java 20555 2010-12-09 17:54:31Z aperepel $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
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   * <code>RouteableExceptionStrategy</code> allows transforming and routing exceptions
37   * to outbound routers. This exception strategy does not take into account any
38   * defined endpoints in its instance variable.
39   * 
40   * @author estebanroblesluna
41   * @since 2.2.6
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       * {@inheritDoc}
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      * {@inheritDoc}
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      * {@inheritDoc}
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      * {@inheritDoc}
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      * {@inheritDoc}
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      * {@inheritDoc}
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         // copy the message
263         DefaultMuleMessage messageCopy = new DefaultMuleMessage(contextMsg.getPayload(), contextMsg, muleContext);
264 
265         // route the message
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 }