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