~raginggoblin/infolog/infolog

« back to all changes in this revision

Viewing changes to InfologServer/lib/hibernate-distribution-3.3.2.GA/project/core/src/main/java/org/hibernate/transaction/JTATransaction.java

  • Committer: Raging Goblin
  • Date: 2013-11-16 16:51:32 UTC
  • Revision ID: raging_goblin-20131116165132-weujnptzc88uy4ah
Mavenized the project, now using shared project InfologSync

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Hibernate, Relational Persistence for Idiomatic Java
3
 
 *
4
 
 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
5
 
 * indicated by the @author tags or express copyright attribution
6
 
 * statements applied by the authors.  All third-party contributions are
7
 
 * distributed under license by Red Hat Middleware LLC.
8
 
 *
9
 
 * This copyrighted material is made available to anyone wishing to use, modify,
10
 
 * copy, or redistribute it subject to the terms and conditions of the GNU
11
 
 * Lesser General Public License, as published by the Free Software Foundation.
12
 
 *
13
 
 * This program is distributed in the hope that it will be useful,
14
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
 
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
16
 
 * for more details.
17
 
 *
18
 
 * You should have received a copy of the GNU Lesser General Public License
19
 
 * along with this distribution; if not, write to:
20
 
 * Free Software Foundation, Inc.
21
 
 * 51 Franklin Street, Fifth Floor
22
 
 * Boston, MA  02110-1301  USA
23
 
 *
24
 
 */
25
 
package org.hibernate.transaction;
26
 
 
27
 
import javax.transaction.Status;
28
 
import javax.transaction.Synchronization;
29
 
import javax.transaction.SystemException;
30
 
import javax.transaction.TransactionManager;
31
 
import javax.transaction.UserTransaction;
32
 
 
33
 
import org.slf4j.Logger;
34
 
import org.slf4j.LoggerFactory;
35
 
 
36
 
import org.hibernate.HibernateException;
37
 
import org.hibernate.Transaction;
38
 
import org.hibernate.TransactionException;
39
 
import org.hibernate.jdbc.JDBCContext;
40
 
import org.hibernate.util.JTAHelper;
41
 
 
42
 
/**
43
 
 * {@link Transaction} implementation based on transaction management through
44
 
 * a JTA {@link UserTransaction}.  Similar to {@link CMTTransaction}, except
45
 
 * here we are actually managing the transactions through the Hibernate
46
 
 * transaction mechanism.
47
 
 *
48
 
 * @author Gavin King
49
 
 * @author Steve Ebersole
50
 
 * @author Les Hazlewood
51
 
 */
52
 
public class JTATransaction implements Transaction {
53
 
 
54
 
        private static final Logger log = LoggerFactory.getLogger( JTATransaction.class );
55
 
 
56
 
        private final JDBCContext jdbcContext;
57
 
        private final TransactionFactory.Context transactionContext;
58
 
 
59
 
        private UserTransaction userTransaction;
60
 
        private boolean newTransaction;
61
 
        private boolean begun;
62
 
        private boolean commitFailed;
63
 
        private boolean commitSucceeded;
64
 
        private boolean callback;
65
 
 
66
 
        public JTATransaction(
67
 
                        UserTransaction userTransaction,
68
 
                        JDBCContext jdbcContext,
69
 
                        TransactionFactory.Context transactionContext) {
70
 
                this.jdbcContext = jdbcContext;
71
 
                this.transactionContext = transactionContext;
72
 
                this.userTransaction = userTransaction;
73
 
        }
74
 
 
75
 
        /**
76
 
         * {@inheritDoc}
77
 
         */
78
 
        public void begin() throws HibernateException {
79
 
                if ( begun ) {
80
 
                        return;
81
 
                }
82
 
                if ( commitFailed ) {
83
 
                        throw new TransactionException( "cannot re-start transaction after failed commit" );
84
 
                }
85
 
 
86
 
                log.debug( "begin" );
87
 
 
88
 
                try {
89
 
                        newTransaction = userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION;
90
 
                        if ( newTransaction ) {
91
 
                                userTransaction.begin();
92
 
                                log.debug( "Began a new JTA transaction" );
93
 
                        }
94
 
                }
95
 
                catch ( Exception e ) {
96
 
                        log.error( "JTA transaction begin failed", e );
97
 
                        throw new TransactionException( "JTA transaction begin failed", e );
98
 
                }
99
 
 
100
 
                /*if (newTransaction) {
101
 
                        // don't need a synchronization since we are committing
102
 
                        // or rolling back the transaction ourselves - assuming
103
 
                        // that we do no work in beforeTransactionCompletion()
104
 
                        synchronization = false;
105
 
                }*/
106
 
 
107
 
                boolean synchronization = jdbcContext.registerSynchronizationIfPossible();
108
 
 
109
 
                if ( !newTransaction && !synchronization ) {
110
 
                        log.warn( "You should set hibernate.transaction.manager_lookup_class if cache is enabled" );
111
 
                }
112
 
 
113
 
                if ( !synchronization ) {
114
 
                        //if we could not register a synchronization,
115
 
                        //do the before/after completion callbacks
116
 
                        //ourself (but we need to let jdbcContext
117
 
                        //know that this is what we are going to
118
 
                        //do, so it doesn't keep trying to register
119
 
                        //synchronizations)
120
 
                        callback = jdbcContext.registerCallbackIfNecessary();
121
 
                }
122
 
 
123
 
                begun = true;
124
 
                commitSucceeded = false;
125
 
 
126
 
                jdbcContext.afterTransactionBegin( this );
127
 
        }
128
 
 
129
 
        /**
130
 
         * {@inheritDoc}
131
 
         */
132
 
        public void commit() throws HibernateException {
133
 
                if ( !begun ) {
134
 
                        throw new TransactionException( "Transaction not successfully started" );
135
 
                }
136
 
 
137
 
                log.debug( "commit" );
138
 
 
139
 
                boolean flush = !transactionContext.isFlushModeNever()
140
 
                                && ( callback || !transactionContext.isFlushBeforeCompletionEnabled() );
141
 
 
142
 
                if ( flush ) {
143
 
                        transactionContext.managedFlush(); //if an exception occurs during flush, user must call rollback()
144
 
                }
145
 
 
146
 
                if ( callback && newTransaction ) {
147
 
                        jdbcContext.beforeTransactionCompletion( this );
148
 
                }
149
 
 
150
 
                closeIfRequired();
151
 
 
152
 
                if ( newTransaction ) {
153
 
                        try {
154
 
                                userTransaction.commit();
155
 
                                commitSucceeded = true;
156
 
                                log.debug( "Committed JTA UserTransaction" );
157
 
                        }
158
 
                        catch ( Exception e ) {
159
 
                                commitFailed = true; // so the transaction is already rolled back, by JTA spec
160
 
                                log.error( "JTA commit failed", e );
161
 
                                throw new TransactionException( "JTA commit failed: ", e );
162
 
                        }
163
 
                        finally {
164
 
                                afterCommitRollback();
165
 
                        }
166
 
                }
167
 
                else {
168
 
                        // this one only really needed for badly-behaved applications!
169
 
                        // (if the TransactionManager has a Sychronization registered,
170
 
                        // its a noop)
171
 
                        // (actually we do need it for downgrading locks)
172
 
                        afterCommitRollback();
173
 
                }
174
 
 
175
 
        }
176
 
 
177
 
        /**
178
 
         * {@inheritDoc}
179
 
         */
180
 
        public void rollback() throws HibernateException {
181
 
                if ( !begun && !commitFailed ) {
182
 
                        throw new TransactionException( "Transaction not successfully started" );
183
 
                }
184
 
 
185
 
                log.debug( "rollback" );
186
 
 
187
 
                try {
188
 
                        closeIfRequired();
189
 
                }
190
 
                catch ( Exception e ) {
191
 
                        // swallow it, and continue to roll back JTA transaction
192
 
                        log.error( "could not close session during rollback", e );
193
 
                }
194
 
 
195
 
                try {
196
 
                        if ( newTransaction ) {
197
 
                                if ( !commitFailed ) {
198
 
                                        userTransaction.rollback();
199
 
                                        log.debug( "Rolled back JTA UserTransaction" );
200
 
                                }
201
 
                        }
202
 
                        else {
203
 
                                userTransaction.setRollbackOnly();
204
 
                                log.debug( "set JTA UserTransaction to rollback only" );
205
 
                        }
206
 
                }
207
 
                catch ( Exception e ) {
208
 
                        log.error( "JTA rollback failed", e );
209
 
                        throw new TransactionException( "JTA rollback failed", e );
210
 
                }
211
 
                finally {
212
 
                        afterCommitRollback();
213
 
                }
214
 
        }
215
 
 
216
 
        private static final int NULL = Integer.MIN_VALUE;
217
 
 
218
 
        private void afterCommitRollback() throws TransactionException {
219
 
 
220
 
                begun = false;
221
 
                // this method is a noop if there is a Synchronization!
222
 
                if ( callback ) {
223
 
                        if ( !newTransaction ) {
224
 
                                log.warn( "You should set hibernate.transaction.manager_lookup_class if cache is enabled" );
225
 
                        }
226
 
                        int status = NULL;
227
 
                        try {
228
 
                                status = userTransaction.getStatus();
229
 
                        }
230
 
                        catch ( Exception e ) {
231
 
                                log.error( "Could not determine transaction status after commit", e );
232
 
                                throw new TransactionException( "Could not determine transaction status after commit", e );
233
 
                        }
234
 
                        finally {
235
 
                                jdbcContext.afterTransactionCompletion( status == Status.STATUS_COMMITTED, this );
236
 
                        }
237
 
                }
238
 
        }
239
 
 
240
 
        /**
241
 
         * {@inheritDoc}
242
 
         */
243
 
        public boolean wasRolledBack() throws TransactionException {
244
 
                final int status;
245
 
                try {
246
 
                        status = userTransaction.getStatus();
247
 
                }
248
 
                catch ( SystemException se ) {
249
 
                        log.error( "Could not determine transaction status", se );
250
 
                        throw new TransactionException( "Could not determine transaction status", se );
251
 
                }
252
 
                if ( status == Status.STATUS_UNKNOWN ) {
253
 
                        throw new TransactionException( "Could not determine transaction status" );
254
 
                }
255
 
                else {
256
 
                        return JTAHelper.isRollback( status );
257
 
                }
258
 
        }
259
 
 
260
 
        /**
261
 
         * {@inheritDoc}
262
 
         */
263
 
        public boolean wasCommitted() throws TransactionException {
264
 
                final int status;
265
 
                try {
266
 
                        status = userTransaction.getStatus();
267
 
                }
268
 
                catch ( SystemException se ) {
269
 
                        log.error( "Could not determine transaction status", se );
270
 
                        throw new TransactionException( "Could not determine transaction status: ", se );
271
 
                }
272
 
                if ( status == Status.STATUS_UNKNOWN ) {
273
 
                        throw new TransactionException( "Could not determine transaction status" );
274
 
                }
275
 
                else {
276
 
                        return status == Status.STATUS_COMMITTED;
277
 
                }
278
 
        }
279
 
 
280
 
        /**
281
 
         * {@inheritDoc}
282
 
         */
283
 
        public boolean isActive() throws TransactionException {
284
 
                if ( !begun || commitFailed || commitSucceeded ) {
285
 
                        return false;
286
 
                }
287
 
 
288
 
                final int status;
289
 
                try {
290
 
                        status = userTransaction.getStatus();
291
 
                }
292
 
                catch ( SystemException se ) {
293
 
                        log.error( "Could not determine transaction status", se );
294
 
                        throw new TransactionException( "Could not determine transaction status: ", se );
295
 
                }
296
 
                if ( status == Status.STATUS_UNKNOWN ) {
297
 
                        throw new TransactionException( "Could not determine transaction status" );
298
 
                }
299
 
                else {
300
 
                        return status == Status.STATUS_ACTIVE;
301
 
                }
302
 
        }
303
 
 
304
 
        /**
305
 
         * {@inheritDoc}
306
 
         */
307
 
        public void registerSynchronization(Synchronization sync) throws HibernateException {
308
 
                if ( getTransactionManager() == null ) {
309
 
                        throw new IllegalStateException( "JTA TransactionManager not available" );
310
 
                }
311
 
                else {
312
 
                        try {
313
 
                                getTransactionManager().getTransaction().registerSynchronization( sync );
314
 
                        }
315
 
                        catch ( Exception e ) {
316
 
                                throw new TransactionException( "could not register synchronization", e );
317
 
                        }
318
 
                }
319
 
        }
320
 
 
321
 
        /**
322
 
         * Getter for property 'transactionManager'.
323
 
         *
324
 
         * @return Value for property 'transactionManager'.
325
 
         */
326
 
        private TransactionManager getTransactionManager() {
327
 
                return transactionContext.getFactory().getTransactionManager();
328
 
        }
329
 
 
330
 
        private void closeIfRequired() throws HibernateException {
331
 
                boolean close = callback &&
332
 
                                transactionContext.shouldAutoClose() &&
333
 
                                !transactionContext.isClosed();
334
 
                if ( close ) {
335
 
                        transactionContext.managedClose();
336
 
                }
337
 
        }
338
 
 
339
 
        /**
340
 
         * {@inheritDoc}
341
 
         */
342
 
        public void setTimeout(int seconds) {
343
 
                try {
344
 
                        userTransaction.setTransactionTimeout( seconds );
345
 
                }
346
 
                catch ( SystemException se ) {
347
 
                        throw new TransactionException( "could not set transaction timeout", se );
348
 
                }
349
 
        }
350
 
 
351
 
        /**
352
 
         * Getter for property 'userTransaction'.
353
 
         *
354
 
         * @return Value for property 'userTransaction'.
355
 
         */
356
 
        protected UserTransaction getUserTransaction() {
357
 
                return userTransaction;
358
 
        }
359
 
}