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.transaction.TransactionCoordination;
24 import org.mule.transaction.TransactionTemplate;
25 import org.mule.transport.AbstractMessageReceiver;
26 import org.mule.transport.ConnectException;
27 import org.mule.transport.jms.filters.JmsSelectorFilter;
28 import org.mule.util.ClassUtils;
29
30 import javax.jms.Destination;
31 import javax.jms.JMSException;
32 import javax.jms.Message;
33 import javax.jms.MessageConsumer;
34 import javax.jms.MessageListener;
35 import javax.jms.Session;
36 import javax.jms.Topic;
37 import javax.resource.spi.work.Work;
38
39 public class TransactedSingleResourceJmsMessageReceiver extends AbstractMessageReceiver
40 implements MessageListener
41 {
42 protected JmsConnector connector;
43 protected RedeliveryHandler redeliveryHandler;
44 protected MessageConsumer consumer;
45 protected Session session;
46 protected boolean startOnConnect = false;
47
48
49 protected boolean receiveMessagesInTransaction = true;
50
51
52 protected boolean useMultipleReceivers = true;
53
54
55 public TransactedSingleResourceJmsMessageReceiver(Connector connector,
56 FlowConstruct flowConstruct,
57 InboundEndpoint endpoint) throws CreateException
58 {
59
60 super(connector, flowConstruct, endpoint);
61
62 this.connector = (JmsConnector) connector;
63
64
65
66
67 try
68 {
69 redeliveryHandler = this.connector.getRedeliveryHandlerFactory().create();
70 redeliveryHandler.setConnector(this.connector);
71 }
72 catch (Exception e)
73 {
74 throw new CreateException(e, this);
75 }
76 }
77
78 @Override
79 protected void doDispose()
80 {
81
82 }
83
84 @Override
85 protected void doConnect() throws Exception
86 {
87 try
88 {
89 JmsSupport jmsSupport = this.connector.getJmsSupport();
90
91 if (session == null)
92 {
93 session = this.connector.getSession(endpoint);
94 }
95
96
97 boolean topic = connector.getTopicResolver().isTopic(endpoint);
98
99 Destination dest = jmsSupport.createDestination(session, endpoint);
100
101 String selector = null;
102 if (endpoint.getFilter() != null && endpoint.getFilter() instanceof JmsSelectorFilter)
103 {
104 selector = ((JmsSelectorFilter) endpoint.getFilter()).getExpression();
105 }
106 else if (endpoint.getProperties() != null)
107 {
108
109
110 selector = (String) endpoint.getProperties().get(JmsConstants.JMS_SELECTOR_PROPERTY);
111 }
112 String tempDurable = (String) endpoint.getProperties().get(JmsConstants.DURABLE_PROPERTY);
113 boolean durable = connector.isDurable();
114 if (tempDurable != null)
115 {
116 durable = Boolean.valueOf(tempDurable).booleanValue();
117 }
118
119
120 String durableName = (String) endpoint.getProperties().get(JmsConstants.DURABLE_NAME_PROPERTY);
121 if (durableName == null && durable && dest instanceof Topic)
122 {
123 durableName = "mule." + connector.getName() + "." + endpoint.getEndpointURI().getAddress();
124 logger.debug("Jms Connector for this receiver is durable but no durable name has been specified. Defaulting to: "
125 + durableName);
126 }
127
128
129 consumer = jmsSupport.createConsumer(session, dest, selector, connector.isNoLocal(), durableName,
130 topic, endpoint);
131 }
132 catch (JMSException e)
133 {
134 throw new ConnectException(e, this);
135 }
136 }
137
138 @Override
139 protected void doStart() throws MuleException
140 {
141 try
142 {
143
144
145
146
147 if (consumer == null)
148 {
149 startOnConnect = true;
150 }
151 else
152 {
153 startOnConnect = false;
154 this.consumer.setMessageListener(this);
155 }
156 }
157 catch (JMSException e)
158 {
159 throw new StartException(e, this);
160 }
161 }
162
163 @Override
164 protected void doStop() throws MuleException
165 {
166 try
167 {
168 if (consumer != null)
169 {
170 consumer.setMessageListener(null);
171 }
172 }
173 catch (JMSException e)
174 {
175 throw new StopException(e, this);
176 }
177 }
178
179 @Override
180 public void doDisconnect() throws Exception
181 {
182 closeConsumer();
183 }
184
185 protected void closeConsumer()
186 {
187 connector.closeQuietly(consumer);
188 consumer = null;
189 connector.closeQuietly(session);
190 session = null;
191 }
192
193 public void onMessage(Message message)
194 {
195 try
196 {
197 getWorkManager().scheduleWork(new MessageReceiverWorker(message));
198 }
199 catch (Exception e)
200 {
201 getConnector().getMuleContext().getExceptionListener().handleException(e);
202 }
203 }
204
205 protected class MessageReceiverWorker implements Work
206 {
207 Message message;
208
209 public MessageReceiverWorker(Message message)
210 {
211 this.message = message;
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(), 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);
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 }