View Javadoc

1   /*
2    * $Id: JmsMessageReceiver.java 23075 2011-10-03 21:51:50Z pablo.lagreca $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.transport.jms;
12  
13  import org.mule.MessageExchangePattern;
14  import org.mule.api.MuleException;
15  import org.mule.api.MuleMessage;
16  import org.mule.api.MuleRuntimeException;
17  import org.mule.api.construct.FlowConstruct;
18  import org.mule.api.endpoint.InboundEndpoint;
19  import org.mule.api.lifecycle.CreateException;
20  import org.mule.api.lifecycle.LifecycleException;
21  import org.mule.api.transaction.Transaction;
22  import org.mule.api.transaction.TransactionException;
23  import org.mule.api.transport.Connector;
24  import org.mule.api.transport.ReplyToHandler;
25  import org.mule.transport.AbstractMessageReceiver;
26  import org.mule.transport.AbstractReceiverWorker;
27  import org.mule.transport.ConnectException;
28  import org.mule.transport.jms.filters.JmsSelectorFilter;
29  import org.mule.transport.jms.redelivery.RedeliveryHandler;
30  import org.mule.util.ClassUtils;
31  
32  import java.util.ArrayList;
33  import java.util.List;
34  
35  import javax.jms.Destination;
36  import javax.jms.JMSException;
37  import javax.jms.Message;
38  import javax.jms.MessageConsumer;
39  import javax.jms.MessageListener;
40  import javax.jms.Session;
41  import javax.jms.Topic;
42  import javax.resource.spi.work.WorkException;
43  
44  /**
45   * Registers a single JmsMessage listener but uses a thread pool to process incoming
46   * messages.
47   * @deprecated use {@link org.mule.transport.jms.MultiConsumerJmsMessageReceiver} (set by default).
48   */
49  @Deprecated
50  public class JmsMessageReceiver extends AbstractMessageReceiver implements MessageListener
51  {
52  
53      protected JmsConnector connector;
54      protected RedeliveryHandler redeliveryHandler;
55      protected MessageConsumer consumer;
56      protected Session session;
57      protected boolean startOnConnect = false;
58  
59      public JmsMessageReceiver(Connector connector, FlowConstruct flowConstruct, InboundEndpoint endpoint)
60              throws CreateException
61      {
62          super(connector, flowConstruct, endpoint);
63          this.connector = (JmsConnector) connector;
64  
65          try
66          {
67              redeliveryHandler = this.connector.getRedeliveryHandlerFactory().create();
68              redeliveryHandler.setConnector(this.connector);
69          }
70          catch (Exception e)
71          {
72              throw new CreateException(e, this);
73          }
74      }
75  
76      protected void doConnect() throws Exception
77      {
78          createConsumer();
79          if (startOnConnect)
80          {
81              doStart();
82          }
83      }
84  
85      protected void doDisconnect() throws Exception
86      {
87          closeConsumer();
88      }
89  
90      public void onMessage(Message message)
91      {
92          try
93          {
94              getWorkManager().scheduleWork(new JmsWorker(message, this));
95          }
96          catch (WorkException e)
97          {
98              throw new MuleRuntimeException(e);
99          }
100     }
101 
102     protected  class JmsWorker extends AbstractReceiverWorker
103     {
104         public JmsWorker(Message message, AbstractMessageReceiver receiver)
105         {
106             super(new ArrayList(1), receiver);
107             messages.add(message);
108         }
109 
110         public JmsWorker(List messages, AbstractMessageReceiver receiver)
111         {
112             super(messages, receiver);
113         }
114 
115         @Override
116         protected Object preProcessMessage(Object message) throws Exception
117         {
118             Message m = (Message) message;
119 
120             if (logger.isDebugEnabled())
121             {
122                 logger.debug("Message received it is of type: " +
123                         ClassUtils.getSimpleName(message.getClass()));
124                 if (m.getJMSDestination() != null)
125                 {
126                     logger.debug("Message received on " + m.getJMSDestination() + " ("
127                             + m.getJMSDestination().getClass().getName() + ")");
128                 }
129                 else
130                 {
131                     logger.debug("Message received on unknown destination");
132                 }
133                 logger.debug("Message CorrelationId is: " + m.getJMSCorrelationID());
134                 logger.debug("Jms Message Id is: " + m.getJMSMessageID());
135             }
136 
137             if (m.getJMSRedelivered() && redeliveryHandler != null)
138             {
139                 if (logger.isDebugEnabled())
140                 {
141                     logger.debug("Message with correlationId: " + m.getJMSCorrelationID()
142                             + " has redelivered flag set, handing off to Exception Handler");
143                 }
144                 redeliveryHandler.handleRedelivery(m, receiver.getEndpoint(), receiver.getFlowConstruct());
145             }
146             return m;
147 
148         }
149 
150         protected void bindTransaction(Transaction tx) throws TransactionException
151         {
152             if(tx instanceof JmsTransaction)
153             {
154                 tx.bindResource(connector.getConnection(), ReusableSessionWrapperFactory.createWrapper(session));
155             }
156             else if(tx instanceof JmsClientAcknowledgeTransaction)
157             {
158                 //We should still bind the session to the transaction, but we also need the message itself
159                 //since that is the object that gets Acknowledged
160 
161                 tx.bindResource(connector.getConnection(), ReusableSessionWrapperFactory.createWrapper(session));
162                 ((JmsClientAcknowledgeTransaction)tx).setMessage((Message)messages.get(0));
163             }
164         }
165     }
166 
167     protected void doStart() throws MuleException
168     {
169         try
170         {
171             // We ned to register the listener when start is called in order to only
172             // start receiving messages after
173             // start/
174             // If the consumer is null it means that the connection strategy is being
175             // run in a separate thread
176             // And hasn't managed to connect yet.
177             if (consumer == null)
178             {
179                 startOnConnect = true;
180             }
181             else
182             {
183                 startOnConnect = false;
184                 consumer.setMessageListener(this);
185             }
186         }
187         catch (JMSException e)
188         {
189             throw new LifecycleException(e, this);
190         }
191     }
192 
193     protected void doStop() throws MuleException
194     {
195         try
196         {
197             if (consumer != null)
198             {
199                 consumer.setMessageListener(null);
200             }
201         }
202         catch (JMSException e)
203         {
204             throw new LifecycleException(e, this);
205         }
206     }
207 
208     protected void doDispose()
209     {
210         // template method
211     }
212 
213     protected void closeConsumer()
214     {
215         connector.closeQuietly(consumer);
216         consumer = null;
217         connector.closeQuietly(session);
218         session = null;
219     }
220 
221     /**
222      * Create a consumer for the jms destination
223      *
224      * @throws Exception
225      */
226     protected void createConsumer() throws Exception
227     {
228         try
229         {
230             JmsSupport jmsSupport = this.connector.getJmsSupport();
231             // Create session if none exists
232             if (session == null)
233             {
234                 session = this.connector.getSession(endpoint);
235             }
236 
237             boolean topic = connector.getTopicResolver().isTopic(endpoint);
238 
239             // Create destination
240             Destination dest = jmsSupport.createDestination(session, endpoint);
241 
242             // Extract jms selector
243             String selector = null;
244             JmsSelectorFilter selectorFilter = connector.getSelector(endpoint);
245             if (selectorFilter != null)
246             {
247                 selector = selectorFilter.getExpression();
248             }
249             else if (endpoint.getProperties() != null)
250             {
251                 // still allow the selector to be set as a property on the endpoint
252                 // to be backward compatable
253                 selector = (String) endpoint.getProperties().get(JmsConstants.JMS_SELECTOR_PROPERTY);
254             }
255             String tempDurable = (String) endpoint.getProperties().get(JmsConstants.DURABLE_PROPERTY);
256             boolean durable = connector.isDurable();
257             if (tempDurable != null)
258             {
259                 durable = Boolean.valueOf(tempDurable).booleanValue();
260             }
261 
262             // Get the durable subscriber name if there is one
263             String durableName = (String) endpoint.getProperties().get(JmsConstants.DURABLE_NAME_PROPERTY);
264             if (durableName == null && durable && dest instanceof Topic)
265             {
266                 durableName = "mule." + connector.getName() + "." + endpoint.getEndpointURI().getAddress();
267                 logger.debug("Jms Connector for this receiver is durable but no durable name has been specified. Defaulting to: "
268                         + durableName);
269             }
270 
271             // Create consumer
272             consumer = jmsSupport.createConsumer(session, dest, selector, connector.isNoLocal(), durableName,
273                     topic, endpoint);
274         }
275         catch (JMSException e)
276         {
277             throw new ConnectException(e, this);
278         }
279     }
280 
281 }