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