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.transport.jms.integration;
8   
9   import org.mule.api.config.MuleProperties;
10  import org.mule.message.ExceptionMessage;
11  import org.mule.util.SerializationUtils;
12  
13  import javax.jms.BytesMessage;
14  import javax.jms.JMSException;
15  import javax.jms.Message;
16  import javax.jms.MessageConsumer;
17  import javax.jms.ObjectMessage;
18  import javax.jms.Session;
19  import javax.jms.TextMessage;
20  
21  import org.junit.Test;
22  
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertNotNull;
25  import static org.junit.Assert.assertNull;
26  import static org.junit.Assert.assertTrue;
27  import static org.junit.Assert.fail;
28  
29  /**
30   * Tests a transactional exception strategy.
31   */
32  public class JmsDeadLetterQueueTestCase extends AbstractJmsFunctionalTestCase
33  {
34      public static final String DEADLETTER_QUEUE_NAME = "dlq";
35  
36      protected String getConfigResources()
37      {
38          return "integration/jms-dead-letter-queue.xml";
39      }
40  
41      @Test
42      public void testTransactedRedeliveryToDLDestination() throws Exception
43      {
44          send(scenarioDeadLetter);
45          // Verify outbound message did _not_ get delivered.
46          receive(scenarioNotReceive);
47          // Verify message got sent to dead letter queue instead.
48          receive(scenarioDeadLetter);
49      }
50  
51      @Test
52      public void testTransactedRedeliveryToDLDestinationRollback() throws Exception
53      {
54          send(scenarioDeadLetter);
55          // Receive message but roll back transaction.
56          receive(scenarioDeadLetterRollback);
57          // Receive message again and commit transaction.
58          receive(scenarioDeadLetter);
59          // Verify there is no more message to receive.
60          receive(scenarioDeadLetterNotReceive);
61      }
62  
63      Scenario scenarioDeadLetter = new ScenarioDeadLetter();
64  
65      class ScenarioDeadLetter extends ScenarioCommit
66      {
67          // @Override
68          public String getOutputDestinationName()
69          {
70              return DEADLETTER_QUEUE_NAME;
71          }
72  
73          // @Override
74          public Message receive(Session session, MessageConsumer consumer) throws JMSException
75          {
76              // Verify message got sent to dead letter queue.
77              Message message = consumer.receive(getTimeout());
78              assertNotNull(message);
79  
80              Object obj = null;
81              // ExceptionMessage got serialized by JMS provider
82              if (message instanceof BytesMessage)
83              {
84                  byte[] messageBytes = new byte[(int) ((BytesMessage) message).getBodyLength()];
85                  ((BytesMessage) message).readBytes(messageBytes);
86                  obj = SerializationUtils.deserialize(messageBytes, muleContext);
87              }
88              // ExceptionMessage did not get serialized by JMS provider
89              else if (message instanceof ObjectMessage)
90              {
91                  obj = ((ObjectMessage) message).getObject();
92              }
93              else
94              {
95                  fail("Message is an unexpected type: " + message.getClass().getName());
96              }
97              assertTrue(obj instanceof ExceptionMessage);
98  
99              // The payload should be the original message, not the reply message
100             // since the FTC threw an exception.
101 
102             Object payload = ((ExceptionMessage) obj).getPayload();
103             // Original JMS message was serializable
104             if (payload instanceof TextMessage)
105             {
106                 assertEquals(DEFAULT_INPUT_MESSAGE, ((TextMessage) payload).getText());
107             }
108             // Original JMS message was not serializable and toString() was called instead
109             // (see AbstractExceptionListener.routeException() )
110             else if (payload instanceof String)
111             {
112                 assertEquals(DEFAULT_INPUT_MESSAGE, payload);
113             }
114             else
115             {
116                 fail("Payload is an unexpected type: " + payload.getClass().getName());
117             }
118 
119             String dest = message.getStringProperty(MuleProperties.MULE_ENDPOINT_PROPERTY);
120             // Some JMS providers do not allow custom properties to be set on JMS messages
121             if (dest != null)
122             {
123                 assertEquals("jms://" + DEADLETTER_QUEUE_NAME, dest);
124             }
125 
126             applyTransaction(session);
127             return message;
128         }
129     }
130 
131     Scenario scenarioDeadLetterRollback = new ScenarioDeadLetterRollback();
132 
133     class ScenarioDeadLetterRollback extends ScenarioDeadLetter
134     {
135         // @Override
136         protected void applyTransaction(Session session) throws JMSException
137         {
138             session.rollback();
139         }
140     }
141 
142     Scenario scenarioDeadLetterNotReceive = new ScenarioDeadLetterNotReceive();
143 
144     class ScenarioDeadLetterNotReceive extends ScenarioDeadLetter
145     {
146         // @Override
147         public Message receive(Session session, MessageConsumer consumer) throws JMSException
148         {
149             Message message = consumer.receive(getSmallTimeout());
150             assertNull(message);
151             return message;
152         }
153     }
154 }