View Javadoc

1   /*
2    * $Id:AbstractExternalTransactionTestCase.java 8215 2007-09-05 16:56:51Z aperepel $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.transport.vm.functional.transactions;
12  
13  import static org.junit.Assert.assertEquals;
14  import static org.junit.Assert.assertNotNull;
15  import static org.junit.Assert.assertNotSame;
16  import static org.junit.Assert.assertNull;
17  import static org.junit.Assert.assertSame;
18  import static org.junit.Assert.assertTrue;
19  import static org.junit.Assert.fail;
20  
21  import org.mule.api.MuleMessage;
22  import org.mule.api.transaction.TransactionCallback;
23  import org.mule.api.transaction.TransactionConfig;
24  import org.mule.module.client.MuleClient;
25  import org.mule.transaction.IllegalTransactionStateException;
26  import org.mule.transaction.TransactionTemplate;
27  import org.mule.util.ExceptionUtils;
28  
29  import java.util.Arrays;
30  import java.util.Collection;
31  
32  import javax.transaction.Transaction;
33  
34  import org.junit.Test;
35  import org.junit.runners.Parameterized.Parameters;
36  
37  /** Test transaction behavior when "joinExternal" is set to allow joining external transactions
38   * There is one test per legal transactional behavior (e.g. ALWAYS_BEGIN).
39   */
40  public class ExternalTransactionTestCase extends AbstractExternalTransactionTestCase
41  {
42      public static final long WAIT = 3000L;
43  
44      public ExternalTransactionTestCase(ConfigVariant variant, String configResources)
45      {
46          super(variant, configResources);   
47      }
48      
49      @Parameters
50      public static Collection<Object[]> parameters()
51      {
52          return Arrays.asList(new Object[][]{
53              {ConfigVariant.SERVICE, "org/mule/test/config/external-transaction-config-service.xml"},
54              {ConfigVariant.FLOW, "org/mule/test/config/external-transaction-config-flow.xml"}
55          });
56      }      
57      
58      @Test
59      public void testBeginOrJoinTransaction() throws Exception
60      {
61          init();
62          TransactionTemplate<String> tt = createTransactionTemplate(TransactionConfig.ACTION_BEGIN_OR_JOIN, true);
63  
64          tm.begin();
65          final Transaction tx = tm.getTransaction();
66          final TestResource resource1 = new TestResource(tm);
67          tx.enlistResource(resource1);
68          assertNotNull(tx);
69          String result = tt.execute(new TransactionCallback<String>()
70          {
71              @Override
72              public String doInTransaction() throws Exception
73              {
74                  Transaction muleTx = tm.getTransaction();
75                  assertSame(tx, muleTx);
76                  resource1.setValue(14);
77                  return "OK";
78              }
79          });
80  
81          // Not committed yet, since Mule joined the external transaction
82          assertEquals("OK", result);
83          assertEquals(14, resource1.getValue());
84          assertEquals(0, resource1.getPersistentValue());
85          tm.commit();
86  
87          // Now it's committed
88          assertEquals(14, resource1.getPersistentValue());
89  
90          // now try with no active transaction
91          result = tt.execute(new TransactionCallback<String>()
92          {
93              @Override
94              public String doInTransaction() throws Exception
95              {
96                  Transaction muleTx = tm.getTransaction();
97                  muleTx.enlistResource(resource1);
98                  resource1.setValue(15);
99                  return "OK";
100             }
101         });
102 
103         // Mule began and committed the transaction
104         assertEquals(15, resource1.getPersistentValue());
105     }
106 
107     @Test
108     public void testBeginTransaction() throws Exception
109     {
110         init();
111         TransactionTemplate<String> tt = createTransactionTemplate(TransactionConfig.ACTION_ALWAYS_BEGIN, true);
112 
113         tm.begin();
114         final Transaction tx = tm.getTransaction();
115         final TestResource resource1 = new TestResource(tm);
116 
117         assertNotNull(tx);
118         String result = tt.execute(new TransactionCallback<String>()
119         {
120             @Override
121             public String doInTransaction() throws Exception
122             {
123                 Transaction muleTx = tm.getTransaction();
124                 assertNotSame(tx, muleTx);
125                 muleTx.enlistResource(resource1);
126                 resource1.setValue(14);
127                 return "OK";
128             }
129         });
130 
131         // Committed in Mule's transaction
132         assertEquals("OK", result);
133         assertEquals(14, resource1.getValue());
134         assertEquals(14, resource1.getPersistentValue());
135         tm.commit();
136 
137         // Now it's committed
138         assertEquals(14, resource1.getPersistentValue());
139 
140         result = tt.execute(new TransactionCallback<String>()
141         {
142             @Override
143             public String doInTransaction() throws Exception
144             {
145                 Transaction muleTx = tm.getTransaction();
146                 assertNotSame(tx, muleTx);
147                 muleTx.enlistResource(resource1);
148                 resource1.setValue(15);
149                 return "OK";
150             }
151         });
152 
153         // Committed in Mule's transaction
154         assertEquals("OK", result);
155         assertEquals(15, resource1.getPersistentValue());
156     }
157 
158     @Test
159     public void testNoTransactionProcessing() throws Exception
160     {
161         init();
162         TransactionTemplate<String> tt = createTransactionTemplate(TransactionConfig.ACTION_NONE, true);
163 
164         tm.begin();
165         final Transaction tx = tm.getTransaction();
166         final TestResource resource1 = new TestResource(tm);
167 
168         assertNotNull(tx);
169         tx.enlistResource(resource1);
170         resource1.setValue(14);
171         String result = tt.execute(new TransactionCallback<String>()
172         {
173             @Override
174             public String doInTransaction() throws Exception
175             {
176                 Transaction muleTx = tm.getTransaction();
177                 assertNull(muleTx);
178                 return "OK";
179             }
180         });
181 
182         // transaction restored, no commit
183         assertEquals("OK", result);
184         assertEquals(14, resource1.getValue());
185         assertEquals(0, resource1.getPersistentValue());
186         tm.commit();
187 
188         // Now it's committed
189         assertEquals(14, resource1.getPersistentValue());
190 
191         result = tt.execute(new TransactionCallback<String>()
192         {
193             @Override
194             public String doInTransaction() throws Exception
195             {
196                 Transaction muleTx = tm.getTransaction();
197                 assertNull(muleTx);
198                 return "OK";
199             }
200         });
201     }
202 
203     @Test
204     public void testAlwaysJoinTransaction() throws Exception
205     {
206         init();
207         TransactionTemplate<String> tt = createTransactionTemplate(TransactionConfig.ACTION_ALWAYS_JOIN, true);
208 
209         tm.begin();
210         final Transaction tx = tm.getTransaction();
211         final TestResource resource1 = new TestResource(tm);
212         tx.enlistResource(resource1);
213         assertNotNull(tx);
214         String result = tt.execute(new TransactionCallback<String>()
215         {
216             @Override
217             public String doInTransaction() throws Exception
218             {
219                 Transaction muleTx = tm.getTransaction();
220                 assertSame(tx, muleTx);
221                 resource1.setValue(14);
222                 return "OK";
223             }
224         });
225 
226         // Not committed yet, since Mule joined the external transaction
227         assertEquals("OK", result);
228         assertEquals(14, resource1.getValue());
229         assertEquals(0, resource1.getPersistentValue());
230         tm.commit();
231 
232         // Now it's committed
233         assertEquals(14, resource1.getPersistentValue());
234 
235         // try with no active transaction.. Should throw
236         try
237         {
238             result = tt.execute(new TransactionCallback<String>()
239             {
240                 @Override
241                 public String doInTransaction() throws Exception
242                 {
243                     return "OK";
244                 }
245             });
246             fail("No exception seen");
247         }
248         catch (Exception e)
249         {
250             logger.debug("saw exception " + e.getMessage());
251         }
252     }
253 
254     @Test
255     public void testJoinTransactionIfPossible() throws Exception
256     {
257         init();
258         TransactionTemplate<String> tt = createTransactionTemplate(TransactionConfig.ACTION_JOIN_IF_POSSIBLE, true);
259 
260         tm.begin();
261         final Transaction tx = tm.getTransaction();
262         final TestResource resource1 = new TestResource(tm);
263         tx.enlistResource(resource1);
264         assertNotNull(tx);
265         String result = tt.execute(new TransactionCallback<String>()
266         {
267             @Override
268             public String doInTransaction() throws Exception
269             {
270                 Transaction muleTx = tm.getTransaction();
271                 assertSame(tx, muleTx);
272                 resource1.setValue(14);
273                 return "OK";
274             }
275         });
276 
277         // Not committed yet, since Mule joined the external transaction
278         assertEquals("OK", result);
279         assertEquals(14, resource1.getValue());
280         assertEquals(0, resource1.getPersistentValue());
281         tm.commit();
282 
283         // Now it's committed
284         assertEquals(14, resource1.getPersistentValue());
285 
286         // try with no active transaction.. Should run with none
287         result = tt.execute(new TransactionCallback<String>()
288         {
289             @Override
290             public String doInTransaction() throws Exception
291             {
292                 Transaction muleTx = tm.getTransaction();
293                 assertNull(muleTx);
294                 return "OK";
295             }
296         });
297         assertEquals("OK", result);
298     }
299 
300     @Test
301     public void testNoTransactionAllowed() throws Exception
302     {
303         init();
304         TransactionTemplate<String> tt = createTransactionTemplate(TransactionConfig.ACTION_NEVER, true);
305 
306         tm.begin();
307         final Transaction tx = tm.getTransaction();
308         final TestResource resource1 = new TestResource(tm);
309         tx.enlistResource(resource1);
310         assertNotNull(tx);
311 
312         // This will throw since no transaction is allowed
313         try
314         {
315             tt.execute(new TransactionCallback<String>()
316             {
317                 @Override
318                 public String doInTransaction() throws Exception
319                 {
320                     return "OK";
321                 }
322             });
323             fail("No exception seen");
324         }
325         catch (Exception e)
326         {
327             logger.debug("saw exception " + e.getMessage());
328         }
329         tm.rollback();
330     }
331 
332     /** Check that the configuration specifies considers external transactions */
333     @Test
334     public void testConfiguration() throws Exception
335     {
336         MuleClient client = new MuleClient(muleContext);
337         tm = client.getMuleContext().getTransactionManager();
338         tm.begin();
339         client.send("vm://entry?connector=vm-normal", "OK", null);
340         tm.commit();
341         MuleMessage response = client.request("queue2", WAIT);
342         assertNull("Response is not null", response);
343 
344         // This will fail, since there will be no transaction to join
345         try
346         {
347             client.send("vm://entry?connector=vm-normal", "OK", null);
348             fail("Exception expected");
349         }
350         catch (Exception e)
351         {
352             assertTrue(ExceptionUtils.getRootCause(e) instanceof IllegalTransactionStateException);
353         }
354     }
355 }