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