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