Browse Source

initialize transaction synchronization before doBegin call in order to avoid OutOfMemory failures after resource binding

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1986 50f2f4bb-b051-0410-bef5-90022cba6387
pull/1/head
Juergen Hoeller 17 years ago
parent
commit
614f52073c
  1. 89
      org.springframework.transaction/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java
  2. 11
      org.springframework.transaction/src/main/java/org/springframework/transaction/support/DefaultTransactionStatus.java

89
org.springframework.transaction/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java

@ -361,23 +361,31 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
SuspendedResourcesHolder suspendedResources = suspend(null); SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) { DefaultTransactionStatus status = null;
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try { try {
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition); doBegin(transaction, definition);
return status;
} }
catch (RuntimeException ex) { catch (RuntimeException ex) {
if (status != null && status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();
}
resume(null, suspendedResources); resume(null, suspendedResources);
throw ex; throw ex;
} }
catch (Error err) { catch (Error err) {
if (status != null && status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();
}
resume(null, suspendedResources); resume(null, suspendedResources);
throw err; throw err;
} }
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
} }
else { else {
// Create "empty" transaction: no actual transaction, but potentially synchronization. // Create "empty" transaction: no actual transaction, but potentially synchronization.
@ -414,20 +422,28 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
definition.getName() + "]"); definition.getName() + "]");
} }
SuspendedResourcesHolder suspendedResources = suspend(transaction); SuspendedResourcesHolder suspendedResources = suspend(transaction);
DefaultTransactionStatus status = null;
try { try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition); doBegin(transaction, definition);
return status;
} }
catch (RuntimeException beginEx) { catch (RuntimeException beginEx) {
if (status != null && status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();
}
resumeAfterBeginException(transaction, suspendedResources, beginEx); resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx; throw beginEx;
} }
catch (Error beginErr) { catch (Error beginErr) {
if (status != null && status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();
}
resumeAfterBeginException(transaction, suspendedResources, beginErr); resumeAfterBeginException(transaction, suspendedResources, beginErr);
throw beginErr; throw beginErr;
} }
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
} }
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
@ -452,9 +468,25 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
// Nested transaction through nested begin and commit/rollback calls. // Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here // Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction. // in case of a pre-existing JTA transaction.
doBegin(transaction, definition);
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null); DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, null);
try {
doBegin(transaction, definition);
}
catch (RuntimeException beginEx) {
if (status != null && status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();
}
throw beginEx;
}
catch (Error beginErr) {
if (status != null && status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();
}
throw beginErr;
}
return status;
} }
} }
@ -495,18 +527,27 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
boolean actualNewSynchronization = newSynchronization && boolean actualNewSynchronization = newSynchronization &&
!TransactionSynchronizationManager.isSynchronizationActive(); !TransactionSynchronizationManager.isSynchronizationActive();
if (actualNewSynchronization) { try {
TransactionSynchronizationManager.setActualTransactionActive(transaction != null); if (actualNewSynchronization) {
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel( TransactionSynchronizationManager.setActualTransactionActive(transaction != null);
(definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) ? TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
definition.getIsolationLevel() : null); (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) ?
TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly()); definition.getIsolationLevel() : null);
TransactionSynchronizationManager.setCurrentTransactionName(definition.getName()); TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
TransactionSynchronizationManager.initSynchronization(); TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
TransactionSynchronizationManager.initSynchronization();
}
return new DefaultTransactionStatus(
transaction, newTransaction, actualNewSynchronization,
definition.isReadOnly(), debug, suspendedResources);
}
catch (Error err) {
// Can only really be an OutOfMemoryError...
if (actualNewSynchronization) {
TransactionSynchronizationManager.clear();
}
throw err;
} }
return new DefaultTransactionStatus(
transaction, newTransaction, actualNewSynchronization,
definition.isReadOnly(), debug, suspendedResources);
} }
/** /**
@ -984,7 +1025,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
} }
if (status.getSuspendedResources() != null) { if (status.getSuspendedResources() != null) {
if (status.isDebug()) { if (status.isDebug()) {
logger.debug("Resuming suspended transaction"); logger.debug("Resuming suspended transaction after completion of inner transaction");
} }
resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources()); resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources());
} }
@ -1076,7 +1117,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
* @throws TransactionException in case of creation or system errors * @throws TransactionException in case of creation or system errors
*/ */
protected abstract void doBegin(Object transaction, TransactionDefinition definition) protected abstract void doBegin(Object transaction, TransactionDefinition definition)
throws TransactionException; throws TransactionException;
/** /**
* Suspend the resources of the current transaction. * Suspend the resources of the current transaction.

11
org.springframework.transaction/src/main/java/org/springframework/transaction/support/DefaultTransactionStatus.java

@ -31,10 +31,10 @@ import org.springframework.transaction.SavepointManager;
* <p>Supports delegating savepoint-related methods to a transaction object * <p>Supports delegating savepoint-related methods to a transaction object
* that implements the {@link SavepointManager} interface. * that implements the {@link SavepointManager} interface.
* *
* <p><b>NOTE:</b> This is <i>not</i> intended to be used for other * <p><b>NOTE:</b> This is <i>not</i> intended for use with other PlatformTransactionManager
* PlatformTransactionManager implementations, in particular not for * implementations, in particular not for mock transaction managers in testing environments.
* mock transaction managers. Use {@link SimpleTransactionStatus} or * Use the alternative {@link SimpleTransactionStatus} class or a mock for the plain
* a mock for the plain TransactionStatus interface instead. * {@link org.springframework.transaction.TransactionStatus} interface instead.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 19.01.2004 * @since 19.01.2004
@ -77,7 +77,7 @@ public class DefaultTransactionStatus extends AbstractTransactionStatus {
* for this transaction, if any * for this transaction, if any
*/ */
public DefaultTransactionStatus( public DefaultTransactionStatus(
Object transaction, boolean newTransaction, boolean newSynchronization, Object transaction, boolean newTransaction, boolean newSynchronization,
boolean readOnly, boolean debug, Object suspendedResources) { boolean readOnly, boolean debug, Object suspendedResources) {
this.transaction = transaction; this.transaction = transaction;
@ -88,6 +88,7 @@ public class DefaultTransactionStatus extends AbstractTransactionStatus {
this.suspendedResources = suspendedResources; this.suspendedResources = suspendedResources;
} }
/** /**
* Return the underlying transaction object. * Return the underlying transaction object.
*/ */

Loading…
Cancel
Save