KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > transaction > support > TransactionTemplate


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.support;
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21
22 import org.springframework.beans.factory.InitializingBean;
23 import org.springframework.transaction.PlatformTransactionManager;
24 import org.springframework.transaction.TransactionDefinition;
25 import org.springframework.transaction.TransactionException;
26 import org.springframework.transaction.TransactionStatus;
27
28 /**
29  * Template class that simplifies programmatic transaction demarcation and
30  * transaction exception handling.
31  *
32  * <p>The central method is "execute", supporting transactional code implementing
33  * the TransactionCallback interface. It handles the transaction lifecycle and
34  * possible exceptions such that neither the TransactionCallback implementation
35  * nor the calling code needs to explicitly handle transactions.
36  *
37  * <p>Typical usage: Allows for writing low-level data access objects that use
38  * (JNDI) resources but are not transaction-aware themselves. Instead, they
39  * can implicitly participate in (JTA) transactions handled by higher-level
40  * application services utilizing this class, making calls to the low-level
41  * services via an inner-class callback object.
42  *
43  * <p>Can be used within a service implementation via direct instantiation with
44  * a transaction manager reference, or get prepared in an application context
45  * and passed to services as bean reference. Note: The transaction manager should
46  * always be configured as bean in the application context: in the first case given
47  * to the service directly, in the second case given to the prepared template.
48  *
49  * <p>Supports setting the propagation behavior and the isolation level by name,
50  * for convenient configuration in context definitions.
51  *
52  * @author Juergen Hoeller
53  * @since 17.03.2003
54  * @see #execute
55  * @see org.springframework.transaction.support.TransactionCallback
56  * @see org.springframework.transaction.PlatformTransactionManager
57  * @see org.springframework.transaction.jta.JtaTransactionManager
58  */

59 public class TransactionTemplate extends DefaultTransactionDefinition implements InitializingBean {
60
61     /** Logger available to subclasses */
62     protected final Log logger = LogFactory.getLog(getClass());
63
64     private PlatformTransactionManager transactionManager = null;
65
66
67     /**
68      * Create a new TransactionTemplate instance.
69      * Mainly targetted at configuration by a bean factory.
70      * Note: Transaction manager property needs to be set before any execute calls.
71      * @see #setTransactionManager
72      */

73     public TransactionTemplate() {
74     }
75
76     /**
77      * Create a new TransactionTemplate instance.
78      * @param transactionManager transaction management strategy to be used
79      */

80     public TransactionTemplate(PlatformTransactionManager transactionManager) {
81         this.transactionManager = transactionManager;
82     }
83     
84     /**
85      * Create a new TransactionTemplate instance.
86      * @param transactionManager transaction management strategy to be used
87      * @param transactionDefinition transaction definition to copy from.
88      * Properties can still be set to change values
89      */

90     public TransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition) {
91         super(transactionDefinition);
92         this.transactionManager = transactionManager;
93     }
94
95     /**
96      * Set the transaction management strategy to be used.
97      */

98     public void setTransactionManager(PlatformTransactionManager transactionManager) {
99         this.transactionManager = transactionManager;
100     }
101
102     /**
103      * Return the transaction management strategy to be used.
104      */

105     public PlatformTransactionManager getTransactionManager() {
106         return transactionManager;
107     }
108
109     public void afterPropertiesSet() {
110         if (this.transactionManager == null) {
111             throw new IllegalArgumentException JavaDoc("transactionManager is required");
112         }
113     }
114
115
116     /**
117      * Execute the action specified by the given callback object within a transaction.
118      * <p>Allows for returning a result object created within the transaction, that is,
119      * a domain object or a collection of domain objects. A RuntimeException thrown
120      * by the callback is treated as a fatal exception that enforces a rollback.
121      * Such an exception gets propagated to the caller of the template.
122      * @param action the callback object that specifies the transactional action
123      * @return a result object returned by the callback, or <code>null</code> if none
124      * @throws TransactionException in case of initialization, rollback, or system errors
125      */

126     public Object JavaDoc execute(TransactionCallback action) throws TransactionException {
127         if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
128             return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
129         }
130         else {
131             TransactionStatus status = this.transactionManager.getTransaction(this);
132             Object JavaDoc result = null;
133             try {
134                 result = action.doInTransaction(status);
135             }
136             catch (RuntimeException JavaDoc ex) {
137                 // Transactional code threw application exception -> rollback
138
rollbackOnException(status, ex);
139                 throw ex;
140             }
141             catch (Error JavaDoc err) {
142                 // Transactional code threw error -> rollback
143
rollbackOnException(status, err);
144                 throw err;
145             }
146             this.transactionManager.commit(status);
147             return result;
148         }
149     }
150
151     /**
152      * Perform a rollback, handling rollback exceptions properly.
153      * @param status object representing the transaction
154      * @param ex the thrown application exception or error
155      * @throws TransactionException in case of a rollback error
156      */

157     private void rollbackOnException(TransactionStatus status, Throwable JavaDoc ex) throws TransactionException {
158         logger.debug("Initiating transaction rollback on application exception", ex);
159         try {
160             this.transactionManager.rollback(status);
161         }
162         catch (RuntimeException JavaDoc ex2) {
163             logger.error("Application exception overridden by rollback exception", ex);
164             throw ex2;
165         }
166         catch (Error JavaDoc err) {
167             logger.error("Application exception overridden by rollback error", ex);
168             throw err;
169         }
170     }
171
172 }
173
Popular Tags