View Javadoc

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