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.test.integration.exceptions;
8   
9   import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
10  import org.hamcrest.core.IsNull;
11  import org.junit.Rule;
12  import org.junit.Test;
13  import org.junit.runners.Parameterized;
14  import org.mule.api.MuleEvent;
15  import org.mule.api.MuleEventContext;
16  import org.mule.api.MuleException;
17  import org.mule.api.MuleMessage;
18  import org.mule.api.client.LocalMuleClient;
19  import org.mule.api.lifecycle.Stoppable;
20  import org.mule.api.processor.MessageProcessor;
21  import org.mule.exception.AbstractMessagingExceptionStrategy;
22  import org.mule.message.ExceptionMessage;
23  import org.mule.tck.AbstractServiceAndFlowTestCase;
24  import org.mule.tck.functional.EventCallback;
25  import org.mule.tck.functional.FunctionalTestComponent;
26  import org.mule.tck.junit4.rule.DynamicPort;
27  import org.mule.transport.NullPayload;
28  import org.mule.transport.email.FixedPortGreenMailSupport;
29  import org.mule.transport.email.functional.AbstractEmailFunctionalTestCase;
30  import org.mule.util.concurrent.Latch;
31  
32  import javax.mail.internet.MimeMessage;
33  import java.util.ArrayList;
34  import java.util.Arrays;
35  import java.util.Collection;
36  import java.util.List;
37  import java.util.concurrent.CountDownLatch;
38  
39  import static org.hamcrest.core.Is.is;
40  import static org.hamcrest.core.IsInstanceOf.instanceOf;
41  import static org.junit.Assert.*;
42  
43  public class ExceptionStrategyCommonScenariosTestCase extends AbstractServiceAndFlowTestCase
44  {
45  
46      public static final String MESSAGE_TO_SEND = "A message";
47      public static final String MESSAGE_MODIFIED = "A message with some text added";
48      public static final int TIMEOUT = 5000;
49      private final static Latch endMessageProcessorExecuted = new Latch();
50      @Rule
51      public DynamicPort dynamicPort1 = new DynamicPort("port1");
52  
53      @Rule
54      public DynamicPort dynamicPort2 = new DynamicPort("port2");
55  
56      @Rule
57      public DynamicPort dynamicPort3 = new DynamicPort("port3");
58  
59      @Rule
60      public DynamicPort dynamicPort4 = new DynamicPort("port4");
61  
62      @Rule
63      public DynamicPort dynamicPort5 = new DynamicPort("port5");
64  
65      @Rule
66      public DynamicPort dynamicPort6 = new DynamicPort("port6");
67  
68      public ExceptionStrategyCommonScenariosTestCase(AbstractServiceAndFlowTestCase.ConfigVariant variant, String configResources)
69      {
70          super(variant, configResources);
71      }
72  
73      @Parameterized.Parameters
74      public static Collection<Object[]> parameters()
75      {
76          return Arrays.asList(new Object[][]{{AbstractServiceAndFlowTestCase.ConfigVariant.SERVICE, "org/mule/test/integration/exceptions/exception-strategy-common-scenarios-service.xml"},
77                  {AbstractServiceAndFlowTestCase.ConfigVariant.FLOW, "org/mule/test/integration/exceptions/exception-strategy-common-scenarios-flow.xml"}});
78      }
79  
80      @Test
81      public void testRoutePayloadBeforeException() throws Exception
82      {
83          final Latch messageProcessedLatch = new Latch();
84          FunctionalTestComponent ftc = getFunctionalTestComponent("LastMessageStateRouting");
85          ftc.setEventCallback(new EventCallback()
86          {
87              public void eventReceived(MuleEventContext context, Object component) throws Exception
88              {
89                  messageProcessedLatch.release();
90                  throw new RuntimeException();
91              }
92          });
93          LocalMuleClient client = muleContext.getClient();
94          client.dispatch("jms://in1?connector=jmsConnector", MESSAGE_TO_SEND, null);
95          if (!messageProcessedLatch.await(TIMEOUT, TimeUnit.MILLISECONDS))
96          {
97              fail("Message never received by mule");
98          }
99          MuleMessage response = client.request("jms://dead.letter1?connector=jmsConnector", TIMEOUT);
100         assertThat(response, IsNull.<Object>notNullValue());
101         assertThat(response.getPayloadAsString(), is(MESSAGE_MODIFIED));
102     }
103 
104     @Test
105     public void testRouteOriginalPayload() throws Exception
106     {
107         final Latch messageProcessedLatch = new Latch();
108         FunctionalTestComponent ftc = getFunctionalTestComponent("OriginalMessageRouting");
109         ftc.setEventCallback(new EventCallback()
110         {
111             public void eventReceived(MuleEventContext context, Object component) throws Exception
112             {
113                 messageProcessedLatch.release();
114                 throw new RuntimeException();
115             }
116         });
117         LocalMuleClient client = muleContext.getClient();
118         client.dispatch("jms://in2?connector=jmsConnector", MESSAGE_TO_SEND, null);
119         if (!messageProcessedLatch.await(TIMEOUT, TimeUnit.MILLISECONDS))
120         {
121             fail("Message never received by mule");
122         }
123         MuleMessage response = client.request("jms://dead.letter2?connector=jmsConnector", TIMEOUT);
124         assertThat(response, IsNull.<Object>notNullValue());
125         assertThat(response.getPayloadAsString(), is(MESSAGE_TO_SEND));
126     }
127 
128     @Test
129     public void testRouteByExceptionType() throws Exception
130     {
131         final CountDownLatch messageProcessedLatch = new CountDownLatch(3);
132         FunctionalTestComponent ftc = getFunctionalTestComponent("RouteByExceptionType");
133         ftc.setEventCallback(new EventCallback()
134         {
135             public void eventReceived(MuleEventContext context, Object component) throws Exception
136             {
137                 messageProcessedLatch.countDown();
138                 throw new RuntimeException();
139             }
140         });
141         LocalMuleClient client = muleContext.getClient();
142         client.dispatch("jms://in3?connector=jmsConnector", MESSAGE_TO_SEND, null);
143         if (!messageProcessedLatch.await(TIMEOUT, java.util.concurrent.TimeUnit.MILLISECONDS))
144         {
145             fail("Message never received by mule");
146         }
147         MuleMessage response = client.request("jms://dead.letter3?connector=jmsConnector", TIMEOUT);
148         assertThat(response, IsNull.<Object>notNullValue());
149         assertThat(response.getPayloadAsString(), is(MESSAGE_TO_SEND));
150         assertThat(client.request("jms://exceptions?connector=jmsConnector", TIMEOUT), IsNull.<Object>notNullValue());
151         assertThat(client.request("jms://exceptions?connector=jmsConnector", TIMEOUT), IsNull.notNullValue());
152         MuleMessage exceptionResponse = client.request("jms://exceptions?connector=jmsConnector", TIMEOUT);
153         assertThat(exceptionResponse, IsNull.<Object>notNullValue());
154         assertThat(exceptionResponse.getPayload(), instanceOf(ExceptionMessage.class));
155     }
156 
157     @Test
158     public void testPreservePayloadExceptionStrategy() throws Exception
159     {
160         LocalMuleClient client = muleContext.getClient();
161         MuleMessage response = client.send("vm://in4", MESSAGE_TO_SEND, null, TIMEOUT);
162         assertThat(response, IsNull.<Object>notNullValue());
163         assertThat(response.getPayloadAsString(), is(MESSAGE_MODIFIED));
164     }
165 
166 
167     @Test(expected = org.mule.api.transport.NoReceiverForEndpointException.class)
168     public void testStopFlowBasedOnExceptionType() throws Throwable
169     {
170         LocalMuleClient client = muleContext.getClient();
171         MuleMessage response = client.send("vm://in5", MESSAGE_TO_SEND, null, TIMEOUT);
172         assertThat((NullPayload) response.getPayload(), is(NullPayload.getInstance()));
173         assertThat(response.getExceptionPayload(), IsNull.<Object>notNullValue());
174         try
175         {
176             client.send("vm://in5", MESSAGE_TO_SEND, null, TIMEOUT);
177         }
178         catch (Exception e)
179         {
180             throw e.getCause();
181         }
182     }
183 
184     @Test
185     public void testRollbackTransactionAndSendAnEmail() throws Exception
186     {
187         if (variant.equals(ConfigVariant.SERVICE))
188         {
189             //((Lifecycle)getFlowConstruct("RollbackTransactionAndSendEmail")).stop(); is not working as expected
190             return;
191         }
192         FixedPortGreenMailSupport greenMailSupport = new FixedPortGreenMailSupport(dynamicPort2.getNumber());
193 
194         List<Integer> ports = new ArrayList<Integer>(6);
195         ports.add(dynamicPort1.getNumber());
196         ports.add(dynamicPort2.getNumber());
197         ports.add(dynamicPort3.getNumber());
198         ports.add(dynamicPort4.getNumber());
199         ports.add(dynamicPort5.getNumber());
200         ports.add(dynamicPort6.getNumber());
201 
202         greenMailSupport.startServers(ports);
203         LocalMuleClient client = muleContext.getClient();
204         client.dispatch("jms://in6?connector=jmsConnectorNoRedelivery", MESSAGE_TO_SEND, null);
205         endMessageProcessorExecuted.await(TIMEOUT, TimeUnit.MILLISECONDS);
206         MuleMessage response = client.request("jms://in6?connector=jmsConnectorNoRedelivery", TIMEOUT);
207         assertThat(response, IsNull.<Object>notNullValue());
208         assertThat(response.getPayloadAsString(), is(MESSAGE_TO_SEND));
209         greenMailSupport.getServers().waitForIncomingEmail(AbstractEmailFunctionalTestCase.DELIVERY_DELAY_MS, 1);
210         MimeMessage[] messages = greenMailSupport.getServers().getReceivedMessages();
211         assertNotNull("did not receive any messages", messages);
212         assertEquals("did not receive 1 mail", 1, messages.length);
213     }
214 
215     public static class EndMessageProcessor implements MessageProcessor
216     {
217 
218         public MuleEvent process(MuleEvent event) throws MuleException
219         {
220             endMessageProcessorExecuted.release();
221             if (event.getFlowConstruct() instanceof Stoppable)
222             {
223                 ((Stoppable)event.getFlowConstruct()).stop();
224             }
225             return event;
226         }
227     }
228 
229     public static class PreservePayloadExceptionStrategy extends AbstractMessagingExceptionStrategy
230     {
231         @Override
232         public MuleEvent handleException(Exception e, MuleEvent event)
233         {
234             Object payloadBeforeException = event.getMessage().getPayload();
235             MuleEvent resultEvent = super.handleException(e, event);
236             resultEvent.getMessage().setPayload(payloadBeforeException);
237             return resultEvent;
238         }
239     }
240 }