1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport;
12
13 import org.mule.api.MessagingException;
14 import org.mule.api.MuleEvent;
15 import org.mule.api.MuleException;
16 import org.mule.api.MuleMessage;
17 import org.mule.api.config.ThreadingProfile;
18 import org.mule.api.construct.FlowConstruct;
19 import org.mule.api.endpoint.InboundEndpoint;
20 import org.mule.api.lifecycle.CreateException;
21 import org.mule.api.transaction.TransactionCallback;
22 import org.mule.api.transport.Connector;
23 import org.mule.transaction.TransactionTemplate;
24
25 import java.util.List;
26 import java.util.concurrent.CountDownLatch;
27
28 import javax.resource.spi.work.Work;
29
30
31
32
33
34
35 public abstract class TransactedPollingMessageReceiver extends AbstractPollingMessageReceiver
36 {
37
38 private boolean receiveMessagesInTransaction = true;
39
40
41 private boolean useMultipleReceivers = true;
42
43 public TransactedPollingMessageReceiver(Connector connector,
44 FlowConstruct flowConstruct,
45 final InboundEndpoint endpoint) throws CreateException
46 {
47 super(connector, flowConstruct, endpoint);
48 this.setReceiveMessagesInTransaction(endpoint.getTransactionConfig().isTransacted());
49 }
50
51
52
53
54
55
56 @Deprecated
57 public TransactedPollingMessageReceiver(Connector connector,
58 FlowConstruct flowConstruct,
59 final InboundEndpoint endpoint,
60 long frequency) throws CreateException
61 {
62 this(connector, flowConstruct, endpoint);
63 this.setFrequency(frequency);
64 }
65
66 public boolean isReceiveMessagesInTransaction()
67 {
68 return receiveMessagesInTransaction;
69 }
70
71 public void setReceiveMessagesInTransaction(boolean useTx)
72 {
73 receiveMessagesInTransaction = useTx;
74 }
75
76 public boolean isUseMultipleTransactedReceivers()
77 {
78 return useMultipleReceivers;
79 }
80
81 public void setUseMultipleTransactedReceivers(boolean useMultiple)
82 {
83 useMultipleReceivers = useMultiple;
84 }
85
86 @Override
87 public void doStart() throws MuleException
88 {
89
90 this.setUseMultipleTransactedReceivers(connector.isCreateMultipleTransactedReceivers());
91
92 ThreadingProfile tp = connector.getReceiverThreadingProfile();
93 int numReceiversToStart = 1;
94
95 if (this.isReceiveMessagesInTransaction() && this.isUseMultipleTransactedReceivers()
96 && tp.isDoThreading())
97 {
98 numReceiversToStart = connector.getNumberOfConcurrentTransactedReceivers();
99 }
100
101 for (int i = 0; i < numReceiversToStart; i++)
102 {
103 super.doStart();
104 }
105 }
106
107 @Override
108 public void poll() throws Exception
109 {
110 TransactionTemplate<Object> tt = new TransactionTemplate<Object>(endpoint.getTransactionConfig(), connector.getMuleContext());
111
112 if (this.isReceiveMessagesInTransaction())
113 {
114 if (hasNoMessages())
115 {
116 return;
117 }
118
119
120
121 TransactionCallback<Object> cb = new TransactionCallback<Object>()
122 {
123 @Override
124 public Object doInTransaction() throws Exception
125 {
126
127 List messages = getMessages();
128 if (messages != null && messages.size() > 0)
129 {
130 for (Object message : messages)
131 {
132 processMessage(message);
133 }
134 }
135 return null;
136 }
137 };
138 tt.execute(cb);
139 }
140 else
141 {
142
143 List messages = getMessages();
144 if (messages != null && messages.size() > 0)
145 {
146 final CountDownLatch countdown = new CountDownLatch(messages.size());
147 for (Object message : messages)
148 {
149 try
150 {
151 this.getWorkManager().scheduleWork(
152 new MessageProcessorWorker(tt, countdown, message));
153 }
154 catch (Exception e)
155 {
156 countdown.countDown();
157 throw e;
158 }
159 }
160 countdown.await();
161 }
162 }
163 }
164
165
166
167
168 protected boolean hasNoMessages()
169 {
170 return false;
171 }
172
173 protected class MessageProcessorWorker implements Work, TransactionCallback
174 {
175 private final TransactionTemplate tt;
176 private final Object message;
177 private final CountDownLatch latch;
178
179 public MessageProcessorWorker(TransactionTemplate tt, CountDownLatch latch, Object message)
180 {
181 this.tt = tt;
182 this.message = message;
183 this.latch = latch;
184 }
185
186 @Override
187 public void release()
188 {
189
190 }
191
192 @Override
193 public void run()
194 {
195 try
196 {
197 tt.execute(this);
198 }
199 catch (MessagingException e)
200 {
201 MuleEvent event = e.getEvent();
202 event.getFlowConstruct().getExceptionListener().handleException(e, event);
203 }
204 catch (Exception e)
205 {
206 connector.getMuleContext().getExceptionListener().handleException(e);
207 }
208 finally
209 {
210 latch.countDown();
211 }
212 }
213
214 @Override
215 public Object doInTransaction() throws Exception
216 {
217 processMessage(message);
218 return null;
219 }
220
221 }
222
223 protected abstract List<MuleMessage> getMessages() throws Exception;
224
225 protected abstract void processMessage(Object message) throws Exception;
226
227 }