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