|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.springframework.transaction.support.AbstractPlatformTransactionManager org.springframework.transaction.jta.JtaTransactionManager
public class JtaTransactionManager
PlatformTransactionManager implementation for JTA, i.e. J2EE container transactions. Can also work with a locally configured JTA implementation.
This transaction manager is appropriate for handling distributed transactions, i.e. transactions that span multiple resources, and for managing transactions on a J2EE Connector (e.g. a persistence toolkit registered as JCA Connector). For a single JDBC DataSource, DataSourceTransactionManager is perfectly sufficient, and for accessing a single resource with Hibernate (including transactional cache), HibernateTransactionManager is appropriate.
Transaction synchronization is active by default, to allow data access support classes to register resources that are opened within the transaction for closing at transaction completion time. Spring's support classes for JDBC, Hibernate and JDO all perform such registration, allowing for reuse of the same Hibernate Session etc within the transaction. Standard JTA does not even guarantee that for Connections from a transactional JDBC DataSource: Spring's synchronization solves those issues.
Synchronization is also leveraged for transactional cache handling with Hibernate. Therefore, as long as JtaTransactionManager drives the JTA transactions, there is no need to configure Hibernate's JTATransaction strategy or a container-specific Hibernate TransactionManagerLookup. However, certain JTA implementations are restrictive in terms of what JDBC calls they allow after transaction completion, complaining even on close calls: In that case, it is indeed necessary to configure a Hibernate TransactionManagerLookup, potentially via Spring's LocalSessionFactoryBean.
If JtaTransactionManager participates in an existing JTA transaction, e.g. from EJB CMT, synchronization will be triggered on finishing the nested transaction, before passing transaction control back to the J2EE container. In this case, a container-specific Hibernate TransactionManagerLookup is the only way to achieve exact afterCompletion callbacks for transactional cache handling with Hibernate.
For typical JTA transactions (REQUIRED, SUPPORTS, MANDATORY, NEVER), a plain JtaTransactionManager definition is all you need, completely portable across all J2EE servers. This corresponds to the functionality of the JTA UserTransaction, for which J2EE specifies a standard JNDI name ("java:comp/UserTransaction"). There is no need to configure a server-specific TransactionManager lookup for this kind of JTA usage.
Note: Advanced JTA usage below. Dealing with these mechanisms is not necessary for typical usage scenarios.
Transaction suspension (REQUIRES_NEW, NOT_SUPPORTED) is just available with a JTA TransactionManager being registered, via the "transactionManagerName" or "transactionManager" property. The location of this internal JTA object is not specified by J2EE; it is individual for each J2EE server, often kept in JNDI like the UserTransaction. Some well-known JNDI locations are:
Both of these cases are autodetected by JtaTransactionManager, provided that the "autodetectTransactionManager" flag is set to "true" (which it is by default). Consequently, JtaTransactionManager will support transaction suspension out-of-the-box on many J2EE servers.
A JNDI lookup can also be factored out into a corresponding JndiObjectFactoryBean, passed into JtaTransactionManager's "transactionManager" property. Such a bean definition can then be reused by other objects, for example Spring's LocalSessionFactoryBean for Hibernate (see below).
For IBM WebSphere and standalone JOTM, static accessor methods are required to obtain the JTA TransactionManager: Therefore, WebSphere and JOTM have their own FactoryBean implementations, to be wired with the "transactionManager" property. In case of JotmFactoryBean, the same JTA object implements UserTransaction too: Therefore, passing the object to the "userTransaction" property is sufficient.
It is also possible to specify a JTA TransactionManager only, either through the corresponding constructor or through the "transactionManager" property. In the latter case, the "userTransactionName" property needs to be set to null, to avoid a "java:comp/UserTransaction" JNDI lookup and thus enforcing to build a UserTransaction handle for the given JTA TransactionManager.
Note: Support for the JTA TransactionManager interface is not required by J2EE. Almost all J2EE servers expose it, but do so as extension to J2EE. There might be some issues with compatibility, despite the TransactionManager interface being part of JTA. The only currently known problem is resuming a transaction on WebLogic, which by default fails if the suspended transaction was marked rollback-only; for other usages, it works properly. Use Spring's WebLogicJtaTransactionManager to enforce a resume in any case.
The JTA TransactionManager can also be used to register custom synchronizations with the JTA transaction itself instead of Spring's transaction manager. This is particularly useful for closing resources with strict JTA implementations such as Weblogic's or WebSphere's that do not allow any access to resources after transaction completion, not even for cleanup. For example, Hibernate access is affected by this issue, as outlined above in the discussion of transaction synchronization.
Spring's LocalSessionFactoryBean for Hibernate supports plugging a given JTA TransactionManager into Hibernate's TransactionManagerLookup mechanism, for Hibernate-driven cache synchronization and proper cleanup without warnings. The same JTA TransactionManager configuration as above can be used in this case (with a JndiObjectFactoryBean for a JNDI lookup, or one of the FactoryBeans), avoiding double configuration. Alternatively, specify corresponding Hibernate properties (see Hibernate docs for details).
This standard JtaTransactionManager supports timeouts but not per-transaction
isolation levels. Custom subclasses can override doJtaBegin
for
specific JTA implementations to provide this functionality; Spring includes a
corresponding WebLogicJtaTransactionManager class, for example. Such adapters
for specific J2EE transaction coordinators can also expose transaction names
for monitoring; with standard JTA, transaction names will be ignored.
Consider using WebLogicJtaTransactionManager on BEA WebLogic, which supports the full power of Spring's transaction definitions on WebLogic's transaction coordinator, beyond standard JTA: transaction names, per-transaction isolation levels, and proper resuming of transactions in all cases. WebLogicJtaTransactionManager automatically adapts to WebLogic 7.0 or 8.1+.
This class is serializable. Active synchronizations do not survive serialization, though.
setUserTransactionName(java.lang.String)
,
setUserTransaction(javax.transaction.UserTransaction)
,
setTransactionManagerName(java.lang.String)
,
setTransactionManager(javax.transaction.TransactionManager)
,
doJtaBegin(org.springframework.transaction.TransactionDefinition)
,
JotmFactoryBean
,
WebSphereTransactionManagerFactoryBean
,
WebLogicJtaTransactionManager
,
JndiObjectFactoryBean
,
LocalSessionFactoryBean.setJtaTransactionManager(javax.transaction.TransactionManager)
,
Serialized FormField Summary | |
---|---|
static String |
DEFAULT_USER_TRANSACTION_NAME
Default JNDI location for the JTA UserTransaction. |
static String |
FALLBACK_TRANSACTION_MANAGER_NAME
Fallback JNDI location for the JTA TransactionManager. |
Fields inherited from class org.springframework.transaction.support.AbstractPlatformTransactionManager |
---|
logger, SYNCHRONIZATION_ALWAYS, SYNCHRONIZATION_NEVER, SYNCHRONIZATION_ON_ACTUAL_TRANSACTION |
Constructor Summary | |
---|---|
JtaTransactionManager()
Create a new JtaTransactionManager instance, to be configured as bean. |
|
JtaTransactionManager(TransactionManager transactionManager)
Create a new JtaTransactionManager instance. |
|
JtaTransactionManager(UserTransaction userTransaction)
Create a new JtaTransactionManager instance. |
|
JtaTransactionManager(UserTransaction userTransaction,
TransactionManager transactionManager)
Create a new JtaTransactionManager instance. |
Method Summary | |
---|---|
void |
afterPropertiesSet()
Invoked by a BeanFactory after it has set all bean properties supplied (and satisfied BeanFactoryAware and ApplicationContextAware). |
protected void |
applyIsolationLevel(int isolationLevel)
Apply the given transaction isolation level. |
protected void |
applyTimeout(int timeout)
Apply the given transaction timeout. |
protected void |
doBegin(Object transaction,
TransactionDefinition definition)
Begin a new transaction with the given transaction definition. |
protected void |
doCommit(DefaultTransactionStatus status)
Perform an actual commit of the given transaction. |
protected Object |
doGetTransaction()
This implementation returns a JtaTransactionObject instance for the JTA UserTransaction. |
protected void |
doJtaBegin(TransactionDefinition definition)
Perform a JTA begin on the JTA UserTransaction or TransactionManager. |
protected void |
doJtaResume(Transaction suspendedTransaction)
Perform a JTA resume on the JTA TransactionManager. |
protected Transaction |
doJtaSuspend()
Perform a JTA suspend on the JTA TransactionManager. |
protected void |
doResume(Object transaction,
Object suspendedResources)
Resume the resources of the current transaction. |
protected void |
doRollback(DefaultTransactionStatus status)
Perform an actual rollback of the given transaction. |
protected void |
doSetRollbackOnly(DefaultTransactionStatus status)
Set the given transaction rollback-only. |
protected Object |
doSuspend(Object transaction)
Suspend the resources of the current transaction. |
Properties |
getJndiEnvironment()
Return the JNDI environment to use for JNDI lookups. |
JndiTemplate |
getJndiTemplate()
Return the JndiTemplate used for JNDI lookups. |
TransactionManager |
getTransactionManager()
Return the JTA TransactionManager that this transaction manager uses. |
UserTransaction |
getUserTransaction()
Return the JTA UserTransaction that this transaction manager uses. |
protected boolean |
isExistingTransaction(Object transaction)
Check if the given transaction object indicates an existing transaction (that is, a transaction which has already started). |
protected TransactionManager |
lookupTransactionManager(String transactionManagerName)
Look up the JTA TransactionManager in JNDI via the configured name. |
protected UserTransaction |
lookupUserTransaction(String userTransactionName)
Look up the JTA UserTransaction in JNDI via the configured name. |
protected TransactionManager |
retrieveTransactionManager()
Allows subclasses to retrieve the JTA TransactionManager in a vendor-specific manner. |
protected UserTransaction |
retrieveUserTransaction()
Allows subclasses to retrieve the JTA UserTransaction in a vendor-specific manner. |
void |
setAutodetectTransactionManager(boolean autodetectTransactionManager)
Set whether to autodetect a JTA UserTransaction object that implements the JTA TransactionManager interface too (i.e. the JNDI location for the TransactionManager is "java:comp/UserTransaction", same as for the UserTransaction). |
void |
setJndiEnvironment(Properties jndiEnvironment)
Set the JNDI environment to use for JNDI lookups. |
void |
setJndiTemplate(JndiTemplate jndiTemplate)
Set the JndiTemplate to use for JNDI lookups. |
void |
setTransactionManager(TransactionManager transactionManager)
Set the JTA TransactionManager to use as direct reference. |
void |
setTransactionManagerName(String transactionManagerName)
Set the JNDI name of the JTA TransactionManager. |
void |
setUserTransaction(UserTransaction userTransaction)
Set the JTA UserTransaction to use as direct reference. |
void |
setUserTransactionName(String userTransactionName)
Set the JNDI name of the JTA UserTransaction. |
protected boolean |
shouldCommitOnGlobalRollbackOnly()
This implementation returns "true": a JTA commit will properly handle transactions that have been marked rollback-only at a global level. |
protected boolean |
useSavepointForNestedTransaction()
This implementation returns false to cause a further invocation of doBegin despite an already existing transaction. |
Methods inherited from class org.springframework.transaction.support.AbstractPlatformTransactionManager |
---|
commit, doCleanupAfterCompletion, getTransaction, getTransactionSynchronization, isNestedTransactionAllowed, isRollbackOnCommitFailure, rollback, setNestedTransactionAllowed, setRollbackOnCommitFailure, setTransactionSynchronization, setTransactionSynchronizationName |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
public static final String DEFAULT_USER_TRANSACTION_NAME
setUserTransactionName(java.lang.String)
,
setAutodetectTransactionManager(boolean)
,
Constant Field Valuespublic static final String FALLBACK_TRANSACTION_MANAGER_NAME
setTransactionManagerName(java.lang.String)
,
setAutodetectTransactionManager(boolean)
,
Constant Field ValuesConstructor Detail |
---|
public JtaTransactionManager()
setUserTransactionName(java.lang.String)
,
setUserTransaction(javax.transaction.UserTransaction)
,
setTransactionManagerName(java.lang.String)
,
setTransactionManager(javax.transaction.TransactionManager)
,
afterPropertiesSet()
public JtaTransactionManager(UserTransaction userTransaction)
userTransaction
- the JTA UserTransaction to use as direct referencepublic JtaTransactionManager(UserTransaction userTransaction, TransactionManager transactionManager)
userTransaction
- the JTA UserTransaction to use as direct referencetransactionManager
- the JTA TransactionManager to use as direct referencepublic JtaTransactionManager(TransactionManager transactionManager)
transactionManager
- the JTA TransactionManager to use as direct referenceMethod Detail |
---|
public void setJndiTemplate(JndiTemplate jndiTemplate)
public JndiTemplate getJndiTemplate()
public void setJndiEnvironment(Properties jndiEnvironment)
setJndiTemplate(org.springframework.jndi.JndiTemplate)
public Properties getJndiEnvironment()
public void setUserTransactionName(String userTransactionName)
DEFAULT_USER_TRANSACTION_NAME
,
setUserTransaction(javax.transaction.UserTransaction)
public void setUserTransaction(UserTransaction userTransaction)
setUserTransactionName(java.lang.String)
public UserTransaction getUserTransaction()
public void setTransactionManagerName(String transactionManagerName)
A TransactionManager is necessary for suspending and resuming transactions, as this not supported by the UserTransaction interface.
Note that the TransactionManager will be autodetected if the JTA UserTransaction object implements the JTA TransactionManager interface too.
setTransactionManager(javax.transaction.TransactionManager)
public void setTransactionManager(TransactionManager transactionManager)
A TransactionManager is necessary for suspending and resuming transactions, as this not supported by the UserTransaction interface.
Note that the TransactionManager will be autodetected if the JTA UserTransaction object implements the JTA TransactionManager interface too.
setTransactionManagerName(java.lang.String)
,
setAutodetectTransactionManager(boolean)
public TransactionManager getTransactionManager()
public void setAutodetectTransactionManager(boolean autodetectTransactionManager)
Default is true. Can be turned off to deliberately ignore an available TransactionManager, for example when there are known issues with suspend/resume and any attempt to use REQUIRES_NEW or NOT_SUPPORTED should fail fast.
FALLBACK_TRANSACTION_MANAGER_NAME
public void afterPropertiesSet() throws TransactionSystemException
InitializingBean
This method allows the bean instance to perform initialization only possible when all bean properties have been set and to throw an exception in the event of misconfiguration.
afterPropertiesSet
in interface InitializingBean
TransactionSystemException
protected UserTransaction lookupUserTransaction(String userTransactionName) throws TransactionSystemException
userTransactionName
- the JNDI name of the UserTransaction
TransactionSystemException
- if the JNDI lookup failedsetJndiTemplate(org.springframework.jndi.JndiTemplate)
,
setUserTransactionName(java.lang.String)
protected TransactionManager lookupTransactionManager(String transactionManagerName) throws TransactionSystemException
transactionManagerName
- the JNDI name of the TransactionManager
TransactionSystemException
- if the JNDI lookup failedsetJndiTemplate(org.springframework.jndi.JndiTemplate)
,
setTransactionManagerName(java.lang.String)
protected UserTransaction retrieveUserTransaction() throws TransactionSystemException
Default implementation simply returns null.
TransactionSystemException
- in case of errorssetUserTransaction(javax.transaction.UserTransaction)
,
setUserTransactionName(java.lang.String)
protected TransactionManager retrieveTransactionManager() throws TransactionSystemException
Default implementation simply returns null.
TransactionSystemException
- in case of errorssetTransactionManager(javax.transaction.TransactionManager)
,
setTransactionManagerName(java.lang.String)
protected Object doGetTransaction()
Note that JtaTransactionManager doesn't need a transaction object, as it will access the JTA UserTransaction and/or TransactionManager singletons that it holds directly. Therefore, any transaction object that's useful for status and identification purposes will do.
doGetTransaction
in class AbstractPlatformTransactionManager
AbstractPlatformTransactionManager.doBegin(java.lang.Object, org.springframework.transaction.TransactionDefinition)
,
AbstractPlatformTransactionManager.doCommit(org.springframework.transaction.support.DefaultTransactionStatus)
,
AbstractPlatformTransactionManager.doRollback(org.springframework.transaction.support.DefaultTransactionStatus)
,
DefaultTransactionStatus.getTransaction()
protected boolean isExistingTransaction(Object transaction)
AbstractPlatformTransactionManager
The result will be evaluated according to the specified propagation behavior for the new transaction. An existing transaction might get suspended (in case of PROPAGATION_REQUIRES_NEW), or the new transaction might participate in the existing one (in case of PROPAGATION_REQUIRED).
Default implementation returns false, assuming that detection of or participating in existing transactions is generally not supported. Subclasses are of course encouraged to provide such support.
isExistingTransaction
in class AbstractPlatformTransactionManager
transaction
- transaction object returned by doGetTransaction
AbstractPlatformTransactionManager.doGetTransaction()
protected boolean useSavepointForNestedTransaction()
JTA implementations might support nested transactions via further
UserTransaction.begin
invocations, but never support savepoints.
useSavepointForNestedTransaction
in class AbstractPlatformTransactionManager
doBegin(java.lang.Object, org.springframework.transaction.TransactionDefinition)
,
UserTransaction.begin()
protected void doBegin(Object transaction, TransactionDefinition definition)
AbstractPlatformTransactionManager
doBegin
in class AbstractPlatformTransactionManager
transaction
- transaction object returned by doGetTransactiondefinition
- TransactionDefinition instance, describing
propagation behavior, isolation level, timeout etc.protected void doJtaBegin(TransactionDefinition definition) throws NotSupportedException, SystemException
This implementation only supports standard JTA functionality: that is, no per-transaction isolation levels and no transaction names. Can be overridden in subclasses, for specific JTA implementations.
Calls applyIsolationLevel
and applyTimeout
before invoking the UserTransaction's begin
method.
NotSupportedException
- if thrown by JTA methods
SystemException
- if thrown by JTA methodsgetUserTransaction()
,
getTransactionManager()
,
applyIsolationLevel(int)
,
applyTimeout(int)
,
UserTransaction.setTransactionTimeout(int)
,
UserTransaction.begin()
protected void applyIsolationLevel(int isolationLevel) throws InvalidIsolationLevelException, SystemException
To be overridden in subclasses for specific JTA implementations,
as alternative to overriding the full doJtaBegin
method.
isolationLevel
- isolation level taken from transaction definition
InvalidIsolationLevelException
- if the given isolation level
cannot be applied
SystemException
- if thrown by the JTA implementationdoJtaBegin(org.springframework.transaction.TransactionDefinition)
,
getUserTransaction()
,
getTransactionManager()
protected void applyTimeout(int timeout) throws SystemException
setTransactionTimeout
for a non-default timeout value.
timeout
- timeout value taken from transaction definition
SystemException
- if thrown by the JTA implementationdoJtaBegin(org.springframework.transaction.TransactionDefinition)
,
getUserTransaction()
,
UserTransaction.setTransactionTimeout(int)
protected Object doSuspend(Object transaction)
AbstractPlatformTransactionManager
Default implementation throws a TransactionSuspensionNotSupportedException, assuming that transaction suspension is generally not supported.
doSuspend
in class AbstractPlatformTransactionManager
transaction
- transaction object returned by doGetTransaction
AbstractPlatformTransactionManager.doResume(java.lang.Object, java.lang.Object)
protected Transaction doJtaSuspend() throws SystemException
Can be overridden in subclasses, for specific JTA implementations.
SystemException
- if thrown by JTA methodsgetTransactionManager()
,
TransactionManager.suspend()
protected void doResume(Object transaction, Object suspendedResources)
AbstractPlatformTransactionManager
Default implementation throws a TransactionSuspensionNotSupportedException, assuming that transaction suspension is generally not supported.
doResume
in class AbstractPlatformTransactionManager
transaction
- transaction object returned by doGetTransactionsuspendedResources
- the object that holds suspended resources,
as returned by doSuspendAbstractPlatformTransactionManager.doSuspend(java.lang.Object)
protected void doJtaResume(Transaction suspendedTransaction) throws InvalidTransactionException, SystemException
Can be overridden in subclasses, for specific JTA implementations.
suspendedTransaction
- the suspended JTA Transaction object
InvalidTransactionException
- if thrown by JTA methods
SystemException
- if thrown by JTA methodsgetTransactionManager()
,
TransactionManager.resume(javax.transaction.Transaction)
protected boolean shouldCommitOnGlobalRollbackOnly()
shouldCommitOnGlobalRollbackOnly
in class AbstractPlatformTransactionManager
AbstractPlatformTransactionManager.doCommit(org.springframework.transaction.support.DefaultTransactionStatus)
,
DefaultTransactionStatus.isGlobalRollbackOnly()
,
DefaultTransactionStatus.isLocalRollbackOnly()
,
TransactionStatus.setRollbackOnly()
,
UnexpectedRollbackException
,
UserTransaction.commit()
,
RollbackException
protected void doCommit(DefaultTransactionStatus status)
AbstractPlatformTransactionManager
An implementation does not need to check the "new transaction" flag or the rollback-only flag; this will already have been handled before. Usually, a straight commit will be performed on the transaction object contained in the passed-in status.
doCommit
in class AbstractPlatformTransactionManager
status
- the status representation of the transactionDefaultTransactionStatus.getTransaction()
protected void doRollback(DefaultTransactionStatus status)
AbstractPlatformTransactionManager
An implementation does not need to check the "new transaction" flag; this will already have been handled before. Usually, a straight rollback will be performed on the transaction object contained in the passed-in status.
doRollback
in class AbstractPlatformTransactionManager
status
- the status representation of the transactionDefaultTransactionStatus.getTransaction()
protected void doSetRollbackOnly(DefaultTransactionStatus status)
AbstractPlatformTransactionManager
Default implementation throws an IllegalTransactionStateException, assuming that participating in existing transactions is generally not supported. Subclasses are of course encouraged to provide such support.
doSetRollbackOnly
in class AbstractPlatformTransactionManager
status
- the status representation of the transaction
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |