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