View Javadoc

1   /*
2    * $Id: ExceptionBasedRouter.java 7963 2007-08-21 08:53:15Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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.config.i18n.CoreMessages;
14  import org.mule.umo.UMOException;
15  import org.mule.umo.UMOExceptionPayload;
16  import org.mule.umo.UMOMessage;
17  import org.mule.umo.UMOSession;
18  import org.mule.umo.endpoint.UMOEndpoint;
19  import org.mule.umo.routing.CouldNotRouteOutboundMessageException;
20  import org.mule.umo.routing.RoutePathNotFoundException;
21  import org.mule.umo.routing.RoutingException;
22  
23  /**
24   * <code>ExceptionBasedRouter</code> Will send the current event to the first
25   * endpoint that doesn't throw an exception. If all attempted endpoints fail then an
26   * exception is thrown. <p/> The router will override the sync/async mode of the
27   * endpoint and force the sync mode for all endpoints except the last one.
28   * <code>remoteSync</code> is also enforced.
29   */
30  
31  public class ExceptionBasedRouter extends FilteringOutboundRouter
32  {
33  
34      public UMOMessage route(UMOMessage message, UMOSession session, boolean synchronous)
35          throws RoutingException
36      {
37          if (endpoints == null || endpoints.size() == 0)
38          {
39              throw new RoutePathNotFoundException(CoreMessages.noEndpointsForRouter(), message, null);
40          }
41  
42          final int endpointsCount = endpoints.size();
43  
44          if (enableCorrelation != ENABLE_CORRELATION_NEVER)
45          {
46              boolean correlationSet = message.getCorrelationId() != null;
47              if (correlationSet && (enableCorrelation == ENABLE_CORRELATION_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(endpointsCount);
55              }
56          }
57  
58          UMOMessage result = null;
59          // need that ref for an error message
60          UMOEndpoint endpoint = null;
61          boolean success = false;
62  
63          synchronized (endpoints)
64          {
65              for (int i = 0; i < endpointsCount; i++)
66              {
67                  // apply endpoint URI templates if any
68                  endpoint = getEndpoint(i, message);
69                  boolean lastEndpoint = (i == endpointsCount - 1);
70  
71                  if (!lastEndpoint)
72                  {
73                      logger.info("Sync mode will be forced for " + endpoint.getEndpointURI()
74                                  + ", as there are more endpoints available.");
75                  }
76  
77                  if (!lastEndpoint || synchronous)
78                  {
79                      try
80                      {
81                          result = send(session, message, endpoint);
82                          if (!exceptionPayloadAvailable(result))
83                          {
84                              if (logger.isDebugEnabled())
85                              {
86                                  logger.debug("Successful invocation detected, stopping further processing.");
87                              }
88                              success = true;
89                              break;
90                          }
91                      }
92                      catch (UMOException e)
93                      {
94                          logger.info("Failed to send to endpoint: " + endpoint.getEndpointURI().toString()
95                                      + ". Error was: " + e.getMessage() + ". Trying next endpoint");
96                      }
97                  }
98                  else
99                  {
100                     try
101                     {
102                         dispatch(session, message, endpoint);
103                         success = true;
104                         break;
105                     }
106                     catch (UMOException e)
107                     {
108                         logger.info("Failed to dispatch to endpoint: " + endpoint.getEndpointURI().toString()
109                                     + ". Error was: " + e.getMessage() + ". Trying next endpoint");
110                     }
111                 }
112             }
113         }
114 
115         if (!success)
116         {
117             throw new CouldNotRouteOutboundMessageException(message, endpoint);
118         }
119 
120         return result;
121     }
122 
123     public void addEndpoint(UMOEndpoint endpoint)
124     {
125         if (!endpoint.isRemoteSync())
126         {
127             logger.debug("Endpoint: "
128                          + endpoint.getEndpointURI()
129                          + " registered on ExceptionBasedRouter needs to be RemoteSync enabled. Setting this property now.");
130             endpoint.setRemoteSync(true);
131         }
132         super.addEndpoint(endpoint);
133     }
134 
135     /**
136      * @param message message to check
137      * @return true if there was an exception payload set
138      */
139     protected boolean exceptionPayloadAvailable(UMOMessage message)
140     {
141         if (message == null)
142         {
143             return false;
144         }
145 
146         final UMOExceptionPayload exceptionPayload = message.getExceptionPayload();
147         if (exceptionPayload != null)
148         {
149             logger.info("Failure returned, will try next endpoint. Exception payload is: " + exceptionPayload);
150             return true;
151         }
152         else
153         {
154             return false;
155         }
156     }
157 }