Clarify ReactiveTransactionManager exception declarations
Avoid misleading "throws TransactionException" declarations but preserve javadoc "@throws" notes for specific exceptions (with reactive propagation semantics). Closes gh-30817
This commit is contained in:
@@ -30,7 +30,6 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.CannotCreateTransactionException;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.reactive.AbstractReactiveTransactionManager;
|
||||
import org.springframework.transaction.reactive.GenericReactiveTransaction;
|
||||
import org.springframework.transaction.reactive.TransactionSynchronizationManager;
|
||||
@@ -170,7 +169,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doGetTransaction(TransactionSynchronizationManager synchronizationManager) throws TransactionException {
|
||||
protected Object doGetTransaction(TransactionSynchronizationManager synchronizationManager) {
|
||||
ConnectionFactoryTransactionObject txObject = new ConnectionFactoryTransactionObject();
|
||||
ConnectionHolder conHolder = (ConnectionHolder) synchronizationManager.getResource(obtainConnectionFactory());
|
||||
txObject.setConnectionHolder(conHolder, false);
|
||||
@@ -184,7 +183,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
||||
|
||||
@Override
|
||||
protected Mono<Void> doBegin(TransactionSynchronizationManager synchronizationManager, Object transaction,
|
||||
TransactionDefinition definition) throws TransactionException {
|
||||
TransactionDefinition definition) {
|
||||
|
||||
ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject) transaction;
|
||||
|
||||
@@ -275,9 +274,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mono<Object> doSuspend(TransactionSynchronizationManager synchronizationManager, Object transaction)
|
||||
throws TransactionException {
|
||||
|
||||
protected Mono<Object> doSuspend(TransactionSynchronizationManager synchronizationManager, Object transaction) {
|
||||
return Mono.defer(() -> {
|
||||
ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject) transaction;
|
||||
txObject.setConnectionHolder(null);
|
||||
@@ -287,7 +284,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
||||
|
||||
@Override
|
||||
protected Mono<Void> doResume(TransactionSynchronizationManager synchronizationManager,
|
||||
@Nullable Object transaction, Object suspendedResources) throws TransactionException {
|
||||
@Nullable Object transaction, Object suspendedResources) {
|
||||
|
||||
return Mono.defer(() -> {
|
||||
synchronizationManager.bindResource(obtainConnectionFactory(), suspendedResources);
|
||||
@@ -297,7 +294,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
||||
|
||||
@Override
|
||||
protected Mono<Void> doCommit(TransactionSynchronizationManager TransactionSynchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
GenericReactiveTransaction status) {
|
||||
|
||||
ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
@@ -309,7 +306,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
||||
|
||||
@Override
|
||||
protected Mono<Void> doRollback(TransactionSynchronizationManager TransactionSynchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
GenericReactiveTransaction status) {
|
||||
|
||||
ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
@@ -321,7 +318,7 @@ public class R2dbcTransactionManager extends AbstractReactiveTransactionManager
|
||||
|
||||
@Override
|
||||
protected Mono<Void> doSetRollbackOnly(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
GenericReactiveTransaction status) {
|
||||
|
||||
return Mono.fromRunnable(() -> {
|
||||
ConnectionFactoryTransactionObject txObject = (ConnectionFactoryTransactionObject) status.getTransaction();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,6 +46,8 @@ public interface ReactiveTransactionManager extends TransactionManager {
|
||||
* <p>An exception to the above rule is the read-only flag, which should be
|
||||
* ignored if no explicit read-only mode is supported. Essentially, the
|
||||
* read-only flag is just a hint for potential optimization.
|
||||
* <p>Note: In contrast to {@link PlatformTransactionManager}, exceptions
|
||||
* are propagated through the reactive pipeline returned from this method.
|
||||
* @param definition the TransactionDefinition instance,
|
||||
* describing propagation behavior, isolation level, timeout etc.
|
||||
* @return transaction status object representing the new or current transaction
|
||||
@@ -58,8 +60,7 @@ public interface ReactiveTransactionManager extends TransactionManager {
|
||||
* @see TransactionDefinition#getTimeout
|
||||
* @see TransactionDefinition#isReadOnly
|
||||
*/
|
||||
Mono<ReactiveTransaction> getReactiveTransaction(@Nullable TransactionDefinition definition)
|
||||
throws TransactionException;
|
||||
Mono<ReactiveTransaction> getReactiveTransaction(@Nullable TransactionDefinition definition);
|
||||
|
||||
/**
|
||||
* Commit the given transaction, with regard to its status. If the transaction
|
||||
@@ -69,14 +70,12 @@ public interface ReactiveTransactionManager extends TransactionManager {
|
||||
* has been suspended to be able to create a new one, resume the previous
|
||||
* transaction after committing the new one.
|
||||
* <p>Note that when the commit call completes, no matter if normally or
|
||||
* throwing an exception, the transaction must be fully completed and
|
||||
* propagating an exception, the transaction must be fully completed and
|
||||
* cleaned up. No rollback call should be expected in such a case.
|
||||
* <p>If this method throws an exception other than a TransactionException,
|
||||
* then some before-commit error caused the commit attempt to fail. For
|
||||
* example, an O/R Mapping tool might have tried to flush changes to the
|
||||
* database right before commit, with the resulting DataAccessException
|
||||
* causing the transaction to fail. The original exception will be
|
||||
* propagated to the caller of this commit method in such a case.
|
||||
* <p>Note: In contrast to {@link PlatformTransactionManager}, exceptions
|
||||
* are propagated through the reactive pipeline returned from this method.
|
||||
* Also, depending on the transaction manager implementation, {@code commit}
|
||||
* may propagate {@link org.springframework.dao.DataAccessException} as well.
|
||||
* @param transaction object returned by the {@code getTransaction} method
|
||||
* @throws UnexpectedRollbackException in case of an unexpected rollback
|
||||
* that the transaction coordinator initiated
|
||||
@@ -88,7 +87,7 @@ public interface ReactiveTransactionManager extends TransactionManager {
|
||||
* is already completed (that is, committed or rolled back)
|
||||
* @see ReactiveTransaction#setRollbackOnly
|
||||
*/
|
||||
Mono<Void> commit(ReactiveTransaction transaction) throws TransactionException;
|
||||
Mono<Void> commit(ReactiveTransaction transaction);
|
||||
|
||||
/**
|
||||
* Perform a rollback of the given transaction.
|
||||
@@ -96,16 +95,20 @@ public interface ReactiveTransactionManager extends TransactionManager {
|
||||
* participation in the surrounding transaction. If a previous transaction
|
||||
* has been suspended to be able to create a new one, resume the previous
|
||||
* transaction after rolling back the new one.
|
||||
* <p><b>Do not call rollback on a transaction if commit threw an exception.</b>
|
||||
* <p><b>Do not call rollback on a transaction if commit failed.</b>
|
||||
* The transaction will already have been completed and cleaned up when commit
|
||||
* returns, even in case of a commit exception. Consequently, a rollback call
|
||||
* after commit failure will lead to an IllegalTransactionStateException.
|
||||
* <p>Note: In contrast to {@link PlatformTransactionManager}, exceptions
|
||||
* are propagated through the reactive pipeline returned from this method.
|
||||
* Also, depending on the transaction manager implementation, {@code rollback}
|
||||
* may propagate {@link org.springframework.dao.DataAccessException} as well.
|
||||
* @param transaction object returned by the {@code getTransaction} method
|
||||
* @throws TransactionSystemException in case of rollback or system errors
|
||||
* (typically caused by fundamental resource failures)
|
||||
* @throws IllegalTransactionStateException if the given transaction
|
||||
* is already completed (that is, committed or rolled back)
|
||||
*/
|
||||
Mono<Void> rollback(ReactiveTransaction transaction) throws TransactionException;
|
||||
Mono<Void> rollback(ReactiveTransaction transaction);
|
||||
|
||||
}
|
||||
|
||||
@@ -95,9 +95,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* @see #doBegin
|
||||
*/
|
||||
@Override
|
||||
public final Mono<ReactiveTransaction> getReactiveTransaction(@Nullable TransactionDefinition definition)
|
||||
throws TransactionException {
|
||||
|
||||
public final Mono<ReactiveTransaction> getReactiveTransaction(@Nullable TransactionDefinition definition) {
|
||||
// Use defaults if no transaction definition given.
|
||||
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
|
||||
|
||||
@@ -165,7 +163,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* Create a ReactiveTransaction for an existing transaction.
|
||||
*/
|
||||
private Mono<ReactiveTransaction> handleExistingTransaction(TransactionSynchronizationManager synchronizationManager,
|
||||
TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException {
|
||||
TransactionDefinition definition, Object transaction, boolean debugEnabled) {
|
||||
|
||||
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
|
||||
return Mono.error(new IllegalTransactionStateException(
|
||||
@@ -277,7 +275,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* @see #resume
|
||||
*/
|
||||
private Mono<SuspendedResourcesHolder> suspend(TransactionSynchronizationManager synchronizationManager,
|
||||
@Nullable Object transaction) throws TransactionException {
|
||||
@Nullable Object transaction) {
|
||||
|
||||
if (synchronizationManager.isSynchronizationActive()) {
|
||||
Mono<List<TransactionSynchronization>> suspendedSynchronizations = doSuspendSynchronization(synchronizationManager);
|
||||
@@ -325,8 +323,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* @see #suspend
|
||||
*/
|
||||
private Mono<Void> resume(TransactionSynchronizationManager synchronizationManager,
|
||||
@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
|
||||
throws TransactionException {
|
||||
@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder) {
|
||||
|
||||
Mono<Void> resume = Mono.empty();
|
||||
|
||||
@@ -403,7 +400,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* @see #rollback
|
||||
*/
|
||||
@Override
|
||||
public final Mono<Void> commit(ReactiveTransaction transaction) throws TransactionException {
|
||||
public final Mono<Void> commit(ReactiveTransaction transaction) {
|
||||
if (transaction.isCompleted()) {
|
||||
return Mono.error(new IllegalTransactionStateException(
|
||||
"Transaction is already completed - do not call commit or rollback more than once per transaction"));
|
||||
@@ -426,10 +423,9 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* Rollback-only flags have already been checked and applied.
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status object representing the transaction
|
||||
* @throws TransactionException in case of commit failure
|
||||
*/
|
||||
private Mono<Void> processCommit(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
GenericReactiveTransaction status) {
|
||||
|
||||
AtomicBoolean beforeCompletionInvoked = new AtomicBoolean();
|
||||
|
||||
@@ -489,7 +485,7 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* @see #doSetRollbackOnly
|
||||
*/
|
||||
@Override
|
||||
public final Mono<Void> rollback(ReactiveTransaction transaction) throws TransactionException {
|
||||
public final Mono<Void> rollback(ReactiveTransaction transaction) {
|
||||
if (transaction.isCompleted()) {
|
||||
return Mono.error(new IllegalTransactionStateException(
|
||||
"Transaction is already completed - do not call commit or rollback more than once per transaction"));
|
||||
@@ -505,7 +501,6 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* The completed flag has already been checked.
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status object representing the transaction
|
||||
* @throws TransactionException in case of rollback failure
|
||||
*/
|
||||
private Mono<Void> processRollback(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) {
|
||||
@@ -544,11 +539,10 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status object representing the transaction
|
||||
* @param ex the thrown application exception or error
|
||||
* @throws TransactionException in case of rollback failure
|
||||
* @see #doRollback
|
||||
*/
|
||||
private Mono<Void> doRollbackOnCommitException(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status, Throwable ex) throws TransactionException {
|
||||
GenericReactiveTransaction status, Throwable ex) {
|
||||
|
||||
return Mono.defer(() -> {
|
||||
if (status.isNewTransaction()) {
|
||||
@@ -716,14 +710,12 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* @return the current transaction object
|
||||
* @throws org.springframework.transaction.CannotCreateTransactionException
|
||||
* if transaction support is not available
|
||||
* @throws TransactionException in case of lookup or system errors
|
||||
* @see #doBegin
|
||||
* @see #doCommit
|
||||
* @see #doRollback
|
||||
* @see GenericReactiveTransaction#getTransaction
|
||||
*/
|
||||
protected abstract Object doGetTransaction(TransactionSynchronizationManager synchronizationManager)
|
||||
throws TransactionException;
|
||||
protected abstract Object doGetTransaction(TransactionSynchronizationManager synchronizationManager);
|
||||
|
||||
/**
|
||||
* Check if the given transaction object indicates an existing transaction
|
||||
@@ -737,10 +729,9 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* Subclasses are of course encouraged to provide such support.
|
||||
* @param transaction the transaction object returned by doGetTransaction
|
||||
* @return if there is an existing transaction
|
||||
* @throws TransactionException in case of system errors
|
||||
* @see #doGetTransaction
|
||||
*/
|
||||
protected boolean isExistingTransaction(Object transaction) throws TransactionException {
|
||||
protected boolean isExistingTransaction(Object transaction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -759,12 +750,11 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* @param transaction the transaction object returned by {@code doGetTransaction}
|
||||
* @param definition a TransactionDefinition instance, describing propagation
|
||||
* behavior, isolation level, read-only flag, timeout, and transaction name
|
||||
* @throws TransactionException in case of creation or system errors
|
||||
* @throws org.springframework.transaction.NestedTransactionNotSupportedException
|
||||
* if the underlying transaction does not support nesting (e.g. through savepoints)
|
||||
*/
|
||||
protected abstract Mono<Void> doBegin(TransactionSynchronizationManager synchronizationManager,
|
||||
Object transaction, TransactionDefinition definition) throws TransactionException;
|
||||
Object transaction, TransactionDefinition definition);
|
||||
|
||||
/**
|
||||
* Suspend the resources of the current transaction.
|
||||
@@ -777,11 +767,10 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* (will be kept unexamined for passing it into doResume)
|
||||
* @throws org.springframework.transaction.TransactionSuspensionNotSupportedException
|
||||
* if suspending is not supported by the transaction manager implementation
|
||||
* @throws TransactionException in case of system errors
|
||||
* @see #doResume
|
||||
*/
|
||||
protected Mono<Object> doSuspend(TransactionSynchronizationManager synchronizationManager,
|
||||
Object transaction) throws TransactionException {
|
||||
Object transaction) {
|
||||
|
||||
throw new TransactionSuspensionNotSupportedException(
|
||||
"Transaction manager [" + getClass().getName() + "] does not support transaction suspension");
|
||||
@@ -798,11 +787,10 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* as returned by doSuspend
|
||||
* @throws org.springframework.transaction.TransactionSuspensionNotSupportedException
|
||||
* if suspending is not supported by the transaction manager implementation
|
||||
* @throws TransactionException in case of system errors
|
||||
* @see #doSuspend
|
||||
*/
|
||||
protected Mono<Void> doResume(TransactionSynchronizationManager synchronizationManager,
|
||||
@Nullable Object transaction, Object suspendedResources) throws TransactionException {
|
||||
@Nullable Object transaction, Object suspendedResources) {
|
||||
|
||||
throw new TransactionSuspensionNotSupportedException(
|
||||
"Transaction manager [" + getClass().getName() + "] does not support transaction suspension");
|
||||
@@ -832,11 +820,10 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* contained in the passed-in status.
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status the status representation of the transaction
|
||||
* @throws TransactionException in case of commit or system errors
|
||||
* @see GenericReactiveTransaction#getTransaction
|
||||
*/
|
||||
protected abstract Mono<Void> doCommit(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException;
|
||||
GenericReactiveTransaction status);
|
||||
|
||||
/**
|
||||
* Perform an actual rollback of the given transaction.
|
||||
@@ -845,11 +832,10 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* will be performed on the transaction object contained in the passed-in status.
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status the status representation of the transaction
|
||||
* @throws TransactionException in case of system errors
|
||||
* @see GenericReactiveTransaction#getTransaction
|
||||
*/
|
||||
protected abstract Mono<Void> doRollback(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException;
|
||||
GenericReactiveTransaction status);
|
||||
|
||||
/**
|
||||
* Set the given transaction rollback-only. Only called on rollback
|
||||
@@ -859,10 +845,9 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* supported. Subclasses are of course encouraged to provide such support.
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param status the status representation of the transaction
|
||||
* @throws TransactionException in case of system errors
|
||||
*/
|
||||
protected Mono<Void> doSetRollbackOnly(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
GenericReactiveTransaction status) {
|
||||
|
||||
throw new IllegalTransactionStateException(
|
||||
"Participating in existing transactions is not supported - when 'isExistingTransaction' " +
|
||||
@@ -880,13 +865,12 @@ public abstract class AbstractReactiveTransactionManager implements ReactiveTran
|
||||
* @param synchronizationManager the synchronization manager bound to the current transaction
|
||||
* @param transaction the transaction object returned by {@code doGetTransaction}
|
||||
* @param synchronizations a List of TransactionSynchronization objects
|
||||
* @throws TransactionException in case of system errors
|
||||
* @see #invokeAfterCompletion(TransactionSynchronizationManager, List, int)
|
||||
* @see TransactionSynchronization#afterCompletion(int)
|
||||
* @see TransactionSynchronization#STATUS_UNKNOWN
|
||||
*/
|
||||
protected Mono<Void> registerAfterCompletionWithExistingTransaction(TransactionSynchronizationManager synchronizationManager,
|
||||
Object transaction, List<TransactionSynchronization> synchronizations) throws TransactionException {
|
||||
Object transaction, List<TransactionSynchronization> synchronizations) {
|
||||
|
||||
logger.debug("Cannot register Spring after-completion synchronization with existing transaction - " +
|
||||
"processing Spring after-completion callbacks immediately, with outcome status 'unknown'");
|
||||
|
||||
Reference in New Issue
Block a user