KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > transaction > AbstractSynchronizationListener


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2005, Oracle. All rights reserved.
22
package oracle.toplink.essentials.transaction;
23
24 import oracle.toplink.essentials.internal.sessions.AbstractSession;
25 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
26 import oracle.toplink.essentials.exceptions.TransactionException;
27 import oracle.toplink.essentials.logging.*;
28 import oracle.toplink.essentials.sessions.SessionProfiler;
29
30 /**
31  * <p>
32  * <b>Purpose</b>: Abstract Synchronization Listener class
33  *
34  * <b>Description</b>: This abstract class is paired with the
35  * AbstractTransactionController class. It contains most of the implementation
36  * logic to handle callback notifications from an external transaction
37  * manager to ensure consistency between the global transaction and the
38  * TopLink unit of work. It does not assume any particular specification
39  * or interface, but can be called by any implementation subclass.
40  *
41  * @see AbstractTransactionController
42  */

43 public abstract class AbstractSynchronizationListener {
44
45     /**
46      * The external txn controller that is intimate with the transaction manager
47      * and knows how to do things like rolling back transactions, etc.
48      */

49     protected AbstractTransactionController controller;
50
51     /**
52      * The parent of the uow.
53      */

54     protected AbstractSession session;
55
56     /**
57      * The unit of work associated with the global txn that this listener is
58      * bound to.
59      */

60     protected UnitOfWorkImpl unitOfWork;
61
62     /**
63      * The global transaction object.
64      */

65     protected Object JavaDoc transaction;
66
67     /**
68      * INTERNAL:
69      */

70     public AbstractSynchronizationListener() {
71         super();
72     }
73
74     /**
75      * INTERNAL:
76      */

77     protected AbstractSynchronizationListener(UnitOfWorkImpl unitOfWork, AbstractSession session, Object JavaDoc transaction, AbstractTransactionController controller) {
78         this.session = session;
79         this.unitOfWork = unitOfWork;
80         this.transaction = transaction;
81         this.controller = controller;
82     }
83
84     /**
85      * INTERNAL:
86      * This method performs the logic that occurs at transaction
87      * completion time. This includes issuing the SQL, etc.
88      * This method executes within the transaction context of the caller of
89      * transaction.commit(), or in the case of container-managed transactions,
90      * in the context of the method for which the Container started the transaction.
91      */

92     public void beforeCompletion() {
93         UnitOfWorkImpl uow = getUnitOfWork();
94         try {
95             Object JavaDoc status = getTransactionController().getTransactionStatus();
96             getTransactionController().logTxStateTrace(uow, "TX_beforeCompletion", status);
97             //CR# 3452053
98
session.startOperationProfile(SessionProfiler.JtsBeforeCompletion);
99
100             // If the uow is not active then somebody somewhere messed up
101
if (!uow.isActive()) {
102                 throw TransactionException.inactiveUnitOfWork(uow);
103             }
104
105             // Bail out if we don't think we should actually issue the SQL
106
if (!getTransactionController().canIssueSQLToDatabase_impl(status)) {
107                 return;
108             }
109
110             // Must force concurrency mgrs active thread if in nested transaction
111
if (getSession().isInTransaction()) {
112                 getSession().getTransactionMutex().setActiveThread(Thread.currentThread());
113             }
114
115             // Send the SQL to the DB
116
uow.issueSQLbeforeCompletion();
117
118             // Fix up our merge state in the unit of work and the session
119
uow.setPendingMerge();
120
121         } catch (RuntimeException JavaDoc exception) {
122             // Something went wrong (probably while sending SQL to the database).
123
uow.log(new SessionLogEntry(uow, SessionLog.WARNING, SessionLog.TRANSACTION, exception));
124             // Handle the exception according to transaction manager requirements
125
handleException(exception);
126         } finally {
127             session.endOperationProfile(SessionProfiler.JtsBeforeCompletion);
128         }
129     }
130
131     /**
132      * INTERNAL:
133      * The method performs the logic that should be executed after the transaction
134      * has been completed. The status passed in indicates whether the transaction
135      * was committed or rolled back. This status flag may be different for different
136      * implementations.
137      * This method executes without a transaction context.
138      *
139      * @param status The status code of the transaction completion.
140      */

141     public void afterCompletion(Object JavaDoc status) {
142         UnitOfWorkImpl uow = getUnitOfWork();
143         try {
144             // Log the fact that we got invoked
145
getTransactionController().logTxStateTrace(uow, "TX_afterCompletion", status);
146             //Cr#3452053
147
session.startOperationProfile(SessionProfiler.JtsAfterCompletion);
148             // The uow should still be active even in rollback case
149
if (!uow.isActive()) {
150                 throw TransactionException.inactiveUnitOfWork(uow);
151             }
152
153             // Only do merge if txn was committed
154
if (getTransactionController().canMergeUnitOfWork_impl(status)) {
155                 uow.afterTransaction(true, true);// committed=true; externalTxn=true
156
if (uow.isMergePending()) {
157                     // uow in PENDING_MERGE state, merge clones
158
uow.mergeClonesAfterCompletion();
159                 }
160             } else {
161                 uow.afterTransaction(false, true);// committed=false; externalTxn=true
162
}
163         } catch (RuntimeException JavaDoc rtEx) {
164             // First log the exception so it gets seen
165
uow.log(new SessionLogEntry(uow, SessionLog.WARNING, SessionLog.TRANSACTION, rtEx));
166             // Rethrow it just for fun (app servers tend to ignore them at this stage)
167
throw rtEx;
168         } finally {
169             session.endOperationProfile(SessionProfiler.JtsAfterCompletion);
170         }
171
172         // Clean up by releasing the uow and client session
173
if (uow.shouldResumeUnitOfWorkOnTransactionCompletion() && getTransactionController().canMergeUnitOfWork_impl(status)){
174             uow.synchronizeAndResume();
175             uow.setSynchronized(false);
176         }else{
177             uow.release();
178             // Release the session explicitly
179
if (getSession().isClientSession()) {
180                 getSession().release();
181             }
182         }
183         getTransactionController().removeUnitOfWork(getTransaction());
184         setUnitOfWork(null);
185         setTransaction(null);
186         setSession(null);
187     }
188
189     /**
190      * INTERNAL:
191      * Do the appropriate thing for when an exception occurs during SQL issuance.
192      * The default thing to do is to simply mark the transaction to be rolled back,
193      * for those transaction managers that support this, and rethrow the exception.
194      * We hope that the exception will do the trick for those that do not allow
195      * marking rollback.
196      *
197      * This method may optionally be overridden by concrete subclass implementations.
198      * Different transaction manager vendors may have different reactions to exceptions
199      * that get signalled during the commit phase of synchronization.
200      */

201     public void handleException(RuntimeException JavaDoc exception) {
202         // Don't do this just yet, since some may not be able to handle it
203
// getTransactionController().markTransactionForRollback();
204
throw exception;
205     }
206
207     protected AbstractTransactionController getTransactionController() {
208         return controller;
209     }
210
211     protected void setTransactionController(AbstractTransactionController newController) {
212         controller = newController;
213     }
214
215     protected Object JavaDoc getTransaction() {
216         return transaction;
217     }
218
219     protected void setTransaction(Object JavaDoc transaction) {
220         this.transaction = transaction;
221     }
222
223     protected AbstractSession getSession() {
224         return session;
225     }
226
227     protected void setSession(AbstractSession session) {
228         this.session = session;
229     }
230
231     protected UnitOfWorkImpl getUnitOfWork() {
232         return unitOfWork;
233     }
234
235     protected void setUnitOfWork(UnitOfWorkImpl unitOfWork) {
236         this.unitOfWork = unitOfWork;
237     }
238 }
Popular Tags