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.DefaultMuleEvent;
10  import org.mule.DefaultMuleMessage;
11  import org.mule.api.MuleEvent;
12  import org.mule.api.MuleException;
13  import org.mule.api.MuleMessage;
14  import org.mule.api.MuleSession;
15  import org.mule.api.endpoint.OutboundEndpoint;
16  import org.mule.api.processor.MessageProcessor;
17  import org.mule.api.routing.CouldNotRouteOutboundMessageException;
18  import org.mule.api.routing.RoutingException;
19  import org.mule.message.DefaultExceptionPayload;
20  import org.mule.routing.LoggingCatchAllStrategy;
21  import org.mule.routing.filters.RegExFilter;
22  import org.mule.tck.MuleTestUtils;
23  import org.mule.tck.junit4.AbstractMuleContextTestCase;
24  
25  import com.mockobjects.dynamic.Mock;
26  
27  import java.util.ArrayList;
28  import java.util.List;
29  
30  import org.junit.Test;
31  
32  import static org.junit.Assert.assertEquals;
33  import static org.junit.Assert.assertNotNull;
34  import static org.junit.Assert.assertNull;
35  import static org.junit.Assert.assertTrue;
36  import static org.junit.Assert.fail;
37  
38  public class ExceptionBasedRouterTestCase extends AbstractMuleContextTestCase
39  {
40      public ExceptionBasedRouterTestCase()
41      {
42          setStartContext(true);
43      }
44  
45      /**
46       * Multiple targets, no failures. MuleEvent dispatched asynchronously, but forced
47       * into sync mode. Test case ends here.
48       */
49      /* TODO MULE-4476
50      @Test
51      public void testSuccessfulExceptionRouterAsynchronous() throws Exception
52      {
53          Mock mockSession = MuleTestUtils.getMockSession();
54          mockSession.matchAndReturn("getFlowConstruct", getTestService());
55  
56          DefaultOutboundRouterCollection messageRouter = new DefaultOutboundRouterCollection();
57          messageRouter.setCatchAllStrategy(new LoggingCatchAllStrategy());
58  
59          OutboundEndpoint endpoint1 = muleContext.getRegistry()
60              .lookupEndpointFactory()
61              .getOutboundEndpoint("test://Dummy1");
62  
63          OutboundEndpoint endpoint2 = muleContext.getRegistry()
64              .lookupEndpointFactory()
65              .getOutboundEndpoint("test://Dummy2");
66  
67          OutboundEndpoint endpoint3 = muleContext.getRegistry()
68              .lookupEndpointFactory()
69              .getOutboundEndpoint("test://Dummy3");
70  
71          Mock mockendpoint1 = RouterTestUtils.getMockEndpoint(endpoint1);
72          Mock mockendpoint2 = RouterTestUtils.getMockEndpoint(endpoint2);
73          Mock mockendpoint3 = RouterTestUtils.getMockEndpoint(endpoint3);
74          ExceptionBasedRouter router = new ExceptionBasedRouter();
75          router.setMuleContext(muleContext);
76          RegExFilter filter = new RegExFilter("(.*) event");
77          router.setFilter(filter);
78          List<MessageProcessor> endpoints = new ArrayList<MessageProcessor>();
79          endpoints.add((OutboundEndpoint) mockendpoint1.proxy());
80          endpoints.add((OutboundEndpoint) mockendpoint2.proxy());
81          endpoints.add((OutboundEndpoint) mockendpoint3.proxy());
82          router.setRoutes(endpoints);
83  
84          assertEquals(filter, router.getFilter());
85  
86          MuleMessage message = new DefaultMuleMessage("test event", muleContext);
87  
88          assertTrue(router.isMatch(message));
89  
90          mockendpoint1.expect("process", RouterTestUtils.getArgListCheckerMuleEvent());
91          MuleEvent result = router.route(new OutboundRoutingTestEvent(message, (MuleSession)mockSession.proxy()));
92          assertNull("Async call should've returned null.", result);
93          mockendpoint1.verify();
94      }
95      */
96  
97      @Test
98      public void testSuccessfulExceptionRouterSynchronous() throws Exception
99      {
100         Mock mockSession = MuleTestUtils.getMockSession();
101         mockSession.matchAndReturn("getFlowConstruct", getTestService());
102 
103         DefaultOutboundRouterCollection messageRouter = new DefaultOutboundRouterCollection();
104         messageRouter.setCatchAllStrategy(new LoggingCatchAllStrategy());
105 
106         OutboundEndpoint endpoint1 =
107             muleContext.getEndpointFactory().getOutboundEndpoint("test://Dummy1?exchangePattern=request-response");
108 
109         OutboundEndpoint endpoint2 =
110             muleContext.getEndpointFactory().getOutboundEndpoint("test://Dummy2?exchangePattern=request-response");
111 
112         OutboundEndpoint endpoint3 =
113             muleContext.getEndpointFactory().getOutboundEndpoint("test://Dummy3?exchangePattern=request-response");
114 
115         Mock mockendpoint1 = RouterTestUtils.getMockEndpoint(endpoint1);
116         Mock mockendpoint2 = RouterTestUtils.getMockEndpoint(endpoint2);
117         Mock mockendpoint3 = RouterTestUtils.getMockEndpoint(endpoint3);
118 
119         ExceptionBasedRouter router = new ExceptionBasedRouter();
120         router.setMuleContext(muleContext);
121         RegExFilter filter = new RegExFilter("(.*) event");
122         router.setFilter(filter);
123         List<MessageProcessor> endpoints = new ArrayList<MessageProcessor>();
124         endpoints.add((OutboundEndpoint) mockendpoint1.proxy());
125         endpoints.add((OutboundEndpoint) mockendpoint2.proxy());
126         endpoints.add((OutboundEndpoint) mockendpoint3.proxy());
127         router.setRoutes(endpoints);
128 
129         assertEquals(filter, router.getFilter());
130 
131         MuleMessage message = new DefaultMuleMessage("test event", muleContext);
132         MuleEvent event = new OutboundRoutingTestEvent(message, null);
133         // only one send should be called and succeed, the others should not be
134         // called
135         mockendpoint1.expectAndReturn("process", RouterTestUtils.getArgListCheckerMuleEvent(), event);
136         MuleEvent result = router.route(new OutboundRoutingTestEvent(message, (MuleSession)mockSession.proxy()));
137         assertNotNull(result);
138         assertEquals(message, result.getMessage());
139         mockendpoint1.verify();
140     }
141 
142     /**
143      * Both targets fail during dispatch. The first endpoint should be forced into
144      * sync mode.
145      */
146     @Test
147     public void testBothFailing() throws Exception
148     {
149         Mock mockSession = MuleTestUtils.getMockSession();
150         mockSession.matchAndReturn("getFlowConstruct", getTestService());
151 
152         OutboundEndpoint endpoint1 =
153             muleContext.getEndpointFactory().getOutboundEndpoint("test://AlwaysFail");
154 
155         OutboundEndpoint endpoint2 =
156             muleContext.getEndpointFactory().getOutboundEndpoint("test://AlwaysFail");
157 
158         Mock mockendpoint1 = RouterTestUtils.getMockEndpoint(endpoint1);
159         Mock mockendpoint2 = RouterTestUtils.getMockEndpoint(endpoint2);
160 
161         ExceptionBasedRouter router = new ExceptionBasedRouter();
162         router.setMuleContext(muleContext);
163         RegExFilter filter = new RegExFilter("(.*) event");
164         router.setFilter(filter);
165         List<MessageProcessor> endpoints = new ArrayList<MessageProcessor>();
166         endpoints.add((OutboundEndpoint) mockendpoint1.proxy());
167         endpoints.add((OutboundEndpoint) mockendpoint2.proxy());
168         router.setRoutes(endpoints);
169 
170         assertEquals(filter, router.getFilter());
171 
172         MuleMessage message = new DefaultMuleMessage("test event", muleContext);
173 
174         assertTrue(router.isMatch(message));
175 
176         // exception to throw
177         MuleSession session = (MuleSession)mockSession.proxy();
178         MuleEvent eventToThrow = new DefaultMuleEvent(message, endpoint1, session);
179         MuleException rex = new RoutingException(eventToThrow, endpoint1);
180         mockendpoint1.expectAndThrow("process", RouterTestUtils.getArgListCheckerMuleEvent(), rex);
181         mockendpoint2.expectAndThrow("process", RouterTestUtils.getArgListCheckerMuleEvent(), rex);
182         MuleEvent result = null;
183         try
184         {
185             result = router.route(new OutboundRoutingTestEvent(message, session));
186             fail("Should have thrown exception as both targets would have failed");
187         }
188         catch (CouldNotRouteOutboundMessageException e)
189         {
190             // expected
191         }
192         assertNull("Async call should've returned null.", result);
193         mockSession.verify();
194 
195         message = new DefaultMuleMessage("test event", muleContext);
196     }
197 
198     /**
199      * The first endpoint fails, second succeeds. Events are being sent
200      * synchronously.
201      */
202     @Test
203     public void testFailFirstSuccessSecondSync() throws Exception
204     {
205         Mock mockSession = MuleTestUtils.getMockSession();
206         mockSession.matchAndReturn("getFlowConstruct", getTestService());
207 
208         OutboundEndpoint endpoint1 = getTestOutboundEndpoint("TestFailEndpoint",
209             "test://Failure?exchangePattern=request-response");
210         OutboundEndpoint endpoint2 = getTestOutboundEndpoint("TestSuccessEndpoint",
211             "test://Success?exchangePattern=request-response");
212         Mock mockendpoint1 = RouterTestUtils.getMockEndpoint(endpoint1);
213         Mock mockendpoint2 = RouterTestUtils.getMockEndpoint(endpoint2);
214 
215         ExceptionBasedRouter router = new ExceptionBasedRouter();
216         router.setMuleContext(muleContext);
217         router.addRoute((OutboundEndpoint) mockendpoint1.proxy());
218         router.addRoute((OutboundEndpoint) mockendpoint2.proxy());
219 
220         MuleMessage message = new DefaultMuleMessage("test event", muleContext);
221         MuleMessage expectedResultMessage = new DefaultMuleMessage("Return event", muleContext);
222         MuleEvent event = new OutboundRoutingTestEvent(expectedResultMessage, null);
223 
224         assertTrue(router.isMatch(message));
225 
226         final MuleSession session = (MuleSession)mockSession.proxy();
227         // exception to throw
228         MuleEvent eventToThrow = new DefaultMuleEvent(message, endpoint1, session);
229         MuleException rex = new RoutingException(eventToThrow, endpoint1);
230         // 1st failure
231         mockendpoint1.expectAndThrow("process", RouterTestUtils.getArgListCheckerMuleEvent(), rex);
232         mockendpoint2.expectAndReturn("process", RouterTestUtils.getArgListCheckerMuleEvent(), event);
233         MuleEvent actualResult = router.route(new OutboundRoutingTestEvent(message, session));
234         mockendpoint1.verify();
235         mockendpoint2.verify();
236 
237         assertEquals("Got an invalid return message.", expectedResultMessage, actualResult.getMessage());
238     }
239 
240     /**
241      * The first endpoint fails, second succeeds. Events are being forced into a sync
242      * mode, until we reach the last one.
243      */
244     @Test
245     public void testFailFirstSuccessSecondAsync() throws Exception
246     {
247         Mock mockSession = MuleTestUtils.getMockSession();
248         mockSession.matchAndReturn("getFlowConstruct", getTestService());
249 
250         OutboundEndpoint endpoint1 = getTestOutboundEndpoint("TestFailEndpoint",
251             "test://Failure?exchangePattern=request-response");
252         OutboundEndpoint endpoint2 = getTestOutboundEndpoint("TestSuccessEndpoint",
253             "test://Success?exchangePattern=one-way");
254         Mock mockendpoint1 = RouterTestUtils.getMockEndpoint(endpoint1);
255         Mock mockendpoint2 = RouterTestUtils.getMockEndpoint(endpoint2);
256 
257         ExceptionBasedRouter router = new ExceptionBasedRouter();
258         router.setMuleContext(muleContext);
259         router.addRoute((OutboundEndpoint) mockendpoint1.proxy());
260         router.addRoute((OutboundEndpoint) mockendpoint2.proxy());
261 
262         MuleMessage message = new DefaultMuleMessage("test event", muleContext);
263         MuleMessage expectedResultMessage = new DefaultMuleMessage("Return event", muleContext);
264         MuleEvent event = new OutboundRoutingTestEvent(expectedResultMessage, null);
265 
266         assertTrue(router.isMatch(message));
267 
268         final MuleSession session = (MuleSession)mockSession.proxy();
269         // exception to throw
270         MuleEvent eventToThrow = new DefaultMuleEvent(message, endpoint1, session);
271         MuleException rex = new RoutingException(eventToThrow, endpoint1);
272 
273         mockendpoint1.expectAndThrow("process", RouterTestUtils.getArgListCheckerMuleEvent(), rex);
274         mockendpoint2.expectAndReturn("process", RouterTestUtils.getArgListCheckerMuleEvent(), event);
275         MuleEvent actualResult = router.route(new OutboundRoutingTestEvent(message, session));
276         assertNull("Async call should not return any results.", actualResult);
277 
278         mockendpoint1.verify();
279         mockendpoint2.verify();
280     }
281 
282     /**
283      * The first endpoint contains exception payload in return message, second
284      * succeeds. Events are being sent synchronously.
285      */
286     @Test
287     public void testFirstHadExceptionPayloadSuccessSecondSyncWithExceptionPayload() throws Exception
288     {
289         Mock mockSession = MuleTestUtils.getMockSession();
290         mockSession.matchAndReturn("getFlowConstruct", getTestService());
291 
292         OutboundEndpoint endpoint1 = getTestOutboundEndpoint("TestFailEndpoint",
293             "test://Failure?exchangePattern=request-response");
294         OutboundEndpoint endpoint2 = getTestOutboundEndpoint("TestSuccessEndpoint",
295             "test://Success?exchangePattern=request-response");
296         Mock mockendpoint1 = RouterTestUtils.getMockEndpoint(endpoint1);
297         Mock mockendpoint2 = RouterTestUtils.getMockEndpoint(endpoint2);
298         ExceptionBasedRouter router = new ExceptionBasedRouter();
299         router.setMuleContext(muleContext);
300         router.addRoute((OutboundEndpoint) mockendpoint1.proxy());
301         router.addRoute((OutboundEndpoint) mockendpoint2.proxy());
302 
303         MuleMessage message = new DefaultMuleMessage("test event", muleContext);
304         MuleMessage expectedResultMessage = new DefaultMuleMessage("Return event", muleContext);
305         MuleEvent expectedResultEvent = new OutboundRoutingTestEvent(expectedResultMessage, null);
306 
307 
308         assertTrue(router.isMatch(message));
309 
310         // remote endpoint failed and set an exception payload on the returned
311         // message
312         MuleMessage exPayloadMessage = new DefaultMuleMessage("there was a failure", muleContext);
313         exPayloadMessage.setExceptionPayload(new DefaultExceptionPayload(new RuntimeException()));
314         MuleEvent exPayloadMessageEvent = new OutboundRoutingTestEvent(exPayloadMessage, null);
315 
316 
317         final MuleSession session = (MuleSession)mockSession.proxy();
318         // 1st failure
319         mockendpoint1.expectAndReturn("process", RouterTestUtils.getArgListCheckerMuleEvent(),
320             exPayloadMessageEvent);
321         // next endpoint
322         mockendpoint2.expectAndReturn("process", RouterTestUtils.getArgListCheckerMuleEvent(),
323             expectedResultEvent);
324         MuleEvent actualResult = router.route(new OutboundRoutingTestEvent(message, session));
325         mockendpoint1.verify();
326         mockendpoint2.verify();
327 
328         assertEquals("Got an invalid return message.", expectedResultMessage, actualResult.getMessage());
329     }
330 }