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