1
2
3
4
5
6
7 package org.mule.transport.jms;
8
9 import org.mule.api.MuleException;
10 import org.mule.api.MuleMessage;
11 import org.mule.api.construct.FlowConstruct;
12 import org.mule.api.endpoint.InboundEndpoint;
13 import org.mule.api.lifecycle.CreateException;
14 import org.mule.api.lifecycle.StartException;
15 import org.mule.api.lifecycle.StopException;
16 import org.mule.api.transaction.Transaction;
17 import org.mule.api.transaction.TransactionCallback;
18 import org.mule.api.transport.Connector;
19 import org.mule.api.transport.MessageReceiver;
20 import org.mule.transaction.TransactionCoordination;
21 import org.mule.transaction.TransactionTemplate;
22 import org.mule.transport.AbstractMessageReceiver;
23 import org.mule.transport.ConnectException;
24 import org.mule.transport.jms.filters.JmsSelectorFilter;
25 import org.mule.transport.jms.redelivery.RedeliveryHandler;
26 import org.mule.util.ClassUtils;
27
28 import javax.jms.Destination;
29 import javax.jms.JMSException;
30 import javax.jms.Message;
31 import javax.jms.MessageConsumer;
32 import javax.jms.MessageListener;
33 import javax.jms.Session;
34 import javax.jms.Topic;
35 import javax.resource.spi.work.Work;
36
37 public class TransactedSingleResourceJmsMessageReceiver extends AbstractMessageReceiver
38 implements MessageListener
39 {
40 protected JmsConnector connector;
41 protected RedeliveryHandler redeliveryHandler;
42 protected MessageConsumer consumer;
43 protected Session session;
44 protected boolean startOnConnect = false;
45
46
47 protected boolean receiveMessagesInTransaction = true;
48
49
50 protected boolean useMultipleReceivers = true;
51
52
53 public TransactedSingleResourceJmsMessageReceiver(Connector connector,
54 FlowConstruct flowConstruct,
55 InboundEndpoint endpoint) throws CreateException
56 {
57
58 super(connector, flowConstruct, endpoint);
59
60 this.connector = (JmsConnector) connector;
61
62
63
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 @Override
77 protected void doDispose()
78 {
79
80 }
81
82 @Override
83 protected void doConnect() throws Exception
84 {
85 try
86 {
87 JmsSupport jmsSupport = this.connector.getJmsSupport();
88
89 if (session == null)
90 {
91 session = this.connector.getSession(endpoint);
92 }
93
94
95 boolean topic = connector.getTopicResolver().isTopic(endpoint);
96
97 Destination dest = jmsSupport.createDestination(session, endpoint);
98
99 String selector = null;
100 if (endpoint.getFilter() != null && endpoint.getFilter() instanceof JmsSelectorFilter)
101 {
102 selector = ((JmsSelectorFilter) endpoint.getFilter()).getExpression();
103 }
104 else if (endpoint.getProperties() != null)
105 {
106
107
108 selector = (String) endpoint.getProperties().get(JmsConstants.JMS_SELECTOR_PROPERTY);
109 }
110 String tempDurable = (String) endpoint.getProperties().get(JmsConstants.DURABLE_PROPERTY);
111 boolean durable = connector.isDurable();
112 if (tempDurable != null)
113 {
114 durable = Boolean.valueOf(tempDurable).booleanValue();
115 }
116
117
118 String durableName = (String) endpoint.getProperties().get(JmsConstants.DURABLE_NAME_PROPERTY);
119 if (durableName == null && durable && dest instanceof Topic)
120 {
121 durableName = "mule." + connector.getName() + "." + endpoint.getEndpointURI().getAddress();
122 logger.debug("Jms Connector for this receiver is durable but no durable name has been specified. Defaulting to: "
123 + durableName);
124 }
125
126
127 consumer = jmsSupport.createConsumer(session, dest, selector, connector.isNoLocal(), durableName,
128 topic, endpoint);
129 }
130 catch (JMSException e)
131 {
132 throw new ConnectException(e, this);
133 }
134 }
135
136 @Override
137 protected void doStart() throws MuleException
138 {
139 try
140 {
141
142
143
144
145 if (consumer == null)
146 {
147 startOnConnect = true;
148 }
149 else
150 {
151 startOnConnect = false;
152 this.consumer.setMessageListener(this);
153 }
154 }
155 catch (JMSException e)
156 {
157 throw new StartException(e, this);
158 }
159 }
160
161 @Override
162 protected void doStop() throws MuleException
163 {
164 try
165 {
166 if (consumer != null)
167 {
168 consumer.setMessageListener(null);
169 }
170 }
171 catch (JMSException e)
172 {
173 throw new StopException(e, this);
174 }
175 }
176
177 @Override
178 public void doDisconnect() throws Exception
179 {
180 closeConsumer();
181 }
182
183 protected void closeConsumer()
184 {
185 connector.closeQuietly(consumer);
186 consumer = null;
187 connector.closeQuietly(session);
188 session = null;
189 }
190
191 public void onMessage(Message message)
192 {
193 try
194 {
195 getWorkManager().scheduleWork(new MessageReceiverWorker(message, this));
196 }
197 catch (Exception e)
198 {
199 getConnector().getMuleContext().getExceptionListener().handleException(e);
200 }
201 }
202
203 protected class MessageReceiverWorker implements Work
204 {
205 Message message;
206 MessageReceiver receiver;
207
208 public MessageReceiverWorker(Message message, MessageReceiver receiver)
209 {
210 this.message = message;
211 this.receiver = receiver;
212 }
213
214 public void run()
215 {
216 try
217 {
218 TransactionTemplate<Void> tt = new TransactionTemplate<Void>(
219 endpoint.getTransactionConfig(),
220 connector.getMuleContext());
221
222 final String encoding = endpoint.getEncoding();
223
224 if (receiveMessagesInTransaction)
225 {
226 TransactionCallback<Void> cb = new MessageTransactionCallback<Void>(message)
227 {
228
229 public Void doInTransaction() throws Exception
230 {
231
232 Transaction tx = TransactionCoordination.getInstance().getTransaction();
233 if (tx != null)
234 {
235 tx.bindResource(connector.getConnection(), ReusableSessionWrapperFactory.createWrapper(session));
236 }
237 if (tx instanceof JmsClientAcknowledgeTransaction)
238 {
239 tx.bindResource(message, message);
240 }
241
242 if (logger.isDebugEnabled())
243 {
244 logger.debug("Message received it is of type: " +
245 ClassUtils.getSimpleName(message.getClass()));
246 if (message.getJMSDestination() != null)
247 {
248 logger.debug("Message received on " + message.getJMSDestination() + " ("
249 + message.getJMSDestination().getClass().getName() + ")");
250 }
251 else
252 {
253 logger.debug("Message received on unknown destination");
254 }
255 logger.debug("Message CorrelationId is: " + message.getJMSCorrelationID());
256 logger.debug("Jms Message Id is: " + message.getJMSMessageID());
257 }
258
259 if (message.getJMSRedelivered())
260 {
261 if (logger.isDebugEnabled())
262 {
263 logger.debug("Message with correlationId: "
264 + message.getJMSCorrelationID()
265 + " is redelivered. handing off to Exception Handler");
266 }
267 redeliveryHandler.handleRedelivery(message, receiver.getEndpoint(), receiver.getFlowConstruct());
268 }
269
270 MuleMessage messageToRoute = createMuleMessage(message, encoding);
271 routeMessage(messageToRoute);
272 return null;
273 }
274 };
275 tt.execute(cb);
276 }
277 else
278 {
279 MuleMessage messageToRoute = createMuleMessage(message, encoding);
280 routeMessage(messageToRoute);
281 }
282 }
283 catch (Exception e)
284 {
285 getConnector().getMuleContext().getExceptionListener().handleException(e);
286 }
287 }
288
289 public void release()
290 {
291
292 }
293 }
294 }