View Javadoc

1   /*
2    * $Id: ExceptionBasedRouter.java 19751 2010-09-28 11:33:56Z dirk.olmes $
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.routing.outbound;
12  
13  import org.mule.DefaultMuleMessage;
14  import org.mule.api.ExceptionPayload;
15  import org.mule.api.MuleEvent;
16  import org.mule.api.MuleException;
17  import org.mule.api.MuleMessage;
18  import org.mule.api.endpoint.OutboundEndpoint;
19  import org.mule.api.expression.RequiredValueException;
20  import org.mule.api.routing.CouldNotRouteOutboundMessageException;
21  import org.mule.api.routing.RoutePathNotFoundException;
22  import org.mule.api.routing.RoutingException;
23  import org.mule.config.i18n.CoreMessages;
24  import org.mule.config.i18n.MessageFactory;
25  import org.mule.routing.CorrelationMode;
26  
27  import java.util.ArrayList;
28  import java.util.Iterator;
29  import java.util.List;
30  
31  /**
32   * <code>ExceptionBasedRouter</code> Will send the current event to the first
33   * endpoint that doesn't throw an exception. If all attempted targets fail then an
34   * exception is thrown. <p/> The router will override the sync/async mode of the
35   * endpoint and force the sync mode for all targets except the last one.
36   */
37  public class ExceptionBasedRouter extends ExpressionRecipientList
38  {
39      @Override
40      public MuleEvent route(MuleEvent event) throws RoutingException
41      {
42          MuleMessage message = event.getMessage();
43  
44          List recipients = null;
45          try
46          {
47              recipients = getRecipients(event);
48          }
49          catch (RequiredValueException e)
50          {
51              // ignore because the recipient list is optional for this router
52          }
53  
54          if (recipients == null)
55          {
56              int endpointsCount = routes.size();
57              recipients = new ArrayList(endpointsCount);
58              for (int i = 0; i < endpointsCount; i++)
59              {
60                  recipients.add(getRoute(i, event));
61              }
62          }        
63          
64          if (recipients.size() == 0)
65          {
66              throw new RoutePathNotFoundException(CoreMessages.noEndpointsForRouter(), event, null);
67          }
68  
69          if (enableCorrelation != CorrelationMode.NEVER)
70          {
71              boolean correlationSet = message.getCorrelationId() != null;
72              if (correlationSet && (enableCorrelation == CorrelationMode.IF_NOT_SET))
73              {
74                  logger.debug("CorrelationId is already set, not setting Correlation group size");
75              }
76              else
77              {
78                  // the correlationId will be set by the AbstractOutboundRouter
79                  message.setCorrelationGroupSize(recipients.size());
80              }
81          }
82  
83          MuleEvent result = null;
84          OutboundEndpoint endpoint = null;
85          MuleMessage request = null;
86          boolean success = false;
87  
88          for (Iterator iterator = recipients.iterator(); iterator.hasNext();)
89          {
90              request = new DefaultMuleMessage(message.getPayload(), message, muleContext);
91              try
92              {
93                  endpoint = getRecipientEndpoint(request, iterator.next());
94                  boolean lastEndpoint = !iterator.hasNext();
95      
96                  // TODO MULE-4476
97                  if (!lastEndpoint && !endpoint.getExchangePattern().hasResponse())
98                  {
99                      throw new CouldNotRouteOutboundMessageException(
100                         MessageFactory.createStaticMessage("The ExceptionBasedRouter does not support asynchronous endpoints, make sure all endpoints on the router are configured as synchronous"), event, endpoint);
101                 }
102                 
103                 if (endpoint.getExchangePattern().hasResponse())
104                 {
105                     MuleMessage resultMessage = null;
106                     result = sendRequest(event, request, endpoint, true);
107                     if (result != null)
108                     {
109                         resultMessage = result.getMessage();
110                     }
111                     if (resultMessage != null)
112                     {
113                         resultMessage.applyTransformers(result, endpoint.getResponseTransformers());
114                     }
115                     if (!exceptionPayloadAvailable(resultMessage))
116                     {
117                         if (logger.isDebugEnabled())
118                         {
119                             logger.debug("Successful invocation detected, stopping further processing.");
120                         }
121                         success = true;
122                         break;
123                     }
124                 }
125                 else
126                 {
127                     sendRequest(event, request, endpoint, false);
128                     success = true;
129                     break;
130                 }
131             }
132             catch (MuleException e)
133             {
134                 logger.info("Failed to send/dispatch to endpoint: " + endpoint.getEndpointURI().toString()
135                             + ". Error was: " + e.getMessage() + ". Trying next endpoint");
136             }
137         }
138 
139         if (!success)
140         {
141             throw new CouldNotRouteOutboundMessageException(event, endpoint);
142         }
143 
144         return result;
145     }
146 
147     /**
148      * @param message message to check
149      * @return true if there was an exception payload set
150      */
151     protected boolean exceptionPayloadAvailable(MuleMessage message)
152     {
153         if (message == null)
154         {
155             return false;
156         }
157 
158         final ExceptionPayload exceptionPayload = message.getExceptionPayload();
159         if (exceptionPayload != null)
160         {
161             logger.info("Failure returned, will try next endpoint. Exception payload is: " + exceptionPayload);
162             return true;
163         }
164         else
165         {
166             return false;
167         }
168     }
169     
170 }