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