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