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