1
2
3
4
5
6
7
8
9
10
11 package org.mule.transaction;
12
13 import org.mule.config.i18n.CoreMessages;
14 import org.mule.umo.TransactionException;
15 import org.mule.umo.UMOTransaction;
16 import org.mule.umo.UMOTransactionConfig;
17
18 import java.beans.ExceptionListener;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22
23 public class TransactionTemplate
24 {
25 private static final Log logger = LogFactory.getLog(TransactionTemplate.class);
26
27 private final UMOTransactionConfig config;
28 private final ExceptionListener exceptionListener;
29
30 public TransactionTemplate(UMOTransactionConfig config, ExceptionListener listener)
31 {
32 this.config = config;
33 exceptionListener = listener;
34 }
35
36 public Object execute(TransactionCallback callback) throws Exception
37 {
38 if (config == null || (config!=null && !config.isConfigured()))
39 {
40 return callback.doInTransaction();
41 }
42 else
43 {
44 byte action = config.getAction();
45 UMOTransaction tx = TransactionCoordination.getInstance().getTransaction();
46 UMOTransaction suspendedXATx = null;
47
48 if (action == UMOTransactionConfig.ACTION_NONE && tx != null)
49 {
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 throw new IllegalTransactionStateException(
66 CoreMessages.transactionAvailableButActionIs("None"));
67 }
68 else if (action == UMOTransactionConfig.ACTION_ALWAYS_BEGIN && tx != null)
69 {
70 if (logger.isDebugEnabled())
71 {
72 logger.debug("Transaction action is ACTION_ALWAYS_BEGIN, " +
73 "current TX: " + tx);
74 }
75 if (tx.isXA())
76 {
77
78 suspendedXATx = tx;
79 suspendXATransaction(suspendedXATx);
80 }
81 else
82 {
83
84 resolveTransaction(tx);
85 }
86
87 tx = null;
88 }
89 else if (action == UMOTransactionConfig.ACTION_ALWAYS_JOIN && tx == null)
90 {
91 throw new IllegalTransactionStateException(
92 CoreMessages.transactionNotAvailableButActionIs("Always Join"));
93 }
94
95 if (action == UMOTransactionConfig.ACTION_ALWAYS_BEGIN
96 || (action == UMOTransactionConfig.ACTION_BEGIN_OR_JOIN && tx == null))
97 {
98 logger.debug("Beginning transaction");
99 tx = config.getFactory().beginTransaction();
100 logger.debug("Transaction successfully started: " + tx);
101 }
102 else
103 {
104 tx = null;
105 }
106 try
107 {
108 Object result = callback.doInTransaction();
109 if (tx != null)
110 {
111 resolveTransaction(tx);
112 if (suspendedXATx != null)
113 {
114 resumeXATransaction(suspendedXATx);
115 tx = suspendedXATx;
116 }
117 }
118 return result;
119 }
120 catch (Exception e)
121 {
122 if (exceptionListener != null)
123 {
124 logger.info("Exception Caught in Transaction template. Handing off to exception handler: "
125 + exceptionListener);
126 exceptionListener.exceptionThrown(e);
127 }
128 else
129 {
130 logger
131 .info("Exception Caught in Transaction template without any exception listeners defined, exception is rethrown.");
132 if (tx != null)
133 {
134 tx.setRollbackOnly();
135 }
136 }
137 if (tx != null)
138 {
139
140
141
142
143
144
145
146 if (tx.isRollbackOnly())
147 {
148 logger.debug("Exception caught: rollback transaction", e);
149 }
150 resolveTransaction(tx);
151 if (suspendedXATx != null)
152 {
153 resumeXATransaction(suspendedXATx);
154 }
155 }
156
157 if (exceptionListener != null)
158 {
159 return null;
160 }
161 else
162 {
163 throw e;
164 }
165 }
166 catch (Error e)
167 {
168 if (tx != null)
169 {
170 logger.info("Error caught, rolling back TX " + tx, e);
171 tx.rollback();
172 }
173 throw e;
174 }
175 }
176 }
177
178 protected void resolveTransaction(UMOTransaction tx) throws TransactionException
179 {
180 if (tx.isRollbackOnly())
181 {
182 logger.debug("Transaction has been marked rollbackOnly, rolling it back: " + tx);
183 tx.rollback();
184 }
185 else
186 {
187 logger.debug("Committing transaction " + tx);
188 tx.commit();
189 }
190 }
191
192 protected void suspendXATransaction(UMOTransaction tx) throws TransactionException
193 {
194 if (logger.isDebugEnabled())
195 {
196 logger.debug("Suspending " + tx);
197 }
198
199 tx.suspend();
200
201 if (logger.isDebugEnabled())
202 {
203 logger.debug("Successfully suspended " + tx);
204 logger.debug("Unbinding the following TX from the current context: " + tx);
205 }
206
207 TransactionCoordination.getInstance().unbindTransaction(tx);
208 }
209
210 protected void resumeXATransaction(UMOTransaction tx) throws TransactionException
211 {
212 if (logger.isDebugEnabled())
213 {
214 logger.debug("Re-binding and Resuming " + tx);
215 }
216
217 TransactionCoordination.getInstance().bindTransaction(tx);
218 tx.resume();
219 }
220
221 }