KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > transaction > interceptor > TransactionInterceptor


1 /*
2  * Copyright 2002-2006 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.transaction.interceptor;
18
19 import java.io.IOException JavaDoc;
20 import java.io.ObjectInputStream JavaDoc;
21 import java.io.ObjectOutputStream JavaDoc;
22 import java.io.Serializable JavaDoc;
23 import java.util.Properties JavaDoc;
24
25 import org.aopalliance.intercept.MethodInterceptor;
26 import org.aopalliance.intercept.MethodInvocation;
27
28 import org.springframework.transaction.PlatformTransactionManager;
29 import org.springframework.transaction.TransactionStatus;
30 import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
31 import org.springframework.transaction.support.TransactionCallback;
32
33 /**
34  * AOP Alliance MethodInterceptor providing declarative transaction
35  * management using the common Spring transaction infrastructure.
36  *
37  * <p>Derives from the TransactionAspectSupport class. That class contains
38  * the necessary calls into Spring's underlying transaction API:
39  * subclasses such as this are responsible for calling superclass methods
40  * such as <code>createTransactionIfNecessary</code> in the correct order,
41  * in the event of normal invocation return or an exception.
42  *
43  * <p>TransactionInterceptors are thread-safe.
44  *
45  * @author Rod Johnson
46  * @author Juergen Hoeller
47  * @see TransactionProxyFactoryBean
48  * @see org.springframework.aop.framework.ProxyFactoryBean
49  * @see org.springframework.transaction.interceptor.TransactionAspectSupport
50  * @see org.springframework.transaction.PlatformTransactionManager
51  */

52 public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable JavaDoc {
53
54     /**
55      * Create a new TransactionInterceptor.
56      * Transaction manager and transaction attributes still need to be set.
57      * @see #setTransactionManager
58      * @see #setTransactionAttributes(java.util.Properties)
59      * @see #setTransactionAttributeSource(TransactionAttributeSource)
60      */

61     public TransactionInterceptor() {
62     }
63
64     /**
65      * Create a new TransactionInterceptor.
66      * @param ptm the transaction manager to perform the actual transaction management
67      * @param attributes the transaction attributes in properties format
68      * @see #setTransactionManager
69      * @see #setTransactionAttributes(java.util.Properties)
70      */

71     public TransactionInterceptor(PlatformTransactionManager ptm, Properties JavaDoc attributes) {
72         setTransactionManager(ptm);
73         setTransactionAttributes(attributes);
74     }
75
76     /**
77      * Create a new TransactionInterceptor.
78      * @param ptm the transaction manager to perform the actual transaction management
79      * @param tas the attribute source to be used to find transaction attributes
80      * @see #setTransactionManager
81      * @see #setTransactionAttributeSource(TransactionAttributeSource)
82      */

83     public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
84         setTransactionManager(ptm);
85         setTransactionAttributeSource(tas);
86     }
87
88
89     public Object JavaDoc invoke(final MethodInvocation invocation) throws Throwable JavaDoc {
90         // Work out the target class: may be <code>null</code>.
91
// The TransactionAttributeSource should be passed the target class
92
// as well as the method, which may be from an interface.
93
Class JavaDoc targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);
94
95         // If the transaction attribute is null, the method is non-transactional.
96
final TransactionAttribute txAttr =
97                 getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);
98         final String JavaDoc joinpointIdentification = methodIdentification(invocation.getMethod());
99
100         if (txAttr == null || !(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) {
101             // Standard transaction demarcation with getTransaction and commit/rollback calls.
102
TransactionInfo txInfo = createTransactionIfNecessary(txAttr, joinpointIdentification);
103             Object JavaDoc retVal = null;
104             try {
105                 // This is an around advice: Invoke the next interceptor in the chain.
106
// This will normally result in a target object being invoked.
107
retVal = invocation.proceed();
108             }
109             catch (Throwable JavaDoc ex) {
110                 // target invocation exception
111
completeTransactionAfterThrowing(txInfo, ex);
112                 throw ex;
113             }
114             finally {
115                 cleanupTransactionInfo(txInfo);
116             }
117             commitTransactionAfterReturning(txInfo);
118             return retVal;
119         }
120
121         else {
122             // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
123
try {
124                 Object JavaDoc result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,
125                         new TransactionCallback() {
126                             public Object JavaDoc doInTransaction(TransactionStatus status) {
127                                 TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);
128                                 try {
129                                     return invocation.proceed();
130                                 }
131                                 catch (Throwable JavaDoc ex) {
132                                     if (txAttr.rollbackOn(ex)) {
133                                         // A RuntimeException: will lead to a rollback.
134
throw new ThrowableHolderException(ex);
135                                     }
136                                     else {
137                                         // A normal return value: will lead to a commit.
138
return new ThrowableHolder(ex);
139                                     }
140                                 }
141                                 finally {
142                                     cleanupTransactionInfo(txInfo);
143                                 }
144                             }
145                         });
146
147                 // Check result: It might indicate a Throwable to rethrow.
148
if (result instanceof ThrowableHolder) {
149                     throw ((ThrowableHolder) result).getThrowable();
150                 }
151                 else {
152                     return result;
153                 }
154             }
155             catch (ThrowableHolderException ex) {
156                 throw ex.getThrowable();
157             }
158         }
159     }
160
161
162     //---------------------------------------------------------------------
163
// Serialization support
164
//---------------------------------------------------------------------
165

166     private void readObject(ObjectInputStream JavaDoc ois) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
167         // Rely on default serialization, although this class itself doesn't carry state anyway...
168
ois.defaultReadObject();
169
170         // Serialize all relevant superclass fields.
171
// Superclass can't implement Serializable because it also serves as base class
172
// for AspectJ aspects (which are not allowed to implement Serializable)!
173
setTransactionManager((PlatformTransactionManager) ois.readObject());
174         setTransactionAttributeSource((TransactionAttributeSource) ois.readObject());
175     }
176
177     private void writeObject(ObjectOutputStream JavaDoc oos) throws IOException JavaDoc {
178         // Rely on default serialization, although this class itself doesn't carry state anyway...
179
oos.defaultWriteObject();
180
181         // Deserialize superclass fields.
182
oos.writeObject(getTransactionManager());
183         oos.writeObject(getTransactionAttributeSource());
184     }
185
186
187     /**
188      * Internal holder class for a Throwable, used as a return value
189      * from a TransactionCallback (to be subsequently unwrapped again).
190      */

191     private static class ThrowableHolder {
192
193         private final Throwable JavaDoc throwable;
194
195         public ThrowableHolder(Throwable JavaDoc throwable) {
196             this.throwable = throwable;
197         }
198
199         public Throwable JavaDoc getThrowable() {
200             return throwable;
201         }
202     }
203
204
205     /**
206      * Internal holder class for a Throwable, used as a RuntimeException to be
207      * thrown from a TransactionCallback (and subsequently unwrapped again).
208      */

209     private static class ThrowableHolderException extends RuntimeException JavaDoc {
210
211         private final Throwable JavaDoc throwable;
212
213         public ThrowableHolderException(Throwable JavaDoc throwable) {
214             super(throwable.toString());
215             this.throwable = throwable;
216         }
217
218         public Throwable JavaDoc getThrowable() {
219             return throwable;
220         }
221
222         public String JavaDoc toString() {
223             return this.throwable.toString();
224         }
225     }
226
227 }
228
Popular Tags