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.MessagingException;
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.processor.MessageProcessor;
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.routing.CorrelationMode;
21  
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  /**
26   * Defines a router that sequentially routes a given message to the list of
27   * registered endpoints and returns the aggregate responses as the result.
28   * Aggregate response is built using the partial responses obtained from
29   * synchronous endpoints.
30   * The routing process can be stopped after receiving a partial response.
31   */
32  public abstract class AbstractSequenceRouter extends FilteringOutboundRouter
33  {
34  
35      @Override
36      public MuleEvent route(MuleEvent event) throws RoutingException
37      {
38          MuleMessage message = event.getMessage();
39  
40          if (routes == null || routes.size() == 0)
41          {
42              throw new RoutePathNotFoundException(CoreMessages.noEndpointsForRouter(), event, null);
43          }
44          if (enableCorrelation != CorrelationMode.NEVER)
45          {
46              boolean correlationSet = message.getCorrelationId() != null;
47              if (correlationSet && (enableCorrelation == CorrelationMode.IF_NOT_SET))
48              {
49                  logger.debug("CorrelationId is already set, not setting Correlation group size");
50              }
51              else
52              {
53                  // the correlationId will be set by the AbstractOutboundRouter
54                  message.setCorrelationGroupSize(routes.size());
55              }
56          }
57  
58          List<MuleEvent> results = new ArrayList<MuleEvent>(routes.size());
59          try
60          {
61              for (int i = 0; i < routes.size(); i++)
62              {
63                  MessageProcessor mp = getRoute(i,event);
64                  OutboundEndpoint endpoint = mp instanceof OutboundEndpoint ? (OutboundEndpoint)mp : null;
65                  if (endpoint == null || endpoint.getFilter() == null || (endpoint.getFilter() != null && endpoint.getFilter().accept(message)))
66                  {
67                      MuleMessage clonedMessage = cloneMessage(event, message);
68                      MuleEvent result = sendRequest(event, clonedMessage, mp, true);
69                      if (result != null)
70                      {
71                          results.add(result);
72                      }
73  
74                      if (!continueRoutingMessageAfter(result))
75                      {
76                          break;
77                      }
78                  }
79              }
80          }
81          catch (MuleException e)
82          {
83              throw new CouldNotRouteOutboundMessageException(event, routes.get(0), e);
84          }
85          return resultsHandler.aggregateResults(results, event, muleContext);
86      }
87  
88  
89      /**
90       * Lets subclasses decide if the routing of a given message should continue
91       * or not after receiving a given response from a synchronous endpoint.
92       *
93       * @param response the last received response
94       * @return true if must continue and false otherwise.
95       * @throws MuleException when the router should stop processing throwing an
96       *                       exception without returning any results to the caller.
97       */
98      protected abstract boolean continueRoutingMessageAfter(MuleEvent response) throws MuleException;
99  }