Source Code Cross Referenced for JtaTransactionManager.java in  » J2EE » spring-framework-2.5 » org » springframework » transaction » jta » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.5 » org.springframework.transaction.jta 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2002-2007 the original author or authors.
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:
0017:        package org.springframework.transaction.jta;
0018:
0019:        import java.io.IOException;
0020:        import java.io.ObjectInputStream;
0021:        import java.io.Serializable;
0022:        import java.util.List;
0023:        import java.util.Properties;
0024:
0025:        import javax.naming.NamingException;
0026:        import javax.transaction.HeuristicMixedException;
0027:        import javax.transaction.HeuristicRollbackException;
0028:        import javax.transaction.InvalidTransactionException;
0029:        import javax.transaction.NotSupportedException;
0030:        import javax.transaction.RollbackException;
0031:        import javax.transaction.Status;
0032:        import javax.transaction.Synchronization;
0033:        import javax.transaction.SystemException;
0034:        import javax.transaction.Transaction;
0035:        import javax.transaction.TransactionManager;
0036:        import javax.transaction.TransactionSynchronizationRegistry;
0037:        import javax.transaction.UserTransaction;
0038:
0039:        import org.springframework.beans.factory.InitializingBean;
0040:        import org.springframework.jndi.JndiTemplate;
0041:        import org.springframework.transaction.CannotCreateTransactionException;
0042:        import org.springframework.transaction.HeuristicCompletionException;
0043:        import org.springframework.transaction.IllegalTransactionStateException;
0044:        import org.springframework.transaction.InvalidIsolationLevelException;
0045:        import org.springframework.transaction.NestedTransactionNotSupportedException;
0046:        import org.springframework.transaction.NoTransactionException;
0047:        import org.springframework.transaction.TransactionDefinition;
0048:        import org.springframework.transaction.TransactionSuspensionNotSupportedException;
0049:        import org.springframework.transaction.TransactionSystemException;
0050:        import org.springframework.transaction.UnexpectedRollbackException;
0051:        import org.springframework.transaction.support.AbstractPlatformTransactionManager;
0052:        import org.springframework.transaction.support.DefaultTransactionStatus;
0053:        import org.springframework.transaction.support.TransactionSynchronization;
0054:        import org.springframework.util.Assert;
0055:        import org.springframework.util.ClassUtils;
0056:        import org.springframework.util.StringUtils;
0057:
0058:        /**
0059:         * {@link org.springframework.transaction.PlatformTransactionManager} implementation
0060:         * for JTA, delegating to a backend JTA provider. This is typically used to delegate
0061:         * to a J2EE server's transaction coordinator, but may also be configured with a
0062:         * local JTA provider which is embedded within the application.
0063:         *
0064:         * <p>This transaction manager is appropriate for handling distributed transactions,
0065:         * i.e. transactions that span multiple resources, and for controlling transactions on
0066:         * application server resources (e.g. JDBC DataSources available in JNDI) in general.
0067:         * For a single JDBC DataSource, DataSourceTransactionManager is perfectly sufficient,
0068:         * and for accessing a single resource with Hibernate (including transactional cache),
0069:         * HibernateTransactionManager is appropriate, for example.
0070:         *
0071:         * <p>Transaction synchronization is active by default, to allow data access support
0072:         * classes to register resources that are opened within the transaction for closing at
0073:         * transaction completion time. Spring's support classes for JDBC, Hibernate, JDO etc
0074:         * all perform such registration, allowing for reuse of the same Hibernate Session etc
0075:         * within the transaction. Standard JTA does not even guarantee that for Connections
0076:         * from a transactional JDBC DataSource: Spring's synchronization solves those issues.
0077:         *
0078:         * <p><b>For typical JTA transactions (REQUIRED, SUPPORTS, MANDATORY, NEVER), a plain
0079:         * JtaTransactionManager definition is all you need, completely portable across all
0080:         * J2EE servers.</b> This corresponds to the functionality of the JTA UserTransaction,
0081:         * for which J2EE specifies a standard JNDI name ("java:comp/UserTransaction").
0082:         * There is no need to configure a server-specific TransactionManager lookup for this
0083:         * kind of JTA usage.
0084:         *
0085:         * <p><b>Note: Advanced JTA usage below. Dealing with these mechanisms is not
0086:         * necessary for typical usage scenarios.</b>
0087:         *
0088:         * <p>Transaction suspension (REQUIRES_NEW, NOT_SUPPORTED) is just available with
0089:         * a JTA TransactionManager being registered, via the "transactionManagerName" or
0090:         * "transactionManager" property. The location of this well-defined JTA object is
0091:         * <i>not</i> specified by J2EE; it is specific to each J2EE server, often kept
0092:         * in JNDI like the JTA UserTransaction. Some well-known JNDI locations are:
0093:         * <ul>
0094:         * <li>"java:comp/UserTransaction" for Resin 2.x, Oracle OC4J (Orion),
0095:         * JOnAS (JOTM), BEA WebLogic
0096:         * <li>"java:comp/TransactionManager" for Resin 3.x
0097:         * <li>"java:pm/TransactionManager" for Borland Enterprise Server and
0098:         * Sun Application Server (Sun ONE 7 and later)
0099:         * <li>"java:/TransactionManager" for JBoss Application Server
0100:         * </ul>
0101:         *
0102:         * <p>All of these cases are autodetected by JtaTransactionManager, provided that the
0103:         * "autodetectTransactionManager" flag is set to "true" (which it is by default).
0104:         *
0105:         * <p><b>Note: Support for the JTA TransactionManager interface is not required by J2EE.
0106:         * Almost all J2EE servers expose it, but do so as extension to J2EE. There might be some
0107:         * issues with compatibility, despite the TransactionManager interface being part of JTA.</b>
0108:         * As a consequence, Spring provides various vendor-specific PlatformTransactionManagers,
0109:         * which are recommended to be used if appropriate: {@link WebLogicJtaTransactionManager},
0110:         * {@link WebSphereUowTransactionManager} and {@link OC4JJtaTransactionManager}.
0111:         * For all other J2EE servers, the standard JtaTransactionManager is sufficient.
0112:         *
0113:         * <p><b>Consider using Spring 2.5's <code>tx:jta-transaction-manager</code> configuration
0114:         * element for automatically picking the appropriate JTA platform transaction manager
0115:         * (automatically detecting WebLogic, WebSphere and OC4J).</b>
0116:         *
0117:         * <p><b>This pure JtaTransactionManager supports timeouts but not per-transaction
0118:         * isolation levels.</b> Custom subclasses may override {@link #doJtaBegin} for
0119:         * specific JTA extensions in order to provide this functionality; Spring includes
0120:         * corresponding {@link WebLogicJtaTransactionManager} and {@link OC4JJtaTransactionManager}
0121:         * classes, for BEA's WebLogic Server and Oracle's OC4J, respectively. Such adapters
0122:         * for specific J2EE transaction coordinators may also expose transaction names for
0123:         * monitoring; with standard JTA, transaction names will simply be ignored.
0124:         *
0125:         * <p>JTA 1.1 adds the TransactionSynchronizationRegistry facility, as public Java EE 5
0126:         * API in addition to the standard JTA UserTransaction handle. As of Spring 2.5, this
0127:         * JtaTransactionManager autodetects the TransactionSynchronizationRegistry and uses
0128:         * it for registering Spring-managed synchronizations when participating in an existing
0129:         * JTA transaction (e.g. controlled by EJB CMT). If no TransactionSynchronizationRegistry
0130:         * is available (or the JTA 1.1 API isn't available), then such synchronizations
0131:         * will be registered via the (non-J2EE) JTA TransactionManager handle.
0132:         *
0133:         * <p>This class is serializable. However, active synchronizations do not survive
0134:         * serialization.
0135:         *
0136:         * @author Juergen Hoeller
0137:         * @since 24.03.2003
0138:         * @see javax.transaction.UserTransaction
0139:         * @see javax.transaction.TransactionManager
0140:         * @see javax.transaction.TransactionSynchronizationRegistry
0141:         * @see #setUserTransactionName
0142:         * @see #setUserTransaction
0143:         * @see #setTransactionManagerName
0144:         * @see #setTransactionManager
0145:         * @see JotmFactoryBean
0146:         * @see WebSphereTransactionManagerFactoryBean
0147:         * @see WebLogicJtaTransactionManager
0148:         */
0149:        public class JtaTransactionManager extends
0150:                AbstractPlatformTransactionManager implements 
0151:                TransactionFactory, InitializingBean, Serializable {
0152:
0153:            /**
0154:             * Default JNDI location for the JTA UserTransaction. Many J2EE servers
0155:             * also provide support for the JTA TransactionManager interface there.
0156:             * @see #setUserTransactionName
0157:             * @see #setAutodetectTransactionManager
0158:             */
0159:            public static final String DEFAULT_USER_TRANSACTION_NAME = "java:comp/UserTransaction";
0160:
0161:            /**
0162:             * Fallback JNDI locations for the JTA TransactionManager. Applied if
0163:             * the JTA UserTransaction does not implement the JTA TransactionManager
0164:             * interface, provided that the "autodetectTransactionManager" flag is "true".
0165:             * @see #setTransactionManagerName
0166:             * @see #setAutodetectTransactionManager
0167:             */
0168:            public static final String[] FALLBACK_TRANSACTION_MANAGER_NAMES = new String[] {
0169:                    "java:comp/TransactionManager",
0170:                    "java:pm/TransactionManager", "java:/TransactionManager" };
0171:
0172:            /**
0173:             * Standard Java EE 5 JNDI location for the JTA TransactionSynchronizationRegistry.
0174:             * Autodetected when available.
0175:             */
0176:            public static final String DEFAULT_TRANSACTION_SYNCHRONIZATION_REGISTRY_NAME = "java:comp/TransactionSynchronizationRegistry";
0177:
0178:            private static final String TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME = "javax.transaction.TransactionSynchronizationRegistry";
0179:
0180:            private transient JndiTemplate jndiTemplate = new JndiTemplate();
0181:
0182:            private transient UserTransaction userTransaction;
0183:
0184:            private String userTransactionName;
0185:
0186:            private boolean autodetectUserTransaction = true;
0187:
0188:            private boolean cacheUserTransaction = true;
0189:
0190:            private boolean userTransactionObtainedFromJndi = false;
0191:
0192:            private transient TransactionManager transactionManager;
0193:
0194:            private String transactionManagerName;
0195:
0196:            private boolean autodetectTransactionManager = true;
0197:
0198:            private String transactionSynchronizationRegistryName;
0199:
0200:            private transient Object transactionSynchronizationRegistry;
0201:
0202:            private boolean allowCustomIsolationLevels = false;
0203:
0204:            /**
0205:             * Create a new JtaTransactionManager instance, to be configured as bean.
0206:             * Invoke <code>afterPropertiesSet</code> to activate the configuration.
0207:             * @see #setUserTransactionName
0208:             * @see #setUserTransaction
0209:             * @see #setTransactionManagerName
0210:             * @see #setTransactionManager
0211:             * @see #afterPropertiesSet()
0212:             */
0213:            public JtaTransactionManager() {
0214:                setNestedTransactionAllowed(true);
0215:            }
0216:
0217:            /**
0218:             * Create a new JtaTransactionManager instance.
0219:             * @param userTransaction the JTA UserTransaction to use as direct reference
0220:             */
0221:            public JtaTransactionManager(UserTransaction userTransaction) {
0222:                this ();
0223:                Assert.notNull(userTransaction,
0224:                        "UserTransaction must not be null");
0225:                this .userTransaction = userTransaction;
0226:            }
0227:
0228:            /**
0229:             * Create a new JtaTransactionManager instance.
0230:             * @param userTransaction the JTA UserTransaction to use as direct reference
0231:             * @param transactionManager the JTA TransactionManager to use as direct reference
0232:             */
0233:            public JtaTransactionManager(UserTransaction userTransaction,
0234:                    TransactionManager transactionManager) {
0235:                this ();
0236:                Assert.notNull(userTransaction,
0237:                        "UserTransaction must not be null");
0238:                Assert.notNull(transactionManager,
0239:                        "TransactionManager must not be null");
0240:                this .userTransaction = userTransaction;
0241:                this .transactionManager = transactionManager;
0242:            }
0243:
0244:            /**
0245:             * Create a new JtaTransactionManager instance.
0246:             * @param transactionManager the JTA TransactionManager to use as direct reference
0247:             */
0248:            public JtaTransactionManager(TransactionManager transactionManager) {
0249:                this ();
0250:                Assert.notNull(transactionManager,
0251:                        "TransactionManager must not be null");
0252:                this .transactionManager = transactionManager;
0253:                this .userTransaction = buildUserTransaction(transactionManager);
0254:            }
0255:
0256:            /**
0257:             * Set the JndiTemplate to use for JNDI lookups.
0258:             * A default one is used if not set.
0259:             */
0260:            public void setJndiTemplate(JndiTemplate jndiTemplate) {
0261:                if (jndiTemplate == null) {
0262:                    throw new IllegalArgumentException(
0263:                            "jndiTemplate must not be null");
0264:                }
0265:                this .jndiTemplate = jndiTemplate;
0266:            }
0267:
0268:            /**
0269:             * Return the JndiTemplate used for JNDI lookups.
0270:             */
0271:            public JndiTemplate getJndiTemplate() {
0272:                return this .jndiTemplate;
0273:            }
0274:
0275:            /**
0276:             * Set the JNDI environment to use for JNDI lookups.
0277:             * Creates a JndiTemplate with the given environment settings.
0278:             * @see #setJndiTemplate
0279:             */
0280:            public void setJndiEnvironment(Properties jndiEnvironment) {
0281:                this .jndiTemplate = new JndiTemplate(jndiEnvironment);
0282:            }
0283:
0284:            /**
0285:             * Return the JNDI environment to use for JNDI lookups.
0286:             */
0287:            public Properties getJndiEnvironment() {
0288:                return this .jndiTemplate.getEnvironment();
0289:            }
0290:
0291:            /**
0292:             * Set the JTA UserTransaction to use as direct reference.
0293:             * <p>Typically just used for local JTA setups; in a J2EE environment,
0294:             * the UserTransaction will always be fetched from JNDI.
0295:             * @see #setUserTransactionName
0296:             * @see #setAutodetectUserTransaction
0297:             */
0298:            public void setUserTransaction(UserTransaction userTransaction) {
0299:                this .userTransaction = userTransaction;
0300:            }
0301:
0302:            /**
0303:             * Return the JTA UserTransaction that this transaction manager uses.
0304:             */
0305:            public UserTransaction getUserTransaction() {
0306:                return this .userTransaction;
0307:            }
0308:
0309:            /**
0310:             * Set the JNDI name of the JTA UserTransaction.
0311:             * <p>Note that the UserTransaction will be autodetected at the J2EE default
0312:             * location "java:comp/UserTransaction" if not specified explicitly.
0313:             * @see #DEFAULT_USER_TRANSACTION_NAME
0314:             * @see #setUserTransaction
0315:             * @see #setAutodetectUserTransaction
0316:             */
0317:            public void setUserTransactionName(String userTransactionName) {
0318:                this .userTransactionName = userTransactionName;
0319:            }
0320:
0321:            /**
0322:             * Set whether to autodetect the JTA UserTransaction at its default
0323:             * JNDI location "java:comp/UserTransaction", as specified by J2EE.
0324:             * Will proceed without UserTransaction if none found.
0325:             * <p>Default is "true", autodetecting the UserTransaction unless
0326:             * it has been specified explicitly. Turn this flag off to allow for
0327:             * JtaTransactionManager operating against the TransactionManager only,
0328:             * despite a default UserTransaction being available.
0329:             * @see #DEFAULT_USER_TRANSACTION_NAME
0330:             */
0331:            public void setAutodetectUserTransaction(
0332:                    boolean autodetectUserTransaction) {
0333:                this .autodetectUserTransaction = autodetectUserTransaction;
0334:            }
0335:
0336:            /**
0337:             * Set whether to cache the JTA UserTransaction object fetched from JNDI.
0338:             * <p>Default is "true": UserTransaction lookup will only happen at startup,
0339:             * reusing the same UserTransaction handle for all transactions of all threads.
0340:             * This is the most efficient choice for all application servers that provide
0341:             * a shared UserTransaction object (the typical case).
0342:             * <p>Turn this flag off to enforce a fresh lookup of the UserTransaction
0343:             * for every transaction. This is only necessary for application servers
0344:             * that return a new UserTransaction for every transaction, keeping state
0345:             * tied to the UserTransaction object itself rather than the current thread.
0346:             * @see #setUserTransactionName
0347:             */
0348:            public void setCacheUserTransaction(boolean cacheUserTransaction) {
0349:                this .cacheUserTransaction = cacheUserTransaction;
0350:            }
0351:
0352:            /**
0353:             * Set the JTA TransactionManager to use as direct reference.
0354:             * <p>A TransactionManager is necessary for suspending and resuming transactions,
0355:             * as this not supported by the UserTransaction interface.
0356:             * <p>Note that the TransactionManager will be autodetected if the JTA
0357:             * UserTransaction object implements the JTA TransactionManager interface too,
0358:             * as well as autodetected at various well-known fallback JNDI locations.
0359:             * @see #setTransactionManagerName
0360:             * @see #setAutodetectTransactionManager
0361:             */
0362:            public void setTransactionManager(
0363:                    TransactionManager transactionManager) {
0364:                this .transactionManager = transactionManager;
0365:            }
0366:
0367:            /**
0368:             * Return the JTA TransactionManager that this transaction manager uses.
0369:             */
0370:            public TransactionManager getTransactionManager() {
0371:                return this .transactionManager;
0372:            }
0373:
0374:            /**
0375:             * Set the JNDI name of the JTA TransactionManager.
0376:             * <p>A TransactionManager is necessary for suspending and resuming transactions,
0377:             * as this not supported by the UserTransaction interface.
0378:             * <p>Note that the TransactionManager will be autodetected if the JTA
0379:             * UserTransaction object implements the JTA TransactionManager interface too,
0380:             * as well as autodetected at various well-known fallback JNDI locations.
0381:             * @see #setTransactionManager
0382:             * @see #setAutodetectTransactionManager
0383:             */
0384:            public void setTransactionManagerName(String transactionManagerName) {
0385:                this .transactionManagerName = transactionManagerName;
0386:            }
0387:
0388:            /**
0389:             * Set whether to autodetect a JTA UserTransaction object that implements
0390:             * the JTA TransactionManager interface too (i.e. the JNDI location for the
0391:             * TransactionManager is "java:comp/UserTransaction", same as for the UserTransaction).
0392:             * Also checks the fallback JNDI locations "java:comp/TransactionManager" and
0393:             * "java:/TransactionManager". Will proceed without TransactionManager if none found.
0394:             * <p>Default is "true", autodetecting the TransactionManager unless it has been
0395:             * specified explicitly. Can be turned off to deliberately ignore an available
0396:             * TransactionManager, for example when there are known issues with suspend/resume
0397:             * and any attempt to use REQUIRES_NEW or NOT_SUPPORTED should fail fast.
0398:             * @see #FALLBACK_TRANSACTION_MANAGER_NAMES
0399:             */
0400:            public void setAutodetectTransactionManager(
0401:                    boolean autodetectTransactionManager) {
0402:                this .autodetectTransactionManager = autodetectTransactionManager;
0403:            }
0404:
0405:            /**
0406:             * Set the JNDI name of the JTA 1.1 TransactionSynchronizationRegistry.
0407:             * <p>Note that the TransactionSynchronizationRegistry will be autodetected
0408:             * at the Java EE 5 default location "java:comp/TransactionSynchronizationRegistry"
0409:             * if not specified explicitly.
0410:             * @see #DEFAULT_TRANSACTION_SYNCHRONIZATION_REGISTRY_NAME
0411:             */
0412:            public void setTransactionSynchronizationRegistryName(
0413:                    String transactionSynchronizationRegistryName) {
0414:                this .transactionSynchronizationRegistryName = transactionSynchronizationRegistryName;
0415:            }
0416:
0417:            /**
0418:             * Set whether to allow custom isolation levels to be specified.
0419:             * <p>Default is "false", throwing an exception if a non-default isolation level
0420:             * is specified for a transaction. Turn this flag on if affected resource adapters
0421:             * check the thread-bound transaction context and apply the specified isolation
0422:             * levels individually (e.g. through a IsolationLevelDataSourceRouter).
0423:             * @see org.springframework.jdbc.datasource.lookup.IsolationLevelDataSourceRouter
0424:             */
0425:            public void setAllowCustomIsolationLevels(
0426:                    boolean allowCustomIsolationLevels) {
0427:                this .allowCustomIsolationLevels = allowCustomIsolationLevels;
0428:            }
0429:
0430:            /**
0431:             * Initialize the UserTransaction as well as the TransactionManager handle.
0432:             * @see #initUserTransactionAndTransactionManager()
0433:             */
0434:            public void afterPropertiesSet() throws TransactionSystemException {
0435:                initUserTransactionAndTransactionManager();
0436:                checkUserTransactionAndTransactionManager();
0437:                initTransactionSynchronizationRegistry();
0438:            }
0439:
0440:            /**
0441:             * Initialize the UserTransaction as well as the TransactionManager handle.
0442:             * @throws TransactionSystemException if initialization failed
0443:             */
0444:            protected void initUserTransactionAndTransactionManager()
0445:                    throws TransactionSystemException {
0446:                // Fetch JTA UserTransaction from JNDI, if necessary.
0447:                if (this .userTransaction == null) {
0448:                    if (StringUtils.hasLength(this .userTransactionName)) {
0449:                        this .userTransaction = lookupUserTransaction(this .userTransactionName);
0450:                        this .userTransactionObtainedFromJndi = true;
0451:                    } else {
0452:                        this .userTransaction = retrieveUserTransaction();
0453:                    }
0454:                }
0455:
0456:                // Fetch JTA TransactionManager from JNDI, if necessary.
0457:                if (this .transactionManager == null) {
0458:                    if (StringUtils.hasLength(this .transactionManagerName)) {
0459:                        this .transactionManager = lookupTransactionManager(this .transactionManagerName);
0460:                    } else {
0461:                        this .transactionManager = retrieveTransactionManager();
0462:                    }
0463:                }
0464:
0465:                // Autodetect UserTransaction at its default JNDI location.
0466:                if (this .userTransaction == null
0467:                        && this .autodetectUserTransaction) {
0468:                    this .userTransaction = findUserTransaction();
0469:                }
0470:
0471:                // Autodetect UserTransaction object that implements TransactionManager,
0472:                // and check fallback JNDI locations else.
0473:                if (this .transactionManager == null
0474:                        && this .autodetectTransactionManager) {
0475:                    this .transactionManager = findTransactionManager(this .userTransaction);
0476:                }
0477:
0478:                // If only JTA TransactionManager specified, create UserTransaction handle for it.
0479:                if (this .userTransaction == null
0480:                        && this .transactionManager != null) {
0481:                    this .userTransaction = buildUserTransaction(this .transactionManager);
0482:                }
0483:            }
0484:
0485:            /**
0486:             * Check the UserTransaction as well as the TransactionManager handle,
0487:             * assuming standard JTA requirements.
0488:             * @throws IllegalStateException if no sufficient handles are available
0489:             */
0490:            protected void checkUserTransactionAndTransactionManager()
0491:                    throws IllegalStateException {
0492:                // We at least need the JTA UserTransaction.
0493:                if (this .userTransaction != null) {
0494:                    if (logger.isInfoEnabled()) {
0495:                        logger.info("Using JTA UserTransaction: "
0496:                                + this .userTransaction);
0497:                    }
0498:                } else {
0499:                    throw new IllegalStateException(
0500:                            "No JTA UserTransaction available - specify either "
0501:                                    + "'userTransaction' or 'userTransactionName' or 'transactionManager' or 'transactionManagerName'");
0502:                }
0503:
0504:                // For transaction suspension, the JTA TransactionManager is necessary too.
0505:                if (this .transactionManager != null) {
0506:                    if (logger.isInfoEnabled()) {
0507:                        logger.info("Using JTA TransactionManager: "
0508:                                + this .transactionManager);
0509:                    }
0510:                } else {
0511:                    logger
0512:                            .warn("No JTA TransactionManager found: "
0513:                                    + "transaction suspension and synchronization with existing JTA transactions not available");
0514:                }
0515:            }
0516:
0517:            /**
0518:             * Initialize the JTA 1.1 TransactionSynchronizationRegistry, if available.
0519:             * <p>To be called after {@link #initUserTransactionAndTransactionManager()},
0520:             * since it may check the UserTransaction and TransactionManager handles.
0521:             * @throws TransactionSystemException if initialization failed
0522:             */
0523:            protected void initTransactionSynchronizationRegistry() {
0524:                if (StringUtils
0525:                        .hasLength(this .transactionSynchronizationRegistryName)) {
0526:                    this .transactionSynchronizationRegistry = lookupTransactionSynchronizationRegistry(this .transactionSynchronizationRegistryName);
0527:                } else {
0528:                    this .transactionSynchronizationRegistry = retrieveTransactionSynchronizationRegistry();
0529:                    if (this .transactionSynchronizationRegistry == null) {
0530:                        this .transactionSynchronizationRegistry = findTransactionSynchronizationRegistry(
0531:                                this .userTransaction, this .transactionManager);
0532:                    }
0533:                }
0534:
0535:                if (this .transactionSynchronizationRegistry != null) {
0536:                    if (logger.isInfoEnabled()) {
0537:                        logger
0538:                                .info("Using JTA TransactionSynchronizationRegistry: "
0539:                                        + this .transactionSynchronizationRegistry);
0540:                    }
0541:                }
0542:            }
0543:
0544:            /**
0545:             * Build a UserTransaction handle based on the given TransactionManager.
0546:             * @param transactionManager the TransactionManager
0547:             * @return a corresponding UserTransaction handle
0548:             */
0549:            protected UserTransaction buildUserTransaction(
0550:                    TransactionManager transactionManager) {
0551:                if (transactionManager instanceof  UserTransaction) {
0552:                    return (UserTransaction) transactionManager;
0553:                } else {
0554:                    return new UserTransactionAdapter(transactionManager);
0555:                }
0556:            }
0557:
0558:            /**
0559:             * Look up the JTA UserTransaction in JNDI via the configured name.
0560:             * <p>Called by <code>afterPropertiesSet</code> if no direct UserTransaction reference was set.
0561:             * Can be overridden in subclasses to provide a different UserTransaction object.
0562:             * @param userTransactionName the JNDI name of the UserTransaction
0563:             * @return the UserTransaction object
0564:             * @throws TransactionSystemException if the JNDI lookup failed
0565:             * @see #setJndiTemplate
0566:             * @see #setUserTransactionName
0567:             */
0568:            protected UserTransaction lookupUserTransaction(
0569:                    String userTransactionName)
0570:                    throws TransactionSystemException {
0571:                try {
0572:                    if (logger.isDebugEnabled()) {
0573:                        logger
0574:                                .debug("Retrieving JTA UserTransaction from JNDI location ["
0575:                                        + userTransactionName + "]");
0576:                    }
0577:                    return (UserTransaction) getJndiTemplate().lookup(
0578:                            userTransactionName, UserTransaction.class);
0579:                } catch (NamingException ex) {
0580:                    throw new TransactionSystemException(
0581:                            "JTA UserTransaction is not available at JNDI location ["
0582:                                    + userTransactionName + "]", ex);
0583:                }
0584:            }
0585:
0586:            /**
0587:             * Look up the JTA TransactionManager in JNDI via the configured name.
0588:             * <p>Called by <code>afterPropertiesSet</code> if no direct TransactionManager reference was set.
0589:             * Can be overridden in subclasses to provide a different TransactionManager object.
0590:             * @param transactionManagerName the JNDI name of the TransactionManager
0591:             * @return the UserTransaction object
0592:             * @throws TransactionSystemException if the JNDI lookup failed
0593:             * @see #setJndiTemplate
0594:             * @see #setTransactionManagerName
0595:             */
0596:            protected TransactionManager lookupTransactionManager(
0597:                    String transactionManagerName)
0598:                    throws TransactionSystemException {
0599:                try {
0600:                    if (logger.isDebugEnabled()) {
0601:                        logger
0602:                                .debug("Retrieving JTA TransactionManager from JNDI location ["
0603:                                        + transactionManagerName + "]");
0604:                    }
0605:                    return (TransactionManager) getJndiTemplate().lookup(
0606:                            transactionManagerName, TransactionManager.class);
0607:                } catch (NamingException ex) {
0608:                    throw new TransactionSystemException(
0609:                            "JTA TransactionManager is not available at JNDI location ["
0610:                                    + transactionManagerName + "]", ex);
0611:                }
0612:            }
0613:
0614:            /**
0615:             * Look up the JTA TransactionSynchronizationRegistry in JNDI via the configured name.
0616:             * <p>Can be overridden in subclasses to provide a different TransactionManager object.
0617:             * @param registryName the JNDI name of the
0618:             * TransactionSynchronizationRegistry
0619:             * @return the TransactionSynchronizationRegistry object
0620:             * @throws TransactionSystemException if the JNDI lookup failed
0621:             * @see #setJndiTemplate
0622:             * @see #setTransactionSynchronizationRegistryName
0623:             */
0624:            protected Object lookupTransactionSynchronizationRegistry(
0625:                    String registryName) throws TransactionSystemException {
0626:                try {
0627:                    if (logger.isDebugEnabled()) {
0628:                        logger
0629:                                .debug("Retrieving JTA TransactionSynchronizationRegistry from JNDI location ["
0630:                                        + registryName + "]");
0631:                    }
0632:                    Class registryClass = ClassUtils.forName(
0633:                            TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME,
0634:                            getClass().getClassLoader());
0635:                    return getJndiTemplate()
0636:                            .lookup(registryName, registryClass);
0637:                } catch (ClassNotFoundException ex) {
0638:                    throw new TransactionSystemException("JTA 1.1 ["
0639:                            + TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME
0640:                            + "] not available");
0641:                } catch (NamingException ex) {
0642:                    throw new TransactionSystemException(
0643:                            "JTA TransactionSynchronizationRegistry is not available at JNDI location ["
0644:                                    + registryName + "]", ex);
0645:                }
0646:            }
0647:
0648:            /**
0649:             * Allows subclasses to retrieve the JTA UserTransaction in a vendor-specific manner.
0650:             * Only called if no "userTransaction" or "userTransactionName" specified.
0651:             * <p>The default implementation simply returns <code>null</code>.
0652:             * @return the JTA UserTransaction handle to use, or <code>null</code> if none found
0653:             * @throws TransactionSystemException in case of errors
0654:             * @see #setUserTransaction
0655:             * @see #setUserTransactionName
0656:             */
0657:            protected UserTransaction retrieveUserTransaction()
0658:                    throws TransactionSystemException {
0659:                return null;
0660:            }
0661:
0662:            /**
0663:             * Allows subclasses to retrieve the JTA TransactionManager in a vendor-specific manner.
0664:             * Only called if no "transactionManager" or "transactionManagerName" specified.
0665:             * <p>The default implementation simply returns <code>null</code>.
0666:             * @return the JTA TransactionManager handle to use, or <code>null</code> if none found
0667:             * @throws TransactionSystemException in case of errors
0668:             * @see #setTransactionManager
0669:             * @see #setTransactionManagerName
0670:             */
0671:            protected TransactionManager retrieveTransactionManager()
0672:                    throws TransactionSystemException {
0673:                return null;
0674:            }
0675:
0676:            /**
0677:             * Allows subclasses to retrieve the JTA 1.1 TransactionSynchronizationRegistry
0678:             * in a vendor-specific manner.
0679:             * <p>The default implementation simply returns <code>null</code>.
0680:             * @return the JTA TransactionSynchronizationRegistry handle to use,
0681:             * or <code>null</code> if none found
0682:             * @throws TransactionSystemException in case of errors
0683:             */
0684:            protected Object retrieveTransactionSynchronizationRegistry()
0685:                    throws TransactionSystemException {
0686:                return null;
0687:            }
0688:
0689:            /**
0690:             * Find the JTA UserTransaction through a default JNDI lookup:
0691:             * "java:comp/UserTransaction".
0692:             * @return the JTA UserTransaction reference, or <code>null</code> if not found
0693:             * @see #DEFAULT_USER_TRANSACTION_NAME
0694:             */
0695:            protected UserTransaction findUserTransaction() {
0696:                String jndiName = DEFAULT_USER_TRANSACTION_NAME;
0697:                try {
0698:                    UserTransaction ut = (UserTransaction) getJndiTemplate()
0699:                            .lookup(jndiName, UserTransaction.class);
0700:                    if (logger.isDebugEnabled()) {
0701:                        logger
0702:                                .debug("JTA UserTransaction found at default JNDI location ["
0703:                                        + jndiName + "]");
0704:                    }
0705:                    this .userTransactionObtainedFromJndi = true;
0706:                    return ut;
0707:                } catch (NamingException ex) {
0708:                    if (logger.isDebugEnabled()) {
0709:                        logger.debug(
0710:                                "No JTA UserTransaction found at default JNDI location ["
0711:                                        + jndiName + "]", ex);
0712:                    }
0713:                    return null;
0714:                }
0715:            }
0716:
0717:            /**
0718:             * Find the JTA TransactionManager through autodetection: checking whether the
0719:             * UserTransaction object implements the TransactionManager, and checking the
0720:             * fallback JNDI locations.
0721:             * @param ut the JTA UserTransaction object
0722:             * @return the JTA TransactionManager reference, or <code>null</code> if not found
0723:             * @see #FALLBACK_TRANSACTION_MANAGER_NAMES
0724:             */
0725:            protected TransactionManager findTransactionManager(
0726:                    UserTransaction ut) {
0727:                if (ut instanceof  TransactionManager) {
0728:                    if (logger.isDebugEnabled()) {
0729:                        logger.debug("JTA UserTransaction object [" + ut
0730:                                + "] implements TransactionManager");
0731:                    }
0732:                    return (TransactionManager) ut;
0733:                }
0734:
0735:                // Check fallback JNDI locations.
0736:                for (int i = 0; i < FALLBACK_TRANSACTION_MANAGER_NAMES.length; i++) {
0737:                    String jndiName = FALLBACK_TRANSACTION_MANAGER_NAMES[i];
0738:                    try {
0739:                        TransactionManager tm = (TransactionManager) getJndiTemplate()
0740:                                .lookup(jndiName, TransactionManager.class);
0741:                        if (logger.isDebugEnabled()) {
0742:                            logger
0743:                                    .debug("JTA TransactionManager found at fallback JNDI location ["
0744:                                            + jndiName + "]");
0745:                        }
0746:                        return tm;
0747:                    } catch (NamingException ex) {
0748:                        if (logger.isDebugEnabled()) {
0749:                            logger.debug(
0750:                                    "No JTA TransactionManager found at fallback JNDI location ["
0751:                                            + jndiName + "]", ex);
0752:                        }
0753:                    }
0754:                }
0755:
0756:                // OK, so no JTA TransactionManager is available...
0757:                return null;
0758:            }
0759:
0760:            /**
0761:             * Find the JTA 1.1 TransactionSynchronizationRegistry through autodetection:
0762:             * checking whether the UserTransaction object or TransactionManager object
0763:             * implements it, and checking Java EE 5's standard JNDI location.
0764:             * <p>The default implementation simply returns <code>null</code>.
0765:             * @param ut the JTA UserTransaction object
0766:             * @param tm the JTA TransactionManager object
0767:             * @return the JTA TransactionSynchronizationRegistry handle to use,
0768:             * or <code>null</code> if none found
0769:             * @throws TransactionSystemException in case of errors
0770:             */
0771:            protected Object findTransactionSynchronizationRegistry(
0772:                    UserTransaction ut, TransactionManager tm)
0773:                    throws TransactionSystemException {
0774:
0775:                try {
0776:                    Class registryClass = ClassUtils.forName(
0777:                            TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME,
0778:                            getClass().getClassLoader());
0779:
0780:                    // If we came here, we might be on Java EE 5, since the JTA 1.1 API is present.
0781:                    if (this .userTransactionObtainedFromJndi) {
0782:                        // UserTransaction has already been obtained from JNDI, so the
0783:                        // TransactionSynchronizationRegistry probably sits there as well.
0784:                        String jndiName = DEFAULT_TRANSACTION_SYNCHRONIZATION_REGISTRY_NAME;
0785:                        try {
0786:                            Object tsr = getJndiTemplate().lookup(jndiName,
0787:                                    registryClass);
0788:                            if (logger.isDebugEnabled()) {
0789:                                logger
0790:                                        .debug("JTA TransactionSynchronizationRegistry found at default JNDI location ["
0791:                                                + jndiName + "]");
0792:                            }
0793:                            return tsr;
0794:                        } catch (NamingException ex) {
0795:                            if (logger.isDebugEnabled()) {
0796:                                logger.debug(
0797:                                        "No JTA TransactionSynchronizationRegistry found at default JNDI location ["
0798:                                                + jndiName + "]", ex);
0799:                            }
0800:                        }
0801:                    }
0802:
0803:                    // Check whether the UserTransaction or TransactionManager implements it...
0804:                    if (registryClass.isInstance(ut)) {
0805:                        return ut;
0806:                    }
0807:                    if (registryClass.isInstance(tm)) {
0808:                        return tm;
0809:                    }
0810:
0811:                    // OK, so no JTA 1.1 TransactionSynchronizationRegistry is available,
0812:                    // despite the API being present...
0813:                    return null;
0814:                } catch (ClassNotFoundException ex) {
0815:                    logger.debug("JTA 1.1 ["
0816:                            + TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME
0817:                            + "] not available");
0818:                    return null;
0819:                }
0820:            }
0821:
0822:            /**
0823:             * This implementation returns a JtaTransactionObject instance for the
0824:             * JTA UserTransaction.
0825:             * <p>The UserTransaction object will either be looked up freshly for the
0826:             * current transaction, or the cached one looked up at startup will be used.
0827:             * The latter is the default: Most application servers use a shared singleton
0828:             * UserTransaction that can be cached. Turn off the "cacheUserTransaction"
0829:             * flag to enforce a fresh lookup for every transaction.
0830:             * @see #setCacheUserTransaction
0831:             */
0832:            protected Object doGetTransaction() {
0833:                UserTransaction ut = getUserTransaction();
0834:                if (ut == null) {
0835:                    throw new CannotCreateTransactionException(
0836:                            "No JTA UserTransaction available - "
0837:                                    + "programmatic PlatformTransactionManager.getTransaction usage not supported");
0838:                }
0839:                if (!this .cacheUserTransaction) {
0840:                    ut = lookupUserTransaction(this .userTransactionName != null ? this .userTransactionName
0841:                            : DEFAULT_USER_TRANSACTION_NAME);
0842:                }
0843:                return doGetJtaTransaction(ut);
0844:            }
0845:
0846:            /**
0847:             * Get a JTA transaction object for the given current UserTransaction.
0848:             * <p>Subclasses can override this to provide a JtaTransactionObject
0849:             * subclass, for example holding some additional JTA handle needed.
0850:             * @param ut the UserTransaction handle to use for the current transaction
0851:             * @return the JtaTransactionObject holding the UserTransaction
0852:             */
0853:            protected JtaTransactionObject doGetJtaTransaction(
0854:                    UserTransaction ut) {
0855:                return new JtaTransactionObject(ut);
0856:            }
0857:
0858:            protected boolean isExistingTransaction(Object transaction) {
0859:                JtaTransactionObject txObject = (JtaTransactionObject) transaction;
0860:                try {
0861:                    return (txObject.getUserTransaction().getStatus() != Status.STATUS_NO_TRANSACTION);
0862:                } catch (SystemException ex) {
0863:                    throw new TransactionSystemException(
0864:                            "JTA failure on getStatus", ex);
0865:                }
0866:            }
0867:
0868:            /**
0869:             * This implementation returns false to cause a further invocation
0870:             * of doBegin despite an already existing transaction.
0871:             * <p>JTA implementations might support nested transactions via further
0872:             * <code>UserTransaction.begin()</code> invocations, but never support savepoints.
0873:             * @see #doBegin
0874:             * @see javax.transaction.UserTransaction#begin()
0875:             */
0876:            protected boolean useSavepointForNestedTransaction() {
0877:                return false;
0878:            }
0879:
0880:            protected void doBegin(Object transaction,
0881:                    TransactionDefinition definition) {
0882:                JtaTransactionObject txObject = (JtaTransactionObject) transaction;
0883:                try {
0884:                    doJtaBegin(txObject, definition);
0885:                } catch (NotSupportedException ex) {
0886:                    // assume nested transaction not supported
0887:                    throw new NestedTransactionNotSupportedException(
0888:                            "JTA implementation does not support nested transactions",
0889:                            ex);
0890:                } catch (UnsupportedOperationException ex) {
0891:                    // assume nested transaction not supported
0892:                    throw new NestedTransactionNotSupportedException(
0893:                            "JTA implementation does not support nested transactions",
0894:                            ex);
0895:                } catch (SystemException ex) {
0896:                    throw new CannotCreateTransactionException(
0897:                            "JTA failure on begin", ex);
0898:                }
0899:            }
0900:
0901:            /**
0902:             * Perform a JTA begin on the JTA UserTransaction or TransactionManager.
0903:             * <p>This implementation only supports standard JTA functionality:
0904:             * that is, no per-transaction isolation levels and no transaction names.
0905:             * Can be overridden in subclasses, for specific JTA implementations.
0906:             * <p>Calls <code>applyIsolationLevel</code> and <code>applyTimeout</code>
0907:             * before invoking the UserTransaction's <code>begin</code> method.
0908:             * @param txObject the JtaTransactionObject containing the UserTransaction
0909:             * @param definition TransactionDefinition instance, describing propagation
0910:             * behavior, isolation level, read-only flag, timeout, and transaction name
0911:             * @throws NotSupportedException if thrown by JTA methods
0912:             * @throws SystemException if thrown by JTA methods
0913:             * @see #getUserTransaction
0914:             * @see #getTransactionManager
0915:             * @see #applyIsolationLevel
0916:             * @see #applyTimeout
0917:             * @see JtaTransactionObject#getUserTransaction()
0918:             * @see javax.transaction.UserTransaction#setTransactionTimeout
0919:             * @see javax.transaction.UserTransaction#begin
0920:             */
0921:            protected void doJtaBegin(JtaTransactionObject txObject,
0922:                    TransactionDefinition definition)
0923:                    throws NotSupportedException, SystemException {
0924:
0925:                applyIsolationLevel(txObject, definition.getIsolationLevel());
0926:                int timeout = determineTimeout(definition);
0927:                applyTimeout(txObject, timeout);
0928:                txObject.getUserTransaction().begin();
0929:            }
0930:
0931:            /**
0932:             * Apply the given transaction isolation level. The default implementation
0933:             * will throw an exception for any level other than ISOLATION_DEFAULT.
0934:             * <p>To be overridden in subclasses for specific JTA implementations,
0935:             * as alternative to overriding the full {@link #doJtaBegin} method.
0936:             * @param txObject the JtaTransactionObject containing the UserTransaction
0937:             * @param isolationLevel isolation level taken from transaction definition
0938:             * @throws InvalidIsolationLevelException if the given isolation level
0939:             * cannot be applied
0940:             * @throws SystemException if thrown by the JTA implementation
0941:             * @see #doJtaBegin
0942:             * @see JtaTransactionObject#getUserTransaction()
0943:             * @see #getTransactionManager()
0944:             */
0945:            protected void applyIsolationLevel(JtaTransactionObject txObject,
0946:                    int isolationLevel) throws InvalidIsolationLevelException,
0947:                    SystemException {
0948:
0949:                if (!this .allowCustomIsolationLevels
0950:                        && isolationLevel != TransactionDefinition.ISOLATION_DEFAULT) {
0951:                    throw new InvalidIsolationLevelException(
0952:                            "JtaTransactionManager does not support custom isolation levels by default - "
0953:                                    + "switch 'allowCustomIsolationLevels' to 'true'");
0954:                }
0955:            }
0956:
0957:            /**
0958:             * Apply the given transaction timeout. The default implementation will call
0959:             * <code>UserTransaction.setTransactionTimeout</code> for a non-default timeout value.
0960:             * @param txObject the JtaTransactionObject containing the UserTransaction
0961:             * @param timeout timeout value taken from transaction definition
0962:             * @throws SystemException if thrown by the JTA implementation
0963:             * @see #doJtaBegin
0964:             * @see JtaTransactionObject#getUserTransaction()
0965:             * @see javax.transaction.UserTransaction#setTransactionTimeout(int)
0966:             */
0967:            protected void applyTimeout(JtaTransactionObject txObject,
0968:                    int timeout) throws SystemException {
0969:                if (timeout > TransactionDefinition.TIMEOUT_DEFAULT) {
0970:                    txObject.getUserTransaction()
0971:                            .setTransactionTimeout(timeout);
0972:                }
0973:            }
0974:
0975:            protected Object doSuspend(Object transaction) {
0976:                JtaTransactionObject txObject = (JtaTransactionObject) transaction;
0977:                try {
0978:                    return doJtaSuspend(txObject);
0979:                } catch (SystemException ex) {
0980:                    throw new TransactionSystemException(
0981:                            "JTA failure on suspend", ex);
0982:                }
0983:            }
0984:
0985:            /**
0986:             * Perform a JTA suspend on the JTA TransactionManager.
0987:             * <p>Can be overridden in subclasses, for specific JTA implementations.
0988:             * @param txObject the JtaTransactionObject containing the UserTransaction
0989:             * @return the suspended JTA Transaction object
0990:             * @throws SystemException if thrown by JTA methods
0991:             * @see #getTransactionManager()
0992:             * @see javax.transaction.TransactionManager#suspend()
0993:             */
0994:            protected Object doJtaSuspend(JtaTransactionObject txObject)
0995:                    throws SystemException {
0996:                if (getTransactionManager() == null) {
0997:                    throw new TransactionSuspensionNotSupportedException(
0998:                            "JtaTransactionManager needs a JTA TransactionManager for suspending a transaction: "
0999:                                    + "specify the 'transactionManager' or 'transactionManagerName' property");
1000:                }
1001:                return getTransactionManager().suspend();
1002:            }
1003:
1004:            protected void doResume(Object transaction,
1005:                    Object suspendedResources) {
1006:                JtaTransactionObject txObject = (JtaTransactionObject) transaction;
1007:                try {
1008:                    doJtaResume(txObject, suspendedResources);
1009:                } catch (InvalidTransactionException ex) {
1010:                    throw new IllegalTransactionStateException(
1011:                            "Tried to resume invalid JTA transaction", ex);
1012:                } catch (SystemException ex) {
1013:                    throw new TransactionSystemException(
1014:                            "JTA failure on resume", ex);
1015:                }
1016:            }
1017:
1018:            /**
1019:             * Perform a JTA resume on the JTA TransactionManager.
1020:             * <p>Can be overridden in subclasses, for specific JTA implementations.
1021:             * @param txObject the JtaTransactionObject containing the UserTransaction
1022:             * @param suspendedTransaction the suspended JTA Transaction object
1023:             * @throws InvalidTransactionException if thrown by JTA methods
1024:             * @throws SystemException if thrown by JTA methods
1025:             * @see #getTransactionManager()
1026:             * @see javax.transaction.TransactionManager#resume(javax.transaction.Transaction)
1027:             */
1028:            protected void doJtaResume(JtaTransactionObject txObject,
1029:                    Object suspendedTransaction)
1030:                    throws InvalidTransactionException, SystemException {
1031:
1032:                if (getTransactionManager() == null) {
1033:                    throw new TransactionSuspensionNotSupportedException(
1034:                            "JtaTransactionManager needs a JTA TransactionManager for suspending a transaction: "
1035:                                    + "specify the 'transactionManager' or 'transactionManagerName' property");
1036:                }
1037:                getTransactionManager().resume(
1038:                        (Transaction) suspendedTransaction);
1039:            }
1040:
1041:            /**
1042:             * This implementation returns "true": a JTA commit will properly handle
1043:             * transactions that have been marked rollback-only at a global level.
1044:             */
1045:            protected boolean shouldCommitOnGlobalRollbackOnly() {
1046:                return true;
1047:            }
1048:
1049:            protected void doCommit(DefaultTransactionStatus status) {
1050:                JtaTransactionObject txObject = (JtaTransactionObject) status
1051:                        .getTransaction();
1052:                try {
1053:                    txObject.getUserTransaction().commit();
1054:                } catch (RollbackException ex) {
1055:                    throw new UnexpectedRollbackException(
1056:                            "JTA transaction unexpectedly rolled back (maybe due to a timeout)",
1057:                            ex);
1058:                } catch (HeuristicMixedException ex) {
1059:                    throw new HeuristicCompletionException(
1060:                            HeuristicCompletionException.STATE_MIXED, ex);
1061:                } catch (HeuristicRollbackException ex) {
1062:                    throw new HeuristicCompletionException(
1063:                            HeuristicCompletionException.STATE_ROLLED_BACK, ex);
1064:                } catch (SystemException ex) {
1065:                    throw new TransactionSystemException(
1066:                            "JTA failure on commit", ex);
1067:                }
1068:            }
1069:
1070:            protected void doRollback(DefaultTransactionStatus status) {
1071:                JtaTransactionObject txObject = (JtaTransactionObject) status
1072:                        .getTransaction();
1073:                try {
1074:                    if (txObject.getUserTransaction().getStatus() != Status.STATUS_NO_TRANSACTION) {
1075:                        txObject.getUserTransaction().rollback();
1076:                    }
1077:                } catch (SystemException ex) {
1078:                    throw new TransactionSystemException(
1079:                            "JTA failure on rollback", ex);
1080:                }
1081:            }
1082:
1083:            protected void doSetRollbackOnly(DefaultTransactionStatus status) {
1084:                JtaTransactionObject txObject = (JtaTransactionObject) status
1085:                        .getTransaction();
1086:                if (status.isDebug()) {
1087:                    logger.debug("Setting JTA transaction rollback-only");
1088:                }
1089:                try {
1090:                    if (txObject.getUserTransaction().getStatus() != Status.STATUS_NO_TRANSACTION) {
1091:                        txObject.getUserTransaction().setRollbackOnly();
1092:                    }
1093:                } catch (IllegalStateException ex) {
1094:                    throw new NoTransactionException(
1095:                            "No active JTA transaction");
1096:                } catch (SystemException ex) {
1097:                    throw new TransactionSystemException(
1098:                            "JTA failure on setRollbackOnly", ex);
1099:                }
1100:            }
1101:
1102:            protected void registerAfterCompletionWithExistingTransaction(
1103:                    Object transaction, List synchronizations) {
1104:                JtaTransactionObject txObject = (JtaTransactionObject) transaction;
1105:                logger
1106:                        .debug("Registering after-completion synchronization with existing JTA transaction");
1107:                try {
1108:                    doRegisterAfterCompletionWithJtaTransaction(txObject,
1109:                            synchronizations);
1110:                } catch (RollbackException ex) {
1111:                    logger
1112:                            .debug("Participating in existing JTA transaction that has been marked rollback-only: "
1113:                                    + "cannot register Spring after-completion callbacks with outer JTA transaction - "
1114:                                    + "immediately performing Spring after-completion callbacks with outcome status 'rollback'");
1115:                    invokeAfterCompletion(synchronizations,
1116:                            TransactionSynchronization.STATUS_ROLLED_BACK);
1117:                } catch (IllegalStateException ex) {
1118:                    logger
1119:                            .debug("Participating in existing JTA transaction, but no JTA transaction active anymore: "
1120:                                    + "cannot register Spring after-completion callbacks with outer JTA transaction - "
1121:                                    + "processing Spring after-completion callbacks with outcome status 'unknown'");
1122:                    invokeAfterCompletion(synchronizations,
1123:                            TransactionSynchronization.STATUS_UNKNOWN);
1124:                } catch (SystemException ex) {
1125:                    throw new TransactionSystemException(
1126:                            "JTA failure on registerSynchronization", ex);
1127:                }
1128:            }
1129:
1130:            /**
1131:             * Register a JTA synchronization on the JTA TransactionManager, for calling
1132:             * <code>afterCompletion</code> on the given Spring TransactionSynchronizations.
1133:             * <p>The default implementation registers the synchronizations on the
1134:             * JTA 1.1 TransactionSynchronizationRegistry, if available, or on the
1135:             * JTA TransactionManager's current Transaction - again, if available.
1136:             * If none of the two is available, a warning will be logged.
1137:             * <p>Can be overridden in subclasses, for specific JTA implementations.
1138:             * @param txObject the current transaction object
1139:             * @param synchronizations List of TransactionSynchronization objects
1140:             * @throws RollbackException if thrown by JTA methods
1141:             * @throws SystemException if thrown by JTA methods
1142:             * @see #getTransactionManager()
1143:             * @see javax.transaction.Transaction#registerSynchronization
1144:             * @see javax.transaction.TransactionSynchronizationRegistry#registerInterposedSynchronization
1145:             */
1146:            protected void doRegisterAfterCompletionWithJtaTransaction(
1147:                    JtaTransactionObject txObject, List synchronizations)
1148:                    throws RollbackException, SystemException {
1149:
1150:                if (this .transactionSynchronizationRegistry != null) {
1151:                    // JTA 1.1 TransactionSynchronizationRegistry available - use it.
1152:                    new InterposedSynchronizationDelegate()
1153:                            .registerInterposedSynchronization(new JtaAfterCompletionSynchronization(
1154:                                    synchronizations));
1155:                }
1156:
1157:                else if (getTransactionManager() != null) {
1158:                    // At least the JTA TransactionManager available - use that one.
1159:                    Transaction transaction = getTransactionManager()
1160:                            .getTransaction();
1161:                    if (transaction != null) {
1162:                        transaction
1163:                                .registerSynchronization(new JtaAfterCompletionSynchronization(
1164:                                        synchronizations));
1165:                    } else {
1166:                        // No current JTA Transaction available - log a warning.
1167:                        logger
1168:                                .debug("Participating in existing JTA transaction, but no current JTA Transaction available: "
1169:                                        + "cannot register Spring after-completion callbacks with outer JTA transaction - "
1170:                                        + "processing Spring after-completion callbacks with outcome status 'unknown'");
1171:                        invokeAfterCompletion(synchronizations,
1172:                                TransactionSynchronization.STATUS_UNKNOWN);
1173:                    }
1174:                }
1175:
1176:                else {
1177:                    // No JTA TransactionManager available - log a warning.
1178:                    logger
1179:                            .warn("Participating in existing JTA transaction, but no JTA TransactionManager available: "
1180:                                    + "cannot register Spring after-completion callbacks with outer JTA transaction - "
1181:                                    + "processing Spring after-completion callbacks with outcome status 'unknown'");
1182:                    invokeAfterCompletion(synchronizations,
1183:                            TransactionSynchronization.STATUS_UNKNOWN);
1184:                }
1185:            }
1186:
1187:            //---------------------------------------------------------------------
1188:            // Implementation of TransactionFactory interface
1189:            //---------------------------------------------------------------------
1190:
1191:            public Transaction createTransaction(String name, int timeout)
1192:                    throws NotSupportedException, SystemException {
1193:                TransactionManager tm = getTransactionManager();
1194:                Assert.state(tm != null, "No JTA TransactionManager available");
1195:                if (timeout >= 0) {
1196:                    tm.setTransactionTimeout(timeout);
1197:                }
1198:                tm.begin();
1199:                return tm.getTransaction();
1200:            }
1201:
1202:            //---------------------------------------------------------------------
1203:            // Serialization support
1204:            //---------------------------------------------------------------------
1205:
1206:            private void readObject(ObjectInputStream ois) throws IOException,
1207:                    ClassNotFoundException {
1208:                // Rely on default serialization; just initialize state after deserialization.
1209:                ois.defaultReadObject();
1210:
1211:                // Create template for client-side JNDI lookup.
1212:                this .jndiTemplate = new JndiTemplate();
1213:
1214:                // Perform a fresh lookup for JTA handles.
1215:                initUserTransactionAndTransactionManager();
1216:                initTransactionSynchronizationRegistry();
1217:            }
1218:
1219:            /**
1220:             * Inner class to avoid a direct dependency on the JTA 1.1 API
1221:             * (javax.transaction.TransactionSynchronizationRegistry interface).
1222:             */
1223:            private class InterposedSynchronizationDelegate {
1224:
1225:                public void registerInterposedSynchronization(
1226:                        Synchronization synch) {
1227:                    ((TransactionSynchronizationRegistry) transactionSynchronizationRegistry)
1228:                            .registerInterposedSynchronization(synch);
1229:                }
1230:            }
1231:
1232:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.