KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > transaction > jta > SpringJtaSynchronizationAdapter


1 /*
2  * Copyright 2002-2007 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.jta;
18
19 import javax.transaction.Status JavaDoc;
20 import javax.transaction.Synchronization JavaDoc;
21 import javax.transaction.TransactionManager JavaDoc;
22 import javax.transaction.UserTransaction JavaDoc;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27 import org.springframework.transaction.support.TransactionSynchronization;
28 import org.springframework.transaction.support.TransactionSynchronizationManager;
29 import org.springframework.util.Assert;
30
31 /**
32  * Adapter that implements the JTA {@link javax.transaction.Synchronization}
33  * interface delegating to an underlying Spring
34  * {@link org.springframework.transaction.support.TransactionSynchronization}.
35  *
36  * <p>Useful for synchronizing Spring resource management code with plain
37  * JTA / EJB CMT transactions, despite the original code being built for
38  * Spring transaction synchronization.
39  *
40  * @author Juergen Hoeller
41  * @since 2.0
42  * @see javax.transaction.Transaction#registerSynchronization
43  * @see org.springframework.transaction.support.TransactionSynchronization
44  */

45 public class SpringJtaSynchronizationAdapter implements Synchronization JavaDoc {
46
47     protected static final Log logger = LogFactory.getLog(SpringJtaSynchronizationAdapter.class);
48
49     private final TransactionSynchronization springSynchronization;
50
51     private UserTransaction JavaDoc jtaTransaction;
52
53     private boolean beforeCompletionCalled = false;
54
55
56     /**
57      * Create a new SpringJtaSynchronizationAdapter for the given Spring
58      * TransactionSynchronization and JTA TransactionManager.
59      * @param springSynchronization the Spring TransactionSynchronization to delegate to
60      */

61     public SpringJtaSynchronizationAdapter(TransactionSynchronization springSynchronization) {
62         Assert.notNull(springSynchronization, "TransactionSynchronization must not be null");
63         this.springSynchronization = springSynchronization;
64     }
65
66     /**
67      * Create a new SpringJtaSynchronizationAdapter for the given Spring
68      * TransactionSynchronization and JTA TransactionManager.
69      * <p>Note that this adapter will never perform a rollback-only call on WebLogic,
70      * since WebLogic Server is known to automatically mark the transaction as
71      * rollback-only in case of a <code>beforeCompletion</code> exception. Hence,
72      * on WLS, this constructor is equivalent to the single-arg constructor.
73      * @param springSynchronization the Spring TransactionSynchronization to delegate to
74      * @param jtaUserTransaction the JTA UserTransaction to use for rollback-only
75      * setting in case of an exception thrown in <code>beforeCompletion</code>
76      * (can be omitted if the JTA provider itself marks the transaction rollback-only
77      * in such a scenario, which is required by the JTA specification as of JTA 1.1).
78      */

79     public SpringJtaSynchronizationAdapter(
80             TransactionSynchronization springSynchronization, UserTransaction JavaDoc jtaUserTransaction) {
81
82         this(springSynchronization);
83         if (jtaUserTransaction != null && !jtaUserTransaction.getClass().getName().startsWith("weblogic.")) {
84             this.jtaTransaction = jtaUserTransaction;
85         }
86     }
87
88     /**
89      * Create a new SpringJtaSynchronizationAdapter for the given Spring
90      * TransactionSynchronization and JTA TransactionManager.
91      * <p>Note that this adapter will never perform a rollback-only call on WebLogic,
92      * since WebLogic Server is known to automatically mark the transaction as
93      * rollback-only in case of a <code>beforeCompletion</code> exception. Hence,
94      * on WLS, this constructor is equivalent to the single-arg constructor.
95      * @param springSynchronization the Spring TransactionSynchronization to delegate to
96      * @param jtaTransactionManager the JTA TransactionManager to use for rollback-only
97      * setting in case of an exception thrown in <code>beforeCompletion</code>
98      * (can be omitted if the JTA provider itself marks the transaction rollback-only
99      * in such a scenario, which is required by the JTA specification as of JTA 1.1)
100      */

101     public SpringJtaSynchronizationAdapter(
102             TransactionSynchronization springSynchronization, TransactionManager JavaDoc jtaTransactionManager) {
103
104         this(springSynchronization);
105         if (jtaTransactionManager != null && !jtaTransactionManager.getClass().getName().startsWith("weblogic.")) {
106             this.jtaTransaction = new UserTransactionAdapter(jtaTransactionManager);
107         }
108     }
109
110
111     /**
112      * JTA <code>beforeCompletion</code> callback: just invoked before commit.
113      * <p>In case of an exception, the JTA transaction will be marked as rollback-only.
114      * @see org.springframework.transaction.support.TransactionSynchronization#beforeCommit
115      */

116     public void beforeCompletion() {
117         try {
118             boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
119             this.springSynchronization.beforeCommit(readOnly);
120         }
121         catch (RuntimeException JavaDoc ex) {
122             setRollbackOnlyIfPossible();
123             throw ex;
124         }
125         catch (Error JavaDoc err) {
126             setRollbackOnlyIfPossible();
127             throw err;
128         }
129         finally {
130             // Process Spring's beforeCompletion early, in order to avoid issues
131
// with strict JTA implementations that issue warnings when doing JDBC
132
// operations after transaction completion (e.g. Connection.getWarnings).
133
this.beforeCompletionCalled = true;
134             this.springSynchronization.beforeCompletion();
135         }
136     }
137
138     /**
139      * Set the underlying JTA transaction to rollback-only.
140      */

141     private void setRollbackOnlyIfPossible() {
142         if (this.jtaTransaction != null) {
143             try {
144                 this.jtaTransaction.setRollbackOnly();
145             }
146             catch (UnsupportedOperationException JavaDoc ex) {
147                 // Probably Hibernate's WebSphereExtendedJTATransactionLookup pseudo JTA stuff...
148
logger.debug("JTA transaction handle does not support setRollbackOnly method - " +
149                         "relying on JTA provider to mark the transaction as rollback-only based on " +
150                         "the exception thrown from beforeCompletion", ex);
151             }
152             catch (Throwable JavaDoc ex) {
153                 logger.error("Could not set JTA transaction rollback-only", ex);
154             }
155         }
156         else {
157             logger.debug("No JTA transaction handle available and/or running on WebLogic - " +
158                         "relying on JTA provider to mark the transaction as rollback-only based on " +
159                         "the exception thrown from beforeCompletion");
160             }
161     }
162
163     /**
164      * JTA <code>afterCompletion</code> callback: invoked after commit/rollback.
165      * <p>Needs to invoke the Spring synchronization's <code>beforeCompletion</code>
166      * at this late stage in case of a rollback, since there is no corresponding
167      * callback with JTA.
168      * @see org.springframework.transaction.support.TransactionSynchronization#beforeCompletion
169      * @see org.springframework.transaction.support.TransactionSynchronization#afterCompletion
170      */

171     public void afterCompletion(int status) {
172         if (!this.beforeCompletionCalled) {
173             // beforeCompletion not called before (probably because of JTA rollback).
174
// Perform the cleanup here.
175
this.springSynchronization.beforeCompletion();
176         }
177         // Call afterCompletion with the appropriate status indication.
178
switch (status) {
179             case Status.STATUS_COMMITTED:
180                 this.springSynchronization.afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
181                 break;
182             case Status.STATUS_ROLLEDBACK:
183                 this.springSynchronization.afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK);
184                 break;
185             default:
186                 this.springSynchronization.afterCompletion(TransactionSynchronization.STATUS_UNKNOWN);
187         }
188     }
189
190 }
191
Popular Tags