1
2
3
4
5
6
7
8
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
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
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 }