View Javadoc

1   /*
2    * $Id$
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.MuleEvent;
14  import org.mule.api.MuleException;
15  import org.mule.api.MuleMessage;
16  import org.mule.api.endpoint.ImmutableEndpoint;
17  import org.mule.api.routing.OutboundRouter;
18  import org.mule.exception.AbstractMessagingExceptionStrategy;
19  import org.mule.message.DefaultExceptionPayload;
20  import org.mule.session.DefaultMuleSession;
21  import org.mule.transport.NullPayload;
22  import org.mule.util.ObjectUtils;
23  
24  import org.apache.commons.lang.exception.ExceptionUtils;
25  
26  /**
27   * <code>RouteableExceptionStrategy</code> allows transforming and routing exceptions
28   * to outbound routers. This exception strategy does not take into account any
29   * defined endpoints in its instance variable.
30   * 
31   * @author estebanroblesluna
32   * @since 2.2.6
33   */
34  public class RouteableExceptionStrategy extends AbstractMessagingExceptionStrategy
35  {
36      private OutboundRouter router;
37  
38      private boolean stopFurtherProcessing = true;
39  
40      /**
41       * {@inheritDoc}
42       */
43      public MuleEvent handleException(Exception e, MuleEvent event)
44      {
45          int currentRootExceptionHashCode = 0;
46          int originalRootExceptionHashCode = 0;
47          MuleMessage msg = null;
48  
49          StringBuffer logInfo = new StringBuffer();
50          
51          try
52          {
53              logInfo.append("****++******Alternate Exception Strategy******++*******\n");
54              logInfo.append("Current Thread = " + Thread.currentThread().toString() + "\n");
55  
56              if (event != null && event.getFlowConstruct() != null)
57              {
58                  String serviceName = event.getFlowConstruct().getName();
59                  logInfo.append("serviceName = " + serviceName + "\n");
60  
61                  int eventHashCode = event.hashCode();
62                  logInfo.append("eventHashCode = " + eventHashCode + "\n");
63              }
64  
65              if (event != null && event.isStopFurtherProcessing())
66              {
67                  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"
68                              + e
69                              + "\n");
70                  event.getMessage().setPayload(NullPayload.getInstance());
71                  event.getMessage().setExceptionPayload(new DefaultExceptionPayload(e));
72                  return event;
73              }
74  
75              Throwable root = ExceptionUtils.getRootCause(e);
76              currentRootExceptionHashCode = root == null ? -1 : root.hashCode();
77  
78              msg = event == null ? null : event.getMessage();
79  
80              if (msg != null)
81              {
82                  int msgHashCode = msg.hashCode();
83                  logInfo.append("msgHashCode = " + msgHashCode + "\n");
84  
85                  if (msg.getExceptionPayload() != null)
86                  {
87                      Throwable t = msg.getExceptionPayload().getRootException();
88                      if (t != null && t.hashCode() == currentRootExceptionHashCode)
89                      {
90                          logInfo.append("*#*#*#*#*\n");
91                          logInfo.append("This error has already been handeled, returning without doing anything: "
92                                      + e.getMessage()
93                                      + "\n");
94                          logInfo.append("*#*#*#*#*\n");
95                          originalRootExceptionHashCode = currentRootExceptionHashCode;
96                          event.getMessage().setPayload(NullPayload.getInstance());
97                          event.getMessage().setExceptionPayload(new DefaultExceptionPayload(e));
98                          return event;
99                      }
100                 }
101 
102                 originalRootExceptionHashCode = msg.getIntProperty("RootExceptionHashCode", 0);
103 
104                 logInfo.append("Original RootExceptionHashCode: " + originalRootExceptionHashCode + "\n");
105                 logInfo.append("Current  RootExceptionHashCode: " + currentRootExceptionHashCode + "\n");
106 
107                 if (originalRootExceptionHashCode == 0)
108                 {
109                     msg.setIntProperty("RootExceptionHashCode", currentRootExceptionHashCode);
110                     originalRootExceptionHashCode = currentRootExceptionHashCode;
111                 }
112                 else if (originalRootExceptionHashCode == currentRootExceptionHashCode)
113                 {
114                     logInfo.append("*#*#*#*#*\n");
115                     logInfo.append("This error has already been handeled, returning without doing anything: "
116                                 + e.getMessage()
117                                 + "\n");
118                     logInfo.append("*#*#*#*#*\n");
119                     event.getMessage().setPayload(NullPayload.getInstance());
120                     event.getMessage().setExceptionPayload(new DefaultExceptionPayload(e));
121                     return event;
122                 }
123                 else
124                 {
125                     msg.setIntProperty("RootExceptionHashCode", currentRootExceptionHashCode);
126                 }
127             }
128 
129             logInfo.append(e.getMessage());
130 
131             StackTraceElement[] st = e.getStackTrace();
132             for (int i = 0; i < st.length; i++)
133             {
134                 if (st[i].getClassName().equals("org.mule.AlternateExceptionStrategy"))
135                 {
136                     logger.warn("*#*#*#*#*\n"
137                         + "Recursive error in AlternateExceptionStrategy " 
138                         + e
139                         + "\n"
140                         + "*#*#*#*#*");
141                     event.getMessage().setPayload(NullPayload.getInstance());
142                     event.getMessage().setExceptionPayload(new DefaultExceptionPayload(e));
143                     return event;
144                 }
145                 logger.debug(st[i].toString());
146             }
147             return super.handleException(e, event);
148         }
149         finally
150         {
151             if (event != null && this.stopFurtherProcessing) event.setStopFurtherProcessing(true);
152 
153             if (msg != null && currentRootExceptionHashCode != 0
154                 && currentRootExceptionHashCode != originalRootExceptionHashCode)
155                 msg.setIntProperty("RootExceptionHashCode", currentRootExceptionHashCode);
156 
157             logInfo.append("****__******Alternate Exception Strategy******__*******\n");
158             logger.debug(logInfo.toString());
159         }
160     }
161 
162     /**
163      * {@inheritDoc}
164      */
165     public void handleMessagingException(MuleMessage message, Throwable t)
166     {
167         defaultHandler(message, t);
168         routeException(getMessageFromContext(message), (ImmutableEndpoint) null, t);
169     }
170 
171     /**
172      * {@inheritDoc}
173      */
174     public void handleRoutingException(MuleMessage message, ImmutableEndpoint endpoint, Throwable t)
175     {
176         defaultHandler(message, t);
177         routeException(getMessageFromContext(message), endpoint, t);
178     }
179 
180     /**
181      * {@inheritDoc}
182      */
183     public void handleLifecycleException(Object component, Throwable t)
184     {
185         logger.error("The object that failed is: \n" + ObjectUtils.toString(component, "null"));
186         handleStandardException(t);
187     }
188 
189     /**
190      * {@inheritDoc}
191      */
192     public void handleStandardException(Throwable t)
193     {
194         handleTransaction(t);
195         if (RequestContext.getEvent() != null)
196         {
197             handleMessagingException(RequestContext.getEvent().getMessage(), t);
198         }
199         else
200         {
201             logger.info("There is no current event available, routing Null message with the exception");
202             handleMessagingException(new DefaultMuleMessage(NullPayload.getInstance(), muleContext), t);
203         }
204     }
205 
206     protected void defaultHandler(MuleMessage message, Throwable t)
207     {
208         if (RequestContext.getEvent() != null && RequestContext.getEvent().getMessage() != null)
209         {
210             RequestContext.getEvent().getMessage().setExceptionPayload(new DefaultExceptionPayload(t));
211         }
212 
213         if (message != null) message.setExceptionPayload(new DefaultExceptionPayload(t));
214     }
215 
216     protected MuleMessage getMessageFromContext(MuleMessage message)
217     {
218         if (RequestContext.getEvent() != null)
219         {
220             return RequestContext.getEvent().getMessage();
221         }
222         else if (message != null)
223         {
224             return message;
225         }
226         else
227         {
228             return new DefaultMuleMessage(NullPayload.getInstance(), muleContext);
229         }
230     }
231 
232     /**
233      * {@inheritDoc}
234      */
235     protected void routeException(MuleMessage msg, ImmutableEndpoint failedEndpoint, Throwable t)
236     {
237         MuleMessage contextMsg = null;
238         MuleEvent exceptionEvent = RequestContext.getEvent();
239         contextMsg = exceptionEvent == null ? msg : exceptionEvent.getMessage();
240 
241         if (contextMsg == null)
242         {
243             contextMsg = new DefaultMuleMessage(NullPayload.getInstance(), muleContext);
244             contextMsg.setExceptionPayload(new DefaultExceptionPayload(t));
245         }
246 
247         if (exceptionEvent == null)
248         {
249             exceptionEvent = new DefaultMuleEvent(contextMsg, failedEndpoint, new DefaultMuleSession(muleContext));
250         }
251 
252         // copy the message
253         DefaultMuleMessage messageCopy = new DefaultMuleMessage(contextMsg.getPayload(), contextMsg, muleContext);
254 
255         // route the message
256         try
257         {
258             router.process(exceptionEvent);
259         }
260         catch (MuleException e)
261         {
262             logFatal(messageCopy, e);
263         }
264     }
265 
266     public OutboundRouter getRouter()
267     {
268         return router;
269     }
270 
271     public void setRouter(OutboundRouter router)
272     {
273         this.router = router;
274     }
275 
276     public boolean isStopFurtherProcessing()
277     {
278         return stopFurtherProcessing;
279     }
280 
281     public void setStopFurtherProcessing(boolean stopFurtherProcessing)
282     {
283         this.stopFurtherProcessing = stopFurtherProcessing;
284     }
285 }