1
2
3
4
5
6
7
8
9
10
11 package org.mule.providers;
12
13 import org.mule.config.ThreadingProfile;
14 import org.mule.transaction.TransactionCallback;
15 import org.mule.transaction.TransactionTemplate;
16 import org.mule.umo.UMOComponent;
17 import org.mule.umo.UMOException;
18 import org.mule.umo.endpoint.UMOEndpoint;
19 import org.mule.umo.lifecycle.InitialisationException;
20 import org.mule.umo.provider.UMOConnector;
21
22 import java.util.Iterator;
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 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
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(UMOConnector connector,
44 UMOComponent component,
45 final UMOEndpoint endpoint) throws InitialisationException
46 {
47 super(connector, component, endpoint);
48 this.setReceiveMessagesInTransaction(endpoint.getTransactionConfig().getFactory() != null);
49 }
50
51
52
53
54
55
56 public TransactedPollingMessageReceiver(UMOConnector connector,
57 UMOComponent component,
58 final UMOEndpoint endpoint,
59 long frequency) throws InitialisationException
60 {
61 this(connector, component, 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
86 public void doStart() throws UMOException
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 public void poll() throws Exception
107 {
108 TransactionTemplate tt = new TransactionTemplate(endpoint.getTransactionConfig(), connector
109 .getExceptionListener());
110
111 if (this.isReceiveMessagesInTransaction())
112 {
113
114
115
116 TransactionCallback cb = new TransactionCallback()
117 {
118 public Object doInTransaction() throws Exception
119 {
120 List messages = getMessages();
121 if (messages != null && messages.size() > 0)
122 {
123 for (Iterator it = messages.iterator(); it.hasNext();)
124 {
125 TransactedPollingMessageReceiver.this.processMessage(it.next());
126 }
127 }
128 return null;
129 }
130 };
131 tt.execute(cb);
132 }
133 else
134 {
135
136 List messages = getMessages();
137 if (messages != null && messages.size() > 0)
138 {
139 final CountDownLatch countdown = new CountDownLatch(messages.size());
140 for (Iterator it = messages.iterator(); it.hasNext();)
141 {
142 try
143 {
144 this.getWorkManager().scheduleWork(
145 new MessageProcessorWorker(tt, countdown, it.next()));
146 }
147 catch (Exception e)
148 {
149 countdown.countDown();
150 throw e;
151 }
152 }
153 countdown.await();
154 }
155 }
156 }
157
158 protected class MessageProcessorWorker implements Work, TransactionCallback
159 {
160 private final TransactionTemplate tt;
161 private final Object message;
162 private final CountDownLatch latch;
163
164 public MessageProcessorWorker(TransactionTemplate tt, CountDownLatch latch, Object message)
165 {
166 this.tt = tt;
167 this.message = message;
168 this.latch = latch;
169 }
170
171 public void release()
172 {
173
174 }
175
176 public void run()
177 {
178 try
179 {
180 tt.execute(this);
181 }
182 catch (Exception e)
183 {
184 handleException(e);
185 }
186 finally
187 {
188 latch.countDown();
189 }
190 }
191
192 public Object doInTransaction() throws Exception
193 {
194 TransactedPollingMessageReceiver.this.processMessage(message);
195 return null;
196 }
197
198 }
199
200 protected abstract List getMessages() throws Exception;
201
202 protected abstract void processMessage(Object message) throws Exception;
203
204 }