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.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
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
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 }