📄 jtatransactionmanager.java
字号:
/**
* Perform a JTA begin on the JTA UserTransaction or TransactionManager.
* <p>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.
* <p>Calls <code>applyIsolationLevel</code> and <code>applyTimeout</code>
* before invoking the UserTransaction's <code>begin</code> method.
* @param txObject the JtaTransactionObject containing the UserTransaction
* @param definition TransactionDefinition instance, describing propagation
* behavior, isolation level, read-only flag, timeout, and transaction name
* @throws NotSupportedException if thrown by JTA methods
* @throws SystemException if thrown by JTA methods
* @see #getUserTransaction
* @see #getTransactionManager
* @see #applyIsolationLevel
* @see #applyTimeout
* @see JtaTransactionObject#getUserTransaction()
* @see javax.transaction.UserTransaction#setTransactionTimeout
* @see javax.transaction.UserTransaction#begin
*/
protected void doJtaBegin(JtaTransactionObject txObject, TransactionDefinition definition)
throws NotSupportedException, SystemException {
applyIsolationLevel(txObject, definition.getIsolationLevel());
applyTimeout(txObject, definition.getTimeout());
txObject.getUserTransaction().begin();
}
/**
* Apply the given transaction isolation level. The default implementation
* will throw an exception for any level other than ISOLATION_DEFAULT.
* <p>To be overridden in subclasses for specific JTA implementations,
* as alternative to overriding the full <code>doJtaBegin</code> method.
* @param txObject the JtaTransactionObject containing the UserTransaction
* @param isolationLevel isolation level taken from transaction definition
* @throws InvalidIsolationLevelException if the given isolation level
* cannot be applied
* @throws SystemException if thrown by the JTA implementation
* @see #doJtaBegin
* @see JtaTransactionObject#getUserTransaction()
* @see #getTransactionManager()
*/
protected void applyIsolationLevel(JtaTransactionObject txObject, int isolationLevel)
throws InvalidIsolationLevelException, SystemException {
if (isolationLevel != TransactionDefinition.ISOLATION_DEFAULT) {
throw new InvalidIsolationLevelException(
"JtaTransactionManager does not support custom isolation levels");
}
}
/**
* Apply the given transaction timeout. The default implementation will call
* <code>setTransactionTimeout</code> for a non-default timeout value.
* @param txObject the JtaTransactionObject containing the UserTransaction
* @param timeout timeout value taken from transaction definition
* @throws SystemException if thrown by the JTA implementation
* @see #doJtaBegin
* @see JtaTransactionObject#getUserTransaction()
* @see javax.transaction.UserTransaction#setTransactionTimeout(int)
*/
protected void applyTimeout(JtaTransactionObject txObject, int timeout) throws SystemException {
if (timeout > TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getUserTransaction().setTransactionTimeout(timeout);
}
}
protected Object doSuspend(Object transaction) {
JtaTransactionObject txObject = (JtaTransactionObject) transaction;
try {
return doJtaSuspend(txObject);
}
catch (SystemException ex) {
throw new TransactionSystemException("JTA failure on suspend", ex);
}
}
/**
* Perform a JTA suspend on the JTA TransactionManager.
* <p>Can be overridden in subclasses, for specific JTA implementations.
* @param txObject the JtaTransactionObject containing the UserTransaction
* @return the suspended JTA Transaction object
* @throws SystemException if thrown by JTA methods
* @see #getTransactionManager()
* @see javax.transaction.TransactionManager#suspend()
*/
protected Object doJtaSuspend(JtaTransactionObject txObject) throws SystemException {
if (getTransactionManager() == null) {
throw new TransactionSuspensionNotSupportedException(
"JtaTransactionManager needs a JTA TransactionManager for suspending a transaction: " +
"specify the 'transactionManager' or 'transactionManagerName' property");
}
return getTransactionManager().suspend();
}
protected void doResume(Object transaction, Object suspendedResources) {
JtaTransactionObject txObject = (JtaTransactionObject) transaction;
try {
doJtaResume(txObject, suspendedResources);
}
catch (InvalidTransactionException ex) {
throw new IllegalTransactionStateException("Tried to resume invalid JTA transaction", ex);
}
catch (SystemException ex) {
throw new TransactionSystemException("JTA failure on resume", ex);
}
}
/**
* Perform a JTA resume on the JTA TransactionManager.
* <p>Can be overridden in subclasses, for specific JTA implementations.
* @param txObject the JtaTransactionObject containing the UserTransaction
* @param suspendedTransaction the suspended JTA Transaction object
* @throws InvalidTransactionException if thrown by JTA methods
* @throws SystemException if thrown by JTA methods
* @see #getTransactionManager()
* @see javax.transaction.TransactionManager#resume(javax.transaction.Transaction)
*/
protected void doJtaResume(JtaTransactionObject txObject, Object suspendedTransaction)
throws InvalidTransactionException, SystemException {
if (getTransactionManager() == null) {
throw new TransactionSuspensionNotSupportedException(
"JtaTransactionManager needs a JTA TransactionManager for suspending a transaction: " +
"specify the 'transactionManager' or 'transactionManagerName' property");
}
getTransactionManager().resume((Transaction) suspendedTransaction);
}
/**
* This implementation returns "true": a JTA commit will properly handle
* transactions that have been marked rollback-only at a global level.
*/
protected boolean shouldCommitOnGlobalRollbackOnly() {
return true;
}
protected void doCommit(DefaultTransactionStatus status) {
JtaTransactionObject txObject = (JtaTransactionObject) status.getTransaction();
try {
txObject.getUserTransaction().commit();
}
catch (RollbackException ex) {
throw new UnexpectedRollbackException(
"JTA transaction unexpectedly rolled back (maybe due to a timeout)", ex);
}
catch (HeuristicMixedException ex) {
throw new HeuristicCompletionException(HeuristicCompletionException.STATE_MIXED, ex);
}
catch (HeuristicRollbackException ex) {
throw new HeuristicCompletionException(HeuristicCompletionException.STATE_ROLLED_BACK, ex);
}
catch (SystemException ex) {
throw new TransactionSystemException("JTA failure on commit", ex);
}
}
protected void doRollback(DefaultTransactionStatus status) {
JtaTransactionObject txObject = (JtaTransactionObject) status.getTransaction();
try {
if (txObject.getUserTransaction().getStatus() != Status.STATUS_NO_TRANSACTION) {
txObject.getUserTransaction().rollback();
}
}
catch (SystemException ex) {
throw new TransactionSystemException("JTA failure on rollback", ex);
}
}
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
JtaTransactionObject txObject = (JtaTransactionObject) status.getTransaction();
if (status.isDebug()) {
logger.debug("Setting JTA transaction rollback-only");
}
try {
if (txObject.getUserTransaction().getStatus() != Status.STATUS_NO_TRANSACTION) {
txObject.getUserTransaction().setRollbackOnly();
}
}
catch (IllegalStateException ex) {
throw new NoTransactionException("No active JTA transaction");
}
catch (SystemException ex) {
throw new TransactionSystemException("JTA failure on setRollbackOnly", ex);
}
}
protected void registerAfterCompletionWithExistingTransaction(Object transaction, List synchronizations) {
JtaTransactionObject txObject = (JtaTransactionObject) transaction;
logger.debug("Registering after-completion synchronization with existing JTA transaction");
try {
doRegisterAfterCompletionWithJtaTransaction(txObject, synchronizations);
}
catch (RollbackException ex) {
logger.debug("Participating in existing JTA transaction that has been marked rollback-only: " +
"cannot register Spring after-completion callbacks with outer JTA transaction - " +
"immediately performing Spring after-completion callbacks with outcome status 'rollback'");
invokeAfterCompletion(synchronizations, TransactionSynchronization.STATUS_ROLLED_BACK);
}
catch (IllegalStateException ex) {
throw new NoTransactionException("No active JTA transaction");
}
catch (SystemException ex) {
throw new TransactionSystemException("JTA failure on registerSynchronization", ex);
}
}
/**
* Register a JTA synchronization on the JTA TransactionManager, for calling
* <code>afterCompletion</code> on the given Spring TransactionSynchronizations.
* <p>Can be overridden in subclasses, for specific JTA implementations.
* @param synchronizations List of TransactionSynchronization objects
* @throws RollbackException if thrown by JTA methods
* @throws SystemException if thrown by JTA methods
* @see #getTransactionManager()
* @see javax.transaction.Transaction#registerSynchronization
* @see #invokeAfterCompletion(java.util.List, int)
*/
protected void doRegisterAfterCompletionWithJtaTransaction(
JtaTransactionObject txObject, List synchronizations)
throws RollbackException, SystemException {
if (getTransactionManager() != null) {
Transaction transaction = getTransactionManager().getTransaction();
if (transaction != null) {
transaction.registerSynchronization(new JtaAfterCompletionSynchronization(synchronizations));
}
else {
// No current JTA Transaction available.
logger.debug("Participating in existing JTA transaction, but no current JTA Transaction available: " +
"cannot register Spring after-completion callbacks with outer JTA transaction - " +
"processing Spring after-completion callbacks with outcome status 'unknown'");
invokeAfterCompletion(synchronizations, TransactionSynchronization.STATUS_UNKNOWN);
}
}
else {
// No JTA TransactionManager available.
logger.warn("Participating in existing JTA transaction, but no JTA TransactionManager available: " +
"cannot register Spring after-completion callbacks with outer JTA transaction - " +
"processing Spring after-completion callbacks with outcome status 'unknown'");
invokeAfterCompletion(synchronizations, TransactionSynchronization.STATUS_UNKNOWN);
}
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException {
// Rely on default serialization, just initialize state after deserialization.
try {
ois.defaultReadObject();
}
catch (ClassNotFoundException ex) {
throw new IOException(
"Failed to deserialize JtaTransactionManager - check that JTA and Spring transaction " +
"libraries are available on the client side: " + ex.getMessage());
}
// Create template for client-side JNDI lookup.
this.jndiTemplate = new JndiTemplate();
// Perform lookup for JTA UserTransaction and TransactionManager.
if (this.userTransactionName != null) {
this.userTransaction = lookupUserTransaction(this.userTransactionName);
}
if (this.transactionManagerName != null) {
this.transactionManager = lookupTransactionManager(this.transactionManagerName);
}
}
/**
* Adapter for a JTA Synchronization, invoking the <code>afterCompletion</code> of
* Spring TransactionSynchronizations after the outer JTA transaction has completed.
* Applied when participating in an existing (non-Spring) JTA transaction.
*/
private class JtaAfterCompletionSynchronization implements Synchronization {
private final List synchronizations;
public JtaAfterCompletionSynchronization(List synchronizations) {
this.synchronizations = synchronizations;
}
public void beforeCompletion() {
}
public void afterCompletion(int status) {
switch (status) {
case Status.STATUS_COMMITTED:
invokeAfterCompletion(this.synchronizations, TransactionSynchronization.STATUS_COMMITTED);
break;
case Status.STATUS_ROLLEDBACK:
invokeAfterCompletion(this.synchronizations, TransactionSynchronization.STATUS_ROLLED_BACK);
break;
default:
invokeAfterCompletion(this.synchronizations, TransactionSynchronization.STATUS_UNKNOWN);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -