KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > orm > jdo > JdoTransactionManager


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.orm.jdo;
18
19 import javax.jdo.JDOException;
20 import javax.jdo.PersistenceManager;
21 import javax.jdo.PersistenceManagerFactory;
22 import javax.jdo.Transaction;
23 import javax.sql.DataSource JavaDoc;
24
25 import org.springframework.beans.factory.InitializingBean;
26 import org.springframework.dao.DataAccessException;
27 import org.springframework.jdbc.datasource.ConnectionHandle;
28 import org.springframework.jdbc.datasource.ConnectionHolder;
29 import org.springframework.jdbc.datasource.JdbcTransactionObjectSupport;
30 import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
31 import org.springframework.transaction.CannotCreateTransactionException;
32 import org.springframework.transaction.IllegalTransactionStateException;
33 import org.springframework.transaction.TransactionDefinition;
34 import org.springframework.transaction.TransactionException;
35 import org.springframework.transaction.TransactionSystemException;
36 import org.springframework.transaction.support.AbstractPlatformTransactionManager;
37 import org.springframework.transaction.support.DefaultTransactionStatus;
38 import org.springframework.transaction.support.ResourceTransactionManager;
39 import org.springframework.transaction.support.TransactionSynchronizationManager;
40
41 /**
42  * {@link org.springframework.transaction.PlatformTransactionManager} implementation
43  * for a single JDO {@link javax.jdo.PersistenceManagerFactory}. Binds a JDO
44  * PersistenceManager from the specified factory to the thread, potentially allowing
45  * for one thread-bound PersistenceManager per factory.
46  * {@link PersistenceManagerFactoryUtils} and {@link JdoTemplate} are aware of
47  * thread-bound persistence managers and participate in such transactions automatically.
48  * Using either of those (or going through a {@link TransactionAwarePersistenceManagerFactoryProxy}
49  * is required for JDO access code supporting this transaction management mechanism.
50  *
51  * <p>This transaction manager is appropriate for applications that use a single
52  * JDO PersistenceManagerFactory for transactional data access. JTA (usually through
53  * {@link org.springframework.transaction.jta.JtaTransactionManager}) is necessary
54  * for accessing multiple transactional resources within the same transaction.
55  * Note that you need to configure your JDO provider accordingly in order to make
56  * it participate in JTA transactions.
57  *
58  * <p>This transaction manager also supports direct DataSource access within a
59  * transaction (i.e. plain JDBC code working with the same DataSource).
60  * This allows for mixing services which access JDO and services which use plain
61  * JDBC (without being aware of JDO)! Application code needs to stick to the
62  * same simple Connection lookup pattern as with
63  * {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
64  * (i.e. {@link org.springframework.jdbc.datasource.DataSourceUtils#getConnection}
65  * or going through a
66  * {@link org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy}).
67  *
68  * <p>Note: To be able to register a DataSource's Connection for plain JDBC code,
69  * this instance needs to be aware of the DataSource ({@link #setDataSource}).
70  * The given DataSource should obviously match the one used by the given
71  * PersistenceManagerFactory. This transaction manager will autodetect the DataSource
72  * that acts as "connectionFactory" of the PersistenceManagerFactory, so you usually
73  * don't need to explicitly specify the "dataSource" property.
74  *
75  * <p>On JDBC 3.0, this transaction manager supports nested transactions via JDBC 3.0
76  * Savepoints. The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"}
77  * flag defaults to "false", though, as nested transactions will just apply to the
78  * JDBC Connection, not to the JDO PersistenceManager and its cached objects.
79  * You can manually set the flag to "true" if you want to use nested transactions
80  * for JDBC access code which participates in JDO transactions (provided that your
81  * JDBC driver supports Savepoints). <i>Note that JDO itself does not support
82  * nested transactions! Hence, do not expect JDO access code to semantically
83  * participate in a nested transaction.</i>
84  *
85  * @author Juergen Hoeller
86  * @since 03.06.2003
87  * @see #setPersistenceManagerFactory
88  * @see #setDataSource
89  * @see javax.jdo.PersistenceManagerFactory#getConnectionFactory
90  * @see LocalPersistenceManagerFactoryBean
91  * @see PersistenceManagerFactoryUtils#getPersistenceManager
92  * @see PersistenceManagerFactoryUtils#releasePersistenceManager
93  * @see JdoTemplate
94  * @see TransactionAwarePersistenceManagerFactoryProxy
95  * @see org.springframework.jdbc.datasource.DataSourceUtils#getConnection
96  * @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
97  * @see org.springframework.jdbc.core.JdbcTemplate
98  * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
99  * @see org.springframework.transaction.jta.JtaTransactionManager
100  */

101 public class JdoTransactionManager extends AbstractPlatformTransactionManager
102         implements ResourceTransactionManager, InitializingBean {
103
104     private static boolean jdoSetRollbackOnlyAvailable;
105
106     static {
107         // Determine whether the JDO 2.0 Transaction.setRollbackOnly method
108
// is available, for use in this JdoTransactionManager.
109
try {
110             Transaction.class.getMethod("setRollbackOnly", new Class JavaDoc[0]);
111             jdoSetRollbackOnlyAvailable = true;
112         }
113         catch (NoSuchMethodException JavaDoc ex) {
114             jdoSetRollbackOnlyAvailable = false;
115         }
116     }
117
118
119     private PersistenceManagerFactory persistenceManagerFactory;
120
121     private DataSource JavaDoc dataSource;
122
123     private boolean autodetectDataSource = true;
124
125     private JdoDialect jdoDialect;
126
127
128     /**
129      * Create a new JdoTransactionManager instance.
130      * A PersistenceManagerFactory has to be set to be able to use it.
131      * @see #setPersistenceManagerFactory
132      */

133     public JdoTransactionManager() {
134     }
135
136     /**
137      * Create a new JdoTransactionManager instance.
138      * @param pmf PersistenceManagerFactory to manage transactions for
139      */

140     public JdoTransactionManager(PersistenceManagerFactory pmf) {
141         this.persistenceManagerFactory = pmf;
142         afterPropertiesSet();
143     }
144
145     /**
146      * Set the PersistenceManagerFactory that this instance should manage transactions for.
147      * <p>The PersistenceManagerFactory specified here should be the target
148      * PersistenceManagerFactory to manage transactions for, not a
149      * TransactionAwarePersistenceManagerFactoryProxy. Only data access
150      * code may work with TransactionAwarePersistenceManagerFactoryProxy, while the
151      * transaction manager needs to work on the underlying target PersistenceManagerFactory.
152      * @see TransactionAwarePersistenceManagerFactoryProxy
153      */

154     public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
155         this.persistenceManagerFactory = pmf;
156     }
157
158     /**
159      * Return the PersistenceManagerFactory that this instance should manage transactions for.
160      */

161     public PersistenceManagerFactory getPersistenceManagerFactory() {
162         return this.persistenceManagerFactory;
163     }
164
165     /**
166      * Set the JDBC DataSource that this instance should manage transactions for.
167    * The DataSource should match the one used by the JDO PersistenceManagerFactory:
168      * for example, you could specify the same JNDI DataSource for both.
169      * <p>If the PersistenceManagerFactory uses a DataSource as connection factory,
170      * the DataSource will be autodetected: You can still explictly specify the
171      * DataSource, but you don't need to in this case.
172      * <p>A transactional JDBC Connection for this DataSource will be provided to
173      * application code accessing this DataSource directly via DataSourceUtils
174      * or JdbcTemplate. The Connection will be taken from the JDO PersistenceManager.
175      * <p>Note that you need to use a JDO dialect for a specific JDO provider to
176      * allow for exposing JDO transactions as JDBC transactions.
177      * <p>The DataSource specified here should be the target DataSource to manage
178      * transactions for, not a TransactionAwareDataSourceProxy. Only data access
179      * code may work with TransactionAwareDataSourceProxy, while the transaction
180      * manager needs to work on the underlying target DataSource. If there's
181      * nevertheless a TransactionAwareDataSourceProxy passed in, it will be
182      * unwrapped to extract its target DataSource.
183      * @see #setAutodetectDataSource
184      * @see #setJdoDialect
185      * @see javax.jdo.PersistenceManagerFactory#getConnectionFactory
186      * @see org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
187      * @see org.springframework.jdbc.datasource.DataSourceUtils
188      * @see org.springframework.jdbc.core.JdbcTemplate
189      */

190     public void setDataSource(DataSource JavaDoc dataSource) {
191         if (dataSource instanceof TransactionAwareDataSourceProxy) {
192             // If we got a TransactionAwareDataSourceProxy, we need to perform transactions
193
// for its underlying target DataSource, else data access code won't see
194
// properly exposed transactions (i.e. transactions for the target DataSource).
195
this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();
196         }
197         else {
198             this.dataSource = dataSource;
199         }
200     }
201
202     /**
203      * Return the JDBC DataSource that this instance manages transactions for.
204      */

205     public DataSource JavaDoc getDataSource() {
206         return this.dataSource;
207     }
208
209     /**
210      * Set whether to autodetect a JDBC DataSource used by the JDO PersistenceManagerFactory,
211      * as returned by the <code>getConnectionFactory()</code> method. Default is "true".
212      * <p>Can be turned off to deliberately ignore an available DataSource,
213      * to not expose JDO transactions as JDBC transactions for that DataSource.
214      * @see #setDataSource
215      * @see javax.jdo.PersistenceManagerFactory#getConnectionFactory
216      */

217     public void setAutodetectDataSource(boolean autodetectDataSource) {
218         this.autodetectDataSource = autodetectDataSource;
219     }
220
221     /**
222      * Set the JDO dialect to use for this transaction manager.
223      * <p>The dialect object can be used to retrieve the underlying JDBC connection
224      * and thus allows for exposing JDO transactions as JDBC transactions.
225      * @see JdoDialect#getJdbcConnection
226      */

227     public void setJdoDialect(JdoDialect jdoDialect) {
228         this.jdoDialect = jdoDialect;
229     }
230
231     /**
232      * Return the JDO dialect to use for this transaction manager.
233      * <p>Creates a default one for the specified PersistenceManagerFactory if none set.
234      */

235     public JdoDialect getJdoDialect() {
236         if (this.jdoDialect == null) {
237             this.jdoDialect = new DefaultJdoDialect();
238         }
239         return this.jdoDialect;
240     }
241
242     /**
243      * Eagerly initialize the JDO dialect, creating a default one
244      * for the specified PersistenceManagerFactory if none set.
245      * Auto-detect the PersistenceManagerFactory's DataSource, if any.
246      */

247     public void afterPropertiesSet() {
248         if (getPersistenceManagerFactory() == null) {
249             throw new IllegalArgumentException JavaDoc("Property 'persistenceManagerFactory' is required");
250         }
251         // Build default JdoDialect if none explicitly specified.
252
if (this.jdoDialect == null) {
253             this.jdoDialect = new DefaultJdoDialect(getPersistenceManagerFactory().getConnectionFactory());
254         }
255
256         // Check for DataSource as connection factory.
257
if (this.autodetectDataSource && getDataSource() == null) {
258             Object JavaDoc pmfcf = getPersistenceManagerFactory().getConnectionFactory();
259             if (pmfcf instanceof DataSource JavaDoc) {
260                 // Use the PersistenceManagerFactory's DataSource for exposing transactions to JDBC code.
261
this.dataSource = (DataSource JavaDoc) pmfcf;
262                 if (logger.isInfoEnabled()) {
263                     logger.info("Using DataSource [" + this.dataSource +
264                             "] of JDO PersistenceManagerFactory for JdoTransactionManager");
265                 }
266             }
267         }
268     }
269
270
271     public Object JavaDoc getResourceFactory() {
272         return getPersistenceManagerFactory();
273     }
274
275     protected Object JavaDoc doGetTransaction() {
276         JdoTransactionObject txObject = new JdoTransactionObject();
277         txObject.setSavepointAllowed(isNestedTransactionAllowed());
278
279         PersistenceManagerHolder pmHolder = (PersistenceManagerHolder)
280                 TransactionSynchronizationManager.getResource(getPersistenceManagerFactory());
281         if (pmHolder != null) {
282             if (logger.isDebugEnabled()) {
283                 logger.debug("Found thread-bound PersistenceManager [" +
284                         pmHolder.getPersistenceManager() + "] for JDO transaction");
285             }
286             txObject.setPersistenceManagerHolder(pmHolder, false);
287         }
288
289         if (getDataSource() != null) {
290             ConnectionHolder conHolder = (ConnectionHolder)
291                     TransactionSynchronizationManager.getResource(getDataSource());
292             txObject.setConnectionHolder(conHolder);
293         }
294
295         return txObject;
296     }
297
298     protected boolean isExistingTransaction(Object JavaDoc transaction) {
299         return ((JdoTransactionObject) transaction).hasTransaction();
300     }
301
302     protected void doBegin(Object JavaDoc transaction, TransactionDefinition definition) {
303         JdoTransactionObject txObject = (JdoTransactionObject) transaction;
304
305         if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
306             throw new IllegalTransactionStateException(
307                     "Pre-bound JDBC Connection found! JdoTransactionManager does not support " +
308                     "running within DataSourceTransactionManager if told to manage the DataSource itself. " +
309                     "It is recommended to use a single JdoTransactionManager for all transactions " +
310                     "on a single DataSource, no matter whether JDO or JDBC access.");
311         }
312
313         PersistenceManager pm = null;
314
315         try {
316             if (txObject.getPersistenceManagerHolder() == null ||
317                     txObject.getPersistenceManagerHolder().isSynchronizedWithTransaction()) {
318                 PersistenceManager newPm = getPersistenceManagerFactory().getPersistenceManager();
319                 if (logger.isDebugEnabled()) {
320                     logger.debug("Opened new PersistenceManager [" + newPm + "] for JDO transaction");
321                 }
322                 txObject.setPersistenceManagerHolder(new PersistenceManagerHolder(newPm), true);
323             }
324
325             txObject.getPersistenceManagerHolder().setSynchronizedWithTransaction(true);
326             pm = txObject.getPersistenceManagerHolder().getPersistenceManager();
327
328             // Delegate to JdoDialect for actual transaction begin.
329
Object JavaDoc transactionData = getJdoDialect().beginTransaction(pm.currentTransaction(), definition);
330             txObject.setTransactionData(transactionData);
331
332             // Register transaction timeout.
333
int timeout = determineTimeout(definition);
334             if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
335                 txObject.getPersistenceManagerHolder().setTimeoutInSeconds(timeout);
336             }
337
338             // Register the JDO PersistenceManager's JDBC Connection for the DataSource, if set.
339
if (getDataSource() != null) {
340                 ConnectionHandle conHandle = getJdoDialect().getJdbcConnection(pm, definition.isReadOnly());
341                 if (conHandle != null) {
342                     ConnectionHolder conHolder = new ConnectionHolder(conHandle);
343                     if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
344                         conHolder.setTimeoutInSeconds(timeout);
345                     }
346                     if (logger.isDebugEnabled()) {
347                         logger.debug("Exposing JDO transaction as JDBC transaction [" + conHolder.getConnectionHandle() + "]");
348                     }
349                     TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
350                     txObject.setConnectionHolder(conHolder);
351                 }
352                 else {
353                     if (logger.isDebugEnabled()) {
354                         logger.debug("Not exposing JDO transaction [" + pm + "] as JDBC transaction because JdoDialect [" +
355                                 getJdoDialect() + "] does not support JDBC Connection retrieval");
356                     }
357                 }
358             }
359
360             // Bind the persistence manager holder to the thread.
361
if (txObject.isNewPersistenceManagerHolder()) {
362                 TransactionSynchronizationManager.bindResource(
363                         getPersistenceManagerFactory(), txObject.getPersistenceManagerHolder());
364             }
365         }
366
367         catch (TransactionException ex) {
368             PersistenceManagerFactoryUtils.releasePersistenceManager(pm, getPersistenceManagerFactory());
369             throw ex;
370         }
371         catch (Exception JavaDoc ex) {
372             PersistenceManagerFactoryUtils.releasePersistenceManager(pm, getPersistenceManagerFactory());
373             throw new CannotCreateTransactionException("Could not open JDO PersistenceManager for transaction", ex);
374         }
375     }
376
377     protected Object JavaDoc doSuspend(Object JavaDoc transaction) {
378         JdoTransactionObject txObject = (JdoTransactionObject) transaction;
379         txObject.setPersistenceManagerHolder(null, false);
380         PersistenceManagerHolder persistenceManagerHolder = (PersistenceManagerHolder)
381                 TransactionSynchronizationManager.unbindResource(getPersistenceManagerFactory());
382         txObject.setConnectionHolder(null);
383         ConnectionHolder connectionHolder = null;
384         if (getDataSource() != null) {
385             connectionHolder = (ConnectionHolder) TransactionSynchronizationManager.unbindResource(getDataSource());
386         }
387         return new SuspendedResourcesHolder(persistenceManagerHolder, connectionHolder);
388     }
389
390     protected void doResume(Object JavaDoc transaction, Object JavaDoc suspendedResources) {
391         SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder) suspendedResources;
392         TransactionSynchronizationManager.bindResource(
393                 getPersistenceManagerFactory(), resourcesHolder.getPersistenceManagerHolder());
394         if (getDataSource() != null) {
395             TransactionSynchronizationManager.bindResource(getDataSource(), resourcesHolder.getConnectionHolder());
396         }
397     }
398
399     /**
400      * This implementation returns "true" for JDO 2.0: a JDO2 commit will properly
401      * handle transactions that have been marked rollback-only at a global level.
402      * On JDO 1.0, the rollback-only flag will be managed in Spring's resource holder.
403      */

404     protected boolean shouldCommitOnGlobalRollbackOnly() {
405         return jdoSetRollbackOnlyAvailable;
406     }
407
408     protected void doCommit(DefaultTransactionStatus status) {
409         JdoTransactionObject txObject = (JdoTransactionObject) status.getTransaction();
410         if (status.isDebug()) {
411             logger.debug("Committing JDO transaction on PersistenceManager [" +
412                     txObject.getPersistenceManagerHolder().getPersistenceManager() + "]");
413         }
414         try {
415             Transaction tx = txObject.getPersistenceManagerHolder().getPersistenceManager().currentTransaction();
416             tx.commit();
417         }
418         catch (JDOException ex) {
419             // Assumably failed to flush changes to database.
420
throw convertJdoAccessException(ex);
421         }
422     }
423
424     protected void doRollback(DefaultTransactionStatus status) {
425         JdoTransactionObject txObject = (JdoTransactionObject) status.getTransaction();
426         if (status.isDebug()) {
427             logger.debug("Rolling back JDO transaction on PersistenceManager [" +
428                     txObject.getPersistenceManagerHolder().getPersistenceManager() + "]");
429         }
430         try {
431             Transaction tx = txObject.getPersistenceManagerHolder().getPersistenceManager().currentTransaction();
432             if (tx.isActive()) {
433                 tx.rollback();
434             }
435         }
436         catch (JDOException ex) {
437             throw new TransactionSystemException("Could not roll back JDO transaction", ex);
438         }
439     }
440
441     protected void doSetRollbackOnly(DefaultTransactionStatus status) {
442         JdoTransactionObject txObject = (JdoTransactionObject) status.getTransaction();
443         if (status.isDebug()) {
444             logger.debug("Setting JDO transaction on PersistenceManager [" +
445                     txObject.getPersistenceManagerHolder().getPersistenceManager() + "] rollback-only");
446         }
447         txObject.setRollbackOnly();
448     }
449
450     protected void doCleanupAfterCompletion(Object JavaDoc transaction) {
451         JdoTransactionObject txObject = (JdoTransactionObject) transaction;
452
453         // Remove the persistence manager holder from the thread.
454
if (txObject.isNewPersistenceManagerHolder()) {
455             TransactionSynchronizationManager.unbindResource(getPersistenceManagerFactory());
456         }
457         txObject.getPersistenceManagerHolder().clear();
458
459         // Remove the JDBC connection holder from the thread, if exposed.
460
if (txObject.hasConnectionHolder()) {
461             TransactionSynchronizationManager.unbindResource(getDataSource());
462             try {
463                 getJdoDialect().releaseJdbcConnection(txObject.getConnectionHolder().getConnectionHandle(),
464                         txObject.getPersistenceManagerHolder().getPersistenceManager());
465             }
466             catch (Throwable JavaDoc ex) {
467                 // Just log it, to keep a transaction-related exception.
468
logger.debug("Could not release JDBC connection after transaction", ex);
469             }
470         }
471
472         getJdoDialect().cleanupTransaction(txObject.getTransactionData());
473
474         if (txObject.isNewPersistenceManagerHolder()) {
475             PersistenceManager pm = txObject.getPersistenceManagerHolder().getPersistenceManager();
476             if (logger.isDebugEnabled()) {
477                 logger.debug("Closing JDO PersistenceManager [" + pm + "] after transaction");
478             }
479             PersistenceManagerFactoryUtils.releasePersistenceManager(pm, getPersistenceManagerFactory());
480         }
481         else {
482             logger.debug("Not closing pre-bound JDO PersistenceManager after transaction");
483         }
484     }
485
486     /**
487      * Convert the given JDOException to an appropriate exception from the
488      * <code>org.springframework.dao</code> hierarchy.
489      * <p>Default implementation delegates to the JdoDialect.
490      * May be overridden in subclasses.
491      * @param ex JDOException that occured
492      * @return the corresponding DataAccessException instance
493      * @see JdoDialect#translateException
494      */

495     protected DataAccessException convertJdoAccessException(JDOException ex) {
496         return getJdoDialect().translateException(ex);
497     }
498
499
500     /**
501      * JDO transaction object, representing a PersistenceManagerHolder.
502      * Used as transaction object by JdoTransactionManager.
503      *
504      * <p>Derives from JdbcTransactionObjectSupport in order to inherit the
505      * capability to manage JDBC 3.0 Savepoints for underlying JDBC Connections.
506      *
507      * @see PersistenceManagerHolder
508      */

509     private static class JdoTransactionObject extends JdbcTransactionObjectSupport {
510
511         private PersistenceManagerHolder persistenceManagerHolder;
512
513         private boolean newPersistenceManagerHolder;
514
515         private Object JavaDoc transactionData;
516
517         public void setPersistenceManagerHolder(
518                 PersistenceManagerHolder persistenceManagerHolder, boolean newPersistenceManagerHolder) {
519             this.persistenceManagerHolder = persistenceManagerHolder;
520             this.newPersistenceManagerHolder = newPersistenceManagerHolder;
521         }
522
523         public PersistenceManagerHolder getPersistenceManagerHolder() {
524             return persistenceManagerHolder;
525         }
526
527         public boolean isNewPersistenceManagerHolder() {
528             return newPersistenceManagerHolder;
529         }
530
531         public boolean hasTransaction() {
532             return (this.persistenceManagerHolder != null &&
533                     this.persistenceManagerHolder.getPersistenceManager() != null &&
534                     this.persistenceManagerHolder.getPersistenceManager().currentTransaction().isActive());
535         }
536
537         public void setTransactionData(Object JavaDoc transactionData) {
538             this.transactionData = transactionData;
539         }
540
541         public Object JavaDoc getTransactionData() {
542             return transactionData;
543         }
544
545         public void setRollbackOnly() {
546             if (jdoSetRollbackOnlyAvailable) {
547                 Transaction tx = this.persistenceManagerHolder.getPersistenceManager().currentTransaction();
548                 if (tx.isActive()) {
549                     tx.setRollbackOnly();
550                 }
551             }
552             else {
553                 getPersistenceManagerHolder().setRollbackOnly();
554             }
555             if (hasConnectionHolder()) {
556                 getConnectionHolder().setRollbackOnly();
557             }
558         }
559
560         public boolean isRollbackOnly() {
561             if (jdoSetRollbackOnlyAvailable) {
562                 Transaction tx = this.persistenceManagerHolder.getPersistenceManager().currentTransaction();
563                 return tx.getRollbackOnly();
564             }
565             else {
566                 return getPersistenceManagerHolder().isRollbackOnly();
567             }
568         }
569     }
570
571
572     /**
573      * Holder for suspended resources.
574      * Used internally by <code>doSuspend</code> and <code>doResume</code>.
575      */

576     private static class SuspendedResourcesHolder {
577
578         private final PersistenceManagerHolder persistenceManagerHolder;
579
580         private final ConnectionHolder connectionHolder;
581
582         private SuspendedResourcesHolder(PersistenceManagerHolder pmHolder, ConnectionHolder conHolder) {
583             this.persistenceManagerHolder = pmHolder;
584             this.connectionHolder = conHolder;
585         }
586
587         private PersistenceManagerHolder getPersistenceManagerHolder() {
588             return this.persistenceManagerHolder;
589         }
590
591         private ConnectionHolder getConnectionHolder() {
592             return this.connectionHolder;
593         }
594     }
595
596 }
597
Popular Tags