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