View Javadoc

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