1
2
3
4
5
6
7
8
9
10
11 package org.mule.tck;
12
13 import org.mule.api.transaction.TransactionCallback;
14 import org.mule.api.transaction.TransactionConfig;
15 import org.mule.api.transaction.TransactionManagerFactory;
16 import org.mule.transaction.MuleTransactionConfig;
17 import org.mule.transaction.TransactionTemplate;
18 import org.mule.transaction.XaTransaction;
19 import org.mule.transaction.XaTransactionFactory;
20
21 import javax.transaction.Status;
22 import javax.transaction.Transaction;
23 import javax.transaction.TransactionManager;
24
25
26
27
28
29 public abstract class AbstractTxThreadAssociationTestCase extends AbstractMuleTestCase
30 {
31
32 private TransactionManager tm;
33 protected static final int TRANSACTION_TIMEOUT_SECONDS = 3;
34
35 protected void doSetUp() throws Exception
36 {
37 super.doSetUp();
38 TransactionManagerFactory factory = getTransactionManagerFactory();
39 tm = factory.create(muleContext.getConfiguration());
40 assertNotNull("Transaction Manager should be available.", tm);
41 assertNull("There sould be no current transaction associated.", tm.getTransaction());
42 }
43
44 public void testTxHandleCommitKeepsThreadAssociation() throws Exception
45 {
46
47 tm.setTransactionTimeout(TRANSACTION_TIMEOUT_SECONDS);
48 tm.begin();
49
50 Transaction tx = tm.getTransaction();
51 assertNotNull("Transaction should have started.", tx);
52 assertEquals("TX should have been active", Status.STATUS_ACTIVE, tx.getStatus());
53
54 tx.commit();
55
56 tx = tm.getTransaction();
57 assertNotNull("Committing via TX handle should NOT disassociated TX from the current thread.",
58 tx);
59 assertEquals("TX status should have been COMMITTED.", Status.STATUS_COMMITTED, tx.getStatus());
60
61
62
63 Transaction suspended = tm.suspend();
64 assertTrue("Wrong TX suspended?.", suspended.equals(tx));
65 assertNull("TX should've been disassociated from the thread.", tm.getTransaction());
66
67
68 tm.resume(null);
69
70
71 assertNull(tm.getTransaction());
72 }
73
74 public void testTxManagerCommitDissassociatesThread() throws Exception
75 {
76
77 tm.setTransactionTimeout(TRANSACTION_TIMEOUT_SECONDS);
78 tm.begin();
79
80 Transaction tx = tm.getTransaction();
81 assertNotNull("Transaction should have started.", tx);
82 assertEquals("TX should have been active", Status.STATUS_ACTIVE, tx.getStatus());
83
84 tm.commit();
85
86 assertNull("Committing via TX Manager should have disassociated TX from the current thread.",
87 tm.getTransaction());
88 }
89
90 public void testTxManagerRollbackDissassociatesThread() throws Exception
91 {
92
93 tm.setTransactionTimeout(TRANSACTION_TIMEOUT_SECONDS);
94 tm.begin();
95
96 Transaction tx = tm.getTransaction();
97 assertNotNull("Transaction should have started.", tx);
98 assertEquals("TX should have been active", Status.STATUS_ACTIVE, tx.getStatus());
99
100 tm.rollback();
101
102 assertNull("Committing via TX Manager should have disassociated TX from the current thread.",
103 tm.getTransaction());
104 }
105
106
107
108
109
110
111 public void testAlwaysBeginXaTransactionSuspendResume() throws Exception
112 {
113 muleContext.setTransactionManager(tm);
114 assertNull("There sould be no current transaction associated.", tm.getTransaction());
115
116
117 tm.setTransactionTimeout(TRANSACTION_TIMEOUT_SECONDS);
118
119
120 TransactionConfig config = new MuleTransactionConfig();
121 config.setFactory(new XaTransactionFactory());
122 config.setAction(TransactionConfig.ACTION_ALWAYS_BEGIN);
123 TransactionTemplate template = new TransactionTemplate(config, muleContext);
124
125
126 final TransactionConfig nestedConfig = new MuleTransactionConfig();
127 nestedConfig.setFactory(new XaTransactionFactory());
128 nestedConfig.setAction(TransactionConfig.ACTION_ALWAYS_BEGIN);
129
130
131 template.execute(new TransactionCallback<Void>()
132 {
133 public Void doInTransaction() throws Exception
134 {
135
136
137 TransactionTemplate<Void> nestedTemplate =
138 new TransactionTemplate<Void>(nestedConfig, muleContext);
139 final Transaction firstTx = tm.getTransaction();
140 assertNotNull(firstTx);
141 assertEquals(firstTx.getStatus(), Status.STATUS_ACTIVE);
142 return nestedTemplate.execute(new TransactionCallback<Void>()
143 {
144 public Void doInTransaction() throws Exception
145 {
146 Transaction secondTx = tm.getTransaction();
147 assertNotNull(secondTx);
148 assertEquals(firstTx.getStatus(), Status.STATUS_ACTIVE);
149 assertEquals(secondTx.getStatus(), Status.STATUS_ACTIVE);
150 try
151 {
152 tm.resume(firstTx);
153 fail("Second transaction must be active");
154 }
155 catch (java.lang.IllegalStateException e)
156 {
157
158
159
160
161 }
162 try
163 {
164 Transaction currentTx = tm.suspend();
165 assertTrue(currentTx.equals(secondTx));
166 tm.resume(firstTx);
167 assertEquals(firstTx, tm.getTransaction());
168 assertEquals(firstTx.getStatus(), Status.STATUS_ACTIVE);
169 assertEquals(secondTx.getStatus(), Status.STATUS_ACTIVE);
170 Transaction a = tm.suspend();
171 assertTrue(a.equals(firstTx));
172 tm.resume(secondTx);
173 }
174 catch (Exception e)
175 {
176 fail("Error: " + e);
177 }
178
179
180 return null;
181 }
182 });
183 }
184 });
185 assertNull("Committing via TX Manager should have disassociated TX from the current thread.",
186 tm.getTransaction());
187 }
188
189
190
191
192
193
194 public void testNoneXaTransactionSuspendResume() throws Exception
195 {
196 muleContext.setTransactionManager(tm);
197 assertNull("There sould be no current transaction associated.", tm.getTransaction());
198
199
200 tm.setTransactionTimeout(TRANSACTION_TIMEOUT_SECONDS);
201
202
203 TransactionConfig config = new MuleTransactionConfig();
204 config.setFactory(new XaTransactionFactory());
205 config.setAction(TransactionConfig.ACTION_ALWAYS_BEGIN);
206 TransactionTemplate<Void> template = new TransactionTemplate<Void>(config, muleContext);
207
208
209 final TransactionConfig nestedConfig = new MuleTransactionConfig();
210 nestedConfig.setFactory(new XaTransactionFactory());
211 nestedConfig.setAction(TransactionConfig.ACTION_NONE);
212
213
214 template.execute(new TransactionCallback<Void>()
215 {
216 public Void doInTransaction() throws Exception
217 {
218
219
220 TransactionTemplate<Void> nestedTemplate =
221 new TransactionTemplate<Void>(nestedConfig, muleContext);
222 final Transaction firstTx = tm.getTransaction();
223 assertNotNull(firstTx);
224 assertEquals(firstTx.getStatus(), Status.STATUS_ACTIVE);
225 return nestedTemplate.execute(new TransactionCallback<Void>()
226 {
227 public Void doInTransaction() throws Exception
228 {
229 Transaction secondTx = tm.getTransaction();
230 assertNull(secondTx);
231 assertEquals(firstTx.getStatus(), Status.STATUS_ACTIVE);
232 try
233 {
234 tm.resume(firstTx);
235 assertEquals(firstTx, tm.getTransaction());
236 assertEquals(firstTx.getStatus(), Status.STATUS_ACTIVE);
237 Transaction a = tm.suspend();
238 assertTrue(a.equals(firstTx));
239 }
240 catch (Exception e)
241 {
242 fail("Error: " + e);
243 }
244
245
246 return null;
247 }
248 });
249 }
250 });
251 assertNull("Committing via TX Manager should have disassociated TX from the current thread.",
252 tm.getTransaction());
253 }
254
255
256
257
258
259
260 public void testXaTransactionTermination() throws Exception
261 {
262 muleContext.setTransactionManager(tm);
263 assertNull("There sould be no current transaction associated.", tm.getTransaction());
264
265
266 tm.setTransactionTimeout(TRANSACTION_TIMEOUT_SECONDS);
267
268 XaTransaction muleTx = new XaTransaction(muleContext);
269 assertFalse(muleTx.isBegun());
270 assertEquals(Status.STATUS_NO_TRANSACTION, muleTx.getStatus());
271 muleTx.begin();
272
273 assertTrue(muleTx.isBegun());
274
275 muleTx.commit();
276
277 Transaction jtaTx = tm.getTransaction();
278 assertNull("Committing via TX Manager should have disassociated TX from the current thread.", jtaTx);
279 assertEquals(Status.STATUS_NO_TRANSACTION, muleTx.getStatus());
280 }
281
282
283
284
285
286
287
288 public void testNoNestedTxStarted() throws Exception
289 {
290 muleContext.setTransactionManager(tm);
291 assertNull("There sould be no current transaction associated.", tm.getTransaction());
292
293
294 tm.setTransactionTimeout(TRANSACTION_TIMEOUT_SECONDS);
295
296
297 TransactionConfig config = new MuleTransactionConfig();
298 config.setFactory(new XaTransactionFactory());
299 config.setAction(TransactionConfig.ACTION_ALWAYS_BEGIN);
300 TransactionTemplate template = new TransactionTemplate(config, muleContext);
301
302
303 final TransactionConfig nestedConfig = new MuleTransactionConfig();
304 nestedConfig.setFactory(new XaTransactionFactory());
305 nestedConfig.setAction(TransactionConfig.ACTION_BEGIN_OR_JOIN);
306
307
308 template.execute(new TransactionCallback<Void>()
309 {
310 public Void doInTransaction() throws Exception
311 {
312
313
314 TransactionTemplate<Void> nestedTemplate =
315 new TransactionTemplate<Void>(nestedConfig, muleContext);
316 return nestedTemplate.execute(new TransactionCallback<Void>()
317 {
318 public Void doInTransaction() throws Exception
319 {
320
321 return null;
322 }
323 });
324 }
325 });
326 }
327
328
329 protected TransactionManager getTransactionManager()
330 {
331 return tm;
332 }
333
334 protected abstract TransactionManagerFactory getTransactionManagerFactory();
335
336 }