KickJava   Java API By Example, From Geeks To Geeks.

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


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 javax.transaction.Status JavaDoc;
19 import javax.transaction.Synchronization JavaDoc;
20
21 import org.apache.ojb.broker.PersistenceBroker;
22 import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
23 import org.apache.ojb.broker.util.logging.Logger;
24 import org.apache.ojb.broker.util.logging.LoggerFactory;
25 import org.odmg.LockNotGrantedException;
26 import org.odmg.ODMGRuntimeException;
27 import org.odmg.TransactionAbortedException;
28
29 /**
30  * Implementation for use in managed environments.
31  *
32  * @author <a HREF="mailto:mattbaird@yahoo.com">Matthew Baird</a>
33  * @version $Id: J2EETransactionImpl.java,v 1.25.2.7 2005/12/21 22:29:21 tomdz Exp $
34  */

35 public class J2EETransactionImpl extends TransactionImpl implements Synchronization JavaDoc
36 {
37     private Logger log = LoggerFactory.getLogger(J2EETransactionImpl.class);
38     private boolean isInExternTransaction;
39
40     /**
41      * beforeCompletion is being called twice in JBoss, so this
42      * isPrepared flag prevents code from executing twice.
43      * todo: find out why it's being called twice and fix it.
44      */

45     private boolean beforeCompletionCall = false;
46     private boolean afterCompletionCall = false;
47
48     public J2EETransactionImpl(ImplementationImpl implementation)
49     {
50         super(implementation);
51         isInExternTransaction = false;
52     }
53
54     public void setInExternTransaction(boolean mode)
55     {
56         isInExternTransaction = mode;
57         }
58
59     public boolean isInExternTransaction()
60     {
61         return isInExternTransaction;
62     }
63
64     public void join()
65     {
66             throw new UnsupportedOperationException JavaDoc("Not supported in managed enviroment");
67         }
68
69     public void leave()
70     {
71             throw new UnsupportedOperationException JavaDoc("Not supported in managed enviroment");
72         }
73
74     public void checkpoint()
75     {
76             throw new UnsupportedOperationException JavaDoc("Not supported in managed enviroment");
77         }
78
79     /**
80      * FOR internal use. This method was called after the external transaction was completed.
81      *
82      * @see javax.transaction.Synchronization
83      */

84     public void afterCompletion(int status)
85     {
86         if(afterCompletionCall) return;
87
88         log.info("Method afterCompletion was called");
89         try
90         {
91             switch(status)
92             {
93                 case Status.STATUS_COMMITTED:
94                     if(log.isDebugEnabled())
95                     {
96                         log.debug("Method afterCompletion: Do commit internal odmg-tx, status of JTA-tx is " + TxUtil.getStatusString(status));
97                     }
98                     commit();
99                     break;
100                 default:
101                     log.error("Method afterCompletion: Do abort call on internal odmg-tx, status of JTA-tx is " + TxUtil.getStatusString(status));
102                     abort();
103             }
104         }
105         finally
106         {
107             afterCompletionCall = true;
108             log.info("Method afterCompletion finished");
109         }
110     }
111
112     /**
113      * FOR internal use. This method was called before the external transaction was completed.
114      *
115      * This method was called by the JTA-TxManager before the JTA-tx prepare call. Within this method
116      * we prepare odmg for commit and pass all modified persistent objects to DB and release/close the used
117      * connection. We have to close the connection in this method, because the TxManager does prepare for commit
118      * after this method and all used DataSource-connections have to be closed before.
119      *
120      * @see javax.transaction.Synchronization
121      */

122     public void beforeCompletion()
123     {
124         // avoid redundant calls
125
if(beforeCompletionCall) return;
126
127         log.info("Method beforeCompletion was called");
128         int status = Status.STATUS_UNKNOWN;
129         try
130         {
131             JTATxManager mgr = (JTATxManager) getImplementation().getTxManager();
132             status = mgr.getJTATransaction().getStatus();
133             // ensure proper work, check all possible status
134
// normally only check for 'STATUS_MARKED_ROLLBACK' is necessary
135
if(status == Status.STATUS_MARKED_ROLLBACK
136                     || status == Status.STATUS_ROLLEDBACK
137                     || status == Status.STATUS_ROLLING_BACK
138                     || status == Status.STATUS_UNKNOWN
139                     || status == Status.STATUS_NO_TRANSACTION)
140             {
141                 log.error("Synchronization#beforeCompletion: Can't prepare for commit, because tx status was "
142                         + TxUtil.getStatusString(status) + ". Do internal cleanup only.");
143             }
144             else
145             {
146                 if(log.isDebugEnabled())
147                 {
148                     log.debug("Synchronization#beforeCompletion: Prepare for commit");
149                 }
150                 // write objects to database
151
prepareCommit();
152             }
153         }
154         catch(Exception JavaDoc e)
155         {
156             log.error("Synchronization#beforeCompletion: Error while prepare for commit", e);
157             if(e instanceof LockNotGrantedException)
158             {
159                 throw (LockNotGrantedException) e;
160             }
161             else if(e instanceof TransactionAbortedException)
162             {
163                 throw (TransactionAbortedException) e;
164             }
165             else if(e instanceof ODMGRuntimeException)
166             {
167                 throw (ODMGRuntimeException) e;
168             }
169             else
170             {
171                 throw new ODMGRuntimeException("Method beforeCompletion() fails, status of JTA-tx was "
172                         + TxUtil.getStatusString(status) + ", message: " + e.getMessage());
173             }
174
175         }
176         finally
177         {
178             beforeCompletionCall = true;
179             setInExternTransaction(false);
180             internalCleanup();
181         }
182     }
183
184     /**
185      * In managed environment do internal close the used connection
186      */

187     private void internalCleanup()
188     {
189         if(hasBroker())
190         {
191             PersistenceBroker broker = getBroker();
192             if(log.isDebugEnabled())
193             {
194                 log.debug("Do internal cleanup and close the internal used connection without" +
195                         " closing the used broker");
196             }
197             ConnectionManagerIF cm = broker.serviceConnectionManager();
198             if(cm.isInLocalTransaction())
199             {
200                 /*
201                 arminw:
202                 in managed environment this call will be ignored because, the JTA transaction
203                 manager control the connection status. But to make connectionManager happy we
204                 have to complete the "local tx" of the connectionManager before release the
205                 connection
206                 */

207                 cm.localCommit();
208             }
209             cm.releaseConnection();
210         }
211     }
212
213     public void commit()
214     {
215         try
216         {
217             // prepare for commit was done before on 'beforeCompleation' call
218
if(log.isDebugEnabled()) log.debug("Commit transaction " + this + ", commit on broker " + broker);
219             if(hasBroker())
220             {
221                 getBroker().commitTransaction();
222                 doClose();
223             }
224             setStatus(Status.STATUS_COMMITTED);
225             // Now, we notify everything the commit is done.
226
performTransactionAwareAfterCommit();
227         }
228         catch(Exception JavaDoc ex)
229         {
230             // We should not reach this block
231
log.error("Unexpected error while do commit on used PB-Instance and close resources", ex);
232             abort();
233         }
234     }
235
236     public void abort()
237     {
238         if(getStatus() == Status.STATUS_ROLLEDBACK) return;
239
240         try
241         {
242             try
243             {
244                 doAbort();
245             }
246             catch(Exception JavaDoc ignore)
247             {
248                 log.error("Failure while do abort call", ignore);
249             }
250
251             getImplementation().getTxManager().abortExternalTx(this);
252
253             try
254             {
255                 doClose();
256             }
257             catch(Exception JavaDoc e)
258             {
259                 log.error("Failure while do abort call", e);
260             }
261             setStatus(Status.STATUS_ROLLEDBACK);
262         }
263         finally
264         {
265             setInExternTransaction(false);
266         }
267     }
268 }
269
Popular Tags