KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > odmg > JTATxManager


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

17
18 import org.apache.ojb.broker.OJBRuntimeException;
19 import org.apache.ojb.broker.util.configuration.Configuration;
20 import org.apache.ojb.broker.util.logging.Logger;
21 import org.apache.ojb.broker.util.logging.LoggerFactory;
22 import org.apache.ojb.broker.transaction.tm.TransactionManagerFactoryException;
23 import org.apache.ojb.broker.transaction.tm.TransactionManagerFactoryFactory;
24 import org.apache.commons.lang.SystemUtils;
25 import org.odmg.TransactionNotInProgressException;
26
27 import javax.transaction.Status JavaDoc;
28 import javax.transaction.SystemException JavaDoc;
29 import javax.transaction.Transaction JavaDoc;
30 import javax.transaction.TransactionManager JavaDoc;
31 import java.lang.ref.WeakReference JavaDoc;
32
33 /**
34  * @author <a HREF="mailto:mattbaird@yahoo.com">Matthew Baird</a>
35  *
36  * In an app server environment, where we have a transaction manager, we
37  * use the transactionmanager and it's associated JTA transaction to associate
38  * with the ODMG transaction. So the key is retrieved by calling getTransaction
39  * on the transactionManager
40  */

41 public class JTATxManager implements OJBTxManager
42 {
43     private Logger log = LoggerFactory.getLogger(JTATxManager.class);
44     private static ThreadLocal JavaDoc txRepository = new ThreadLocal JavaDoc();
45
46     /**
47      * Remove the ODMG transaction from the transaction buffer
48      * ODMG transactions are associated with JTA transactions via a map
49      */

50     public void deregisterTx(Object JavaDoc transaction)
51     {
52 // TxBuffer buf = (TxBuffer) txRepository.get();
53
// if (buf != null)
54
// {
55
// buf.setInternTx(null);
56
// }
57
txRepository.set(null);
58     }
59
60     public void registerTx(TransactionImpl odmgTrans)
61     {
62         if (log.isDebugEnabled()) log.debug("registerSynchronization was called");
63         Transaction JavaDoc transaction = null;
64         try
65         {
66             transaction = getJTATransaction();
67         }
68         catch (SystemException JavaDoc e)
69         {
70             log.error("Obtain current transaction from container failed", e);
71         }
72         if (transaction == null)
73         {
74             log.error("Cannot get the external transaction from the external TM");
75             throw new TransactionNotInProgressException("No external transaction found");
76         }
77         if (log.isDebugEnabled())
78         {
79             log.debug("registerSynchronization was called with parameters"
80                     + SystemUtils.LINE_SEPARATOR +"J2EETransactionImpl: " + odmgTrans
81                     + SystemUtils.LINE_SEPARATOR + "Transaction: " + transaction);
82         }
83         registerSynchronization(odmgTrans, transaction);
84     }
85
86     /**
87      * Do synchronization of the given J2EE ODMG Transaction
88      */

89     private void registerSynchronization(TransactionImpl odmgTrans, Transaction JavaDoc transaction)
90     {
91         // todo only need for development
92
if (odmgTrans == null || transaction == null)
93         {
94             log.error("One of the given parameters was null --> cannot do synchronization!" +
95                     " omdg transaction was null: " + (odmgTrans == null) +
96                     ", external transaction was null: " + (transaction == null));
97             return;
98         }
99
100         int status = -1; // default status.
101
try
102         {
103             status = transaction.getStatus();
104             if (status != Status.STATUS_ACTIVE)
105             {
106                 throw new OJBRuntimeException(
107                         "Transaction synchronization failed - wrong status of external container tx: " +
108                         getStatusString(status));
109             }
110         }
111         catch (SystemException JavaDoc e)
112         {
113             throw new OJBRuntimeException("Can't read status of external tx", e);
114         }
115
116         try
117         {
118             //Sequence of the following method calls is significant
119
// 1. register the synchronization with the ODMG notion of a transaction.
120
transaction.registerSynchronization((J2EETransactionImpl) odmgTrans);
121             // 2. mark the ODMG transaction as being in a JTA Transaction
122
// Associate external transaction with the odmg transaction.
123
txRepository.set(new TxBuffer(odmgTrans, transaction));
124         }
125         catch (Exception JavaDoc e)
126         {
127             log.error("Cannot associate PersistenceBroker with running Transaction", e);
128             throw new OJBRuntimeException(
129                     "Transaction synchronization failed - wrong status of external container tx", e);
130         }
131     }
132
133     private static String JavaDoc getStatusString(int status)
134     {
135         switch (status)
136         {
137             case Status.STATUS_ACTIVE:
138                 return "STATUS_ACTIVE";
139             case Status.STATUS_COMMITTED:
140                 return "STATUS_COMMITTED";
141             case Status.STATUS_COMMITTING:
142                 return "STATUS_COMMITTING";
143             case Status.STATUS_MARKED_ROLLBACK:
144                 return "STATUS_MARKED_ROLLBACK";
145             case Status.STATUS_NO_TRANSACTION:
146                 return "STATUS_NO_TRANSACTION";
147             case Status.STATUS_PREPARED:
148                 return "STATUS_PREPARED";
149             case Status.STATUS_PREPARING:
150                 return "STATUS_PREPARING";
151             case Status.STATUS_ROLLEDBACK:
152                 return "STATUS_ROLLEDBACK";
153             case Status.STATUS_ROLLING_BACK:
154                 return "STATUS_ROLLING_BACK";
155             case Status.STATUS_UNKNOWN:
156                 return "STATUS_UNKNOWN";
157             default:
158                 return "NO STATUS FOUND";
159         }
160     }
161
162     /**
163      * Return the TransactionManager of the external app
164      */

165     private TransactionManager JavaDoc getTransactionManager()
166     {
167         TransactionManager JavaDoc retval = null;
168         try
169         {
170             if (log.isDebugEnabled()) log.debug("getTransactionManager called");
171             retval = TransactionManagerFactoryFactory.instance().getTransactionManager();
172         }
173         catch (TransactionManagerFactoryException e)
174         {
175             log.warn("Exception trying to obtain TransactionManager from Factory", e);
176             e.printStackTrace();
177         }
178         return retval;
179     }
180
181     public Transaction JavaDoc getJTATransaction() throws SystemException JavaDoc
182     {
183         if (log.isDebugEnabled()) log.debug("getTransaction called");
184         if (getTransactionManager() == null)
185         {
186             log.warn("TransactionManager was null");
187             return null;
188         }
189         return getTransactionManager().getTransaction();
190     }
191
192     /**
193      * Returns the current transaction based on the JTA Transaction.
194      * @throws org.odmg.TransactionNotInProgressException if no transaction was found.
195      */

196     public TransactionImpl getCurrentTransaction()
197     {
198         TransactionImpl retval = getTransaction();
199         if (null == retval)
200         {
201             throw new TransactionNotInProgressException(
202                     "Calling method needed transaction, but no transaction found via TransactionManager");
203         }
204         return retval;
205     }
206
207     /**
208      * Returns the current transaction based on the JTA Transaction or <code>null</code>
209      * if no transaction was found.
210      */

211     public TransactionImpl getTransaction()
212     {
213         TxBuffer buf = (TxBuffer) txRepository.get();
214         return buf != null ? buf.getInternTx() : null;
215     }
216
217     /**
218      * Abort an active extern transaction associated with the given PB.
219      */

220     public void abortExternalTx(TransactionImpl odmgTrans)
221     {
222         if (log.isDebugEnabled()) log.debug("abortExternTransaction was called");
223         if (odmgTrans == null) return;
224         TxBuffer buf = (TxBuffer) txRepository.get();
225         Transaction JavaDoc extTx = buf != null ? buf.getExternTx() : null;
226         try
227         {
228             if (extTx != null && extTx.getStatus() == Status.STATUS_ACTIVE)
229             {
230                 if(log.isDebugEnabled())
231                 {
232                     log.debug("Set extern transaction to rollback");
233                 }
234                 extTx.setRollbackOnly();
235             }
236         }
237         catch (Exception JavaDoc ignore)
238         {
239         }
240         txRepository.set(null);
241     }
242
243     public void configure(Configuration config)
244     {
245         /**
246          * no-op
247          */

248     }
249
250
251     //************************************************************************
252
// inner class
253
//************************************************************************
254
private static final class TxBuffer
255     {
256         private WeakReference JavaDoc externTx = null;
257         private WeakReference JavaDoc internTx = null;
258
259         public TxBuffer()
260         {
261         }
262
263         /*
264         arminw:
265         use WeakReference to make sure that closed Transaction objects can be
266         immediately reclaimed by the garbage collector.
267         */

268
269         public TxBuffer(TransactionImpl internTx, Transaction JavaDoc externTx)
270         {
271             this.internTx = new WeakReference JavaDoc(internTx);
272             this.externTx = new WeakReference JavaDoc(externTx);
273         }
274
275         public Transaction JavaDoc getExternTx()
276         {
277             return (Transaction JavaDoc) externTx.get();
278         }
279
280         public void setExternTx(Transaction JavaDoc externTx)
281         {
282             this.externTx = new WeakReference JavaDoc(externTx);
283         }
284
285         public TransactionImpl getInternTx()
286         {
287             return (TransactionImpl) internTx.get();
288         }
289
290         public void setInternTx(TransactionImpl internTx)
291         {
292             this.internTx = new WeakReference JavaDoc(internTx);
293         }
294     }
295 }
296
Popular Tags