Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
TransactionTemplate |
|
| 12.5;12.5 |
1 | /* | |
2 | * $Id: TransactionTemplate.java 7976 2007-08-21 14:26:13Z dirk.olmes $ | |
3 | * -------------------------------------------------------------------------------------- | |
4 | * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.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.transaction; | |
12 | ||
13 | import org.mule.config.i18n.CoreMessages; | |
14 | import org.mule.umo.UMOTransaction; | |
15 | import org.mule.umo.UMOTransactionConfig; | |
16 | ||
17 | import java.beans.ExceptionListener; | |
18 | ||
19 | import org.apache.commons.logging.Log; | |
20 | import org.apache.commons.logging.LogFactory; | |
21 | ||
22 | public class TransactionTemplate | |
23 | { | |
24 | 0 | private static final Log logger = LogFactory.getLog(TransactionTemplate.class); |
25 | ||
26 | private final UMOTransactionConfig config; | |
27 | private final ExceptionListener exceptionListener; | |
28 | ||
29 | public TransactionTemplate(UMOTransactionConfig config, ExceptionListener listener) | |
30 | 0 | { |
31 | 0 | this.config = config; |
32 | 0 | exceptionListener = listener; |
33 | 0 | } |
34 | ||
35 | public Object execute(TransactionCallback callback) throws Exception | |
36 | { | |
37 | 0 | if (config == null) |
38 | { | |
39 | 0 | return callback.doInTransaction(); |
40 | } | |
41 | else | |
42 | { | |
43 | 0 | byte action = config.getAction(); |
44 | 0 | UMOTransaction tx = TransactionCoordination.getInstance().getTransaction(); |
45 | ||
46 | 0 | if (action == UMOTransactionConfig.ACTION_NONE && tx != null) |
47 | { | |
48 | //TODO RM*: I'm not sure there is any value in throwing an exection here, since | |
49 | //there may be a transaction in progress but has nothing to to with this invocation | |
50 | //so maybe we just process outside the tx. Not sure yet | |
51 | //return callback.doInTransaction(); | |
52 | ||
53 | /* | |
54 | Reply from AP: There is value at the moment, at least in having fewer surprises | |
55 | with a more explicit config. Current behavior is that of 'Never' TX attribute | |
56 | in Java EE parlance. | |
57 | ||
58 | What you refer to, however, is the 'Not Supported' TX behavior. A SUSPEND is performed | |
59 | in this case with (optional) RESUME later. | |
60 | ||
61 | Revamping/enhancing the TX attributes in Mule is coming next on my action list for | |
62 | transactions in Mule after bringing Atomikos & ArjunaTS on-board and ditching a broken JOTM. | |
63 | */ | |
64 | ||
65 | 0 | throw new IllegalTransactionStateException( |
66 | CoreMessages.transactionAvailableButActionIs("None")); | |
67 | } | |
68 | 0 | else if (action == UMOTransactionConfig.ACTION_ALWAYS_BEGIN && tx != null) |
69 | { | |
70 | 0 | throw new IllegalTransactionStateException( |
71 | CoreMessages.transactionAvailableButActionIs("Always Begin")); | |
72 | } | |
73 | 0 | else if (action == UMOTransactionConfig.ACTION_ALWAYS_JOIN && tx == null) |
74 | { | |
75 | 0 | throw new IllegalTransactionStateException( |
76 | CoreMessages.transactionNotAvailableButActionIs("Always Join")); | |
77 | } | |
78 | ||
79 | 0 | if (action == UMOTransactionConfig.ACTION_ALWAYS_BEGIN |
80 | || (action == UMOTransactionConfig.ACTION_BEGIN_OR_JOIN && tx == null)) | |
81 | { | |
82 | 0 | logger.debug("Beginning transaction"); |
83 | 0 | tx = config.getFactory().beginTransaction(); |
84 | 0 | logger.debug("Transaction successfully started"); |
85 | } | |
86 | else | |
87 | { | |
88 | 0 | tx = null; |
89 | } | |
90 | try | |
91 | { | |
92 | 0 | Object result = callback.doInTransaction(); |
93 | 0 | if (tx != null) |
94 | { | |
95 | 0 | if (tx.isRollbackOnly()) |
96 | { | |
97 | 0 | logger.debug("Transaction is marked for rollback"); |
98 | 0 | tx.rollback(); |
99 | } | |
100 | else | |
101 | { | |
102 | 0 | logger.debug("Committing transaction"); |
103 | 0 | tx.commit(); |
104 | } | |
105 | } | |
106 | 0 | return result; |
107 | } | |
108 | 0 | catch (Exception e) |
109 | { | |
110 | 0 | if (exceptionListener != null) |
111 | { | |
112 | 0 | logger |
113 | .info("Exception Caught in Transaction template. Handing off to exception handler: " | |
114 | + exceptionListener); | |
115 | 0 | exceptionListener.exceptionThrown(e); |
116 | } | |
117 | else | |
118 | { | |
119 | 0 | logger |
120 | .info("Exception Caught in Transaction template without any exception listeners defined, exception is rethrown."); | |
121 | 0 | if (tx != null) |
122 | { | |
123 | 0 | tx.setRollbackOnly(); |
124 | } | |
125 | } | |
126 | 0 | if (tx != null) |
127 | { | |
128 | // The exception strategy can choose to route exception | |
129 | // messages | |
130 | // as part of the current transaction. So only rollback the | |
131 | // tx | |
132 | // if it has been marked for rollback (which is the default | |
133 | // case in the | |
134 | // AbstractExceptionListener) | |
135 | 0 | if (tx.isRollbackOnly()) |
136 | { | |
137 | 0 | logger.debug("Exception caught: rollback transaction", e); |
138 | 0 | tx.rollback(); |
139 | } | |
140 | else | |
141 | { | |
142 | 0 | tx.commit(); |
143 | } | |
144 | } | |
145 | // we've handled this exception above. just return null now | |
146 | 0 | if (exceptionListener != null) |
147 | { | |
148 | 0 | return null; |
149 | } | |
150 | else | |
151 | { | |
152 | 0 | throw e; |
153 | } | |
154 | } | |
155 | 0 | catch (Error e) |
156 | { | |
157 | 0 | if (tx != null) |
158 | { | |
159 | // TODO MULE-863: Correct level? With trace? | |
160 | 0 | logger.info("Error caught: rollback transaction", e); |
161 | 0 | tx.rollback(); |
162 | } | |
163 | 0 | throw e; |
164 | } | |
165 | } | |
166 | } | |
167 | ||
168 | } |