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 org.mule.api.MuleContext;
14  import org.mule.api.transaction.TransactionConfig;
15  import org.mule.api.transaction.TransactionException;
16  import org.mule.tck.FunctionalTestCase;
17  import org.mule.transaction.MuleTransactionConfig;
18  import org.mule.transaction.TransactionCoordination;
19  import org.mule.transaction.TransactionTemplate;
20  import org.mule.transaction.XaTransactionFactory;
21  
22  import java.io.PrintWriter;
23  import java.io.StringWriter;
24  import java.util.HashMap;
25  import java.util.Map;
26  
27  import javax.transaction.SystemException;
28  import javax.transaction.Transaction;
29  import javax.transaction.TransactionManager;
30  import javax.transaction.xa.XAException;
31  import javax.transaction.xa.XAResource;
32  import javax.transaction.xa.Xid;
33  
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  
37  
38  public abstract class AbstractExternalTransactionTestCase extends FunctionalTestCase
39  {
40      protected static final Log logger = LogFactory.getLog(AbstractExternalTransactionTestCase.class);
41      protected MuleContext context;
42      protected TransactionManager tm;
43  
44      @Override
45      protected void doSetUp() throws Exception
46      {
47          cleanupTransactionState();
48      }
49  
50      @Override
51      protected void doTearDown() throws Exception
52      {
53          cleanupTransactionState();
54      }
55  
56      private void cleanupTransactionState()
57      {
58          try
59          {
60              if (tm != null && tm.getTransaction() != null)
61              {
62                  tm.rollback();
63              }
64          }
65          catch (Exception ex)
66          {
67              logger.debug(ex);
68          }
69          try
70          {
71              org.mule.api.transaction.Transaction tx = TransactionCoordination.getInstance().getTransaction();
72              if (tx != null)
73              {
74                  TransactionCoordination.getInstance().unbindTransaction(tx);
75              }
76          }
77          catch (TransactionException ex)
78          {
79              logger.debug(ex);
80          }
81      }
82  
83      protected void init() throws Exception
84      {
85          context = createMuleContext();
86          tm = context.getTransactionManager();
87      }
88  
89      protected <T> TransactionTemplate<T> createTransactionTemplate(byte action, boolean considerExternal)
90      {
91          TransactionConfig tc = new MuleTransactionConfig();
92          tc.setAction(action);
93          tc.setFactory(new XaTransactionFactory());
94          tc.setInteractWithExternal(considerExternal);
95          TransactionTemplate<T> tt = new TransactionTemplate<T>(tc, context);
96          return tt;
97      }
98  
99      /** An XA resource that allows setting, committing, and rolling back the value of one resource */
100     public static class TestResource implements XAResource
101     {
102         private Map<Transaction, Integer> transientValue = new HashMap<Transaction, Integer>();
103         private int persistentValue;
104         private TransactionManager tm;
105 
106         public TestResource(TransactionManager tm)
107         {
108             this.tm = tm;
109         }
110 
111         public void setValue(int val)
112         {
113             Transaction tx = getCurrentTransaction();
114             transientValue.put(tx, val);
115         }
116 
117         private Transaction getCurrentTransaction()
118         {
119             Transaction tx = null;
120             Exception ex = null;
121             try
122             {
123                 tx = tm.getTransaction();
124             }
125             catch (SystemException e)
126             {
127                 tx = null;
128                 ex = e;
129             }
130             if (tx == null)
131             {
132                 throw new IllegalStateException("Unable to access resource value outside transaction", ex);
133             }
134             return tx;
135         }
136 
137         public int getPersistentValue()
138         {
139             return persistentValue;
140         }
141 
142         public int getValue()
143         {
144             Transaction tx = null;
145             try
146             {
147                 tx = getCurrentTransaction();
148             }
149             catch (Exception ex)
150             {
151                 // return persistent value
152             }
153             Integer val = transientValue.get(tx);
154             return val == null ? persistentValue : val;
155         }
156 
157         public void commit(Xid id, boolean onePhase) throws XAException
158         {
159             logger.debug("XA_COMMIT[" + id + "]");
160             dumpStackTrace();
161             Transaction tx = getCurrentTransaction();
162             persistentValue = transientValue.get(tx);
163         }
164 
165         public void end(Xid xid, int flags) throws XAException
166         {
167             logger.debug("XA_END[" + xid + "] Flags=" + flags);
168             dumpStackTrace();
169         }
170 
171         public void forget(Xid xid) throws XAException
172         {
173             logger.debug("XA_FORGET[" + xid + "]");
174             dumpStackTrace();
175         }
176 
177         public int getTransactionTimeout() throws XAException
178         {
179             return (_timeout);
180         }
181 
182         public boolean isSameRM(XAResource xares) throws XAException
183         {
184             return (xares.equals(this));
185         }
186 
187         public int prepare(Xid xid) throws XAException
188         {
189             logger.debug("XA_PREPARE[" + xid + "]");
190             dumpStackTrace();
191 
192             return (XA_OK);
193         }
194 
195         public Xid[] recover(int flag) throws XAException
196         {
197             logger.debug("RECOVER[" + flag + "]");
198             dumpStackTrace();
199             return (null);
200         }
201 
202         public void rollback(Xid xid) throws XAException
203         {
204             logger.debug("XA_ROLLBACK[" + xid + "]");
205             dumpStackTrace();
206 
207             Transaction tx = getCurrentTransaction();
208             transientValue.remove(tx);
209         }
210 
211         public boolean setTransactionTimeout(int seconds) throws XAException
212         {
213             _timeout = seconds;
214             return (true);
215         }
216 
217         public void start(Xid xid, int flags) throws XAException
218         {
219             logger.debug("XA_START[" + xid + "] Flags=" + flags);
220             dumpStackTrace();
221         }
222 
223         protected int _timeout = 0;
224 
225         private void dumpStackTrace()
226         {
227             if (logger.isDebugEnabled() && false)
228             {
229                 final StringWriter sw = new StringWriter();
230                 PrintWriter pw = new PrintWriter(sw);
231                 new Exception().printStackTrace(pw);
232                 pw.flush();
233                 logger.debug(sw.toString());
234             }
235         }
236     }
237 }