diff --git a/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/tx-decl-explained.adoc b/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/tx-decl-explained.adoc index f59bb26b0005..e27f496de9fe 100644 --- a/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/tx-decl-explained.adoc +++ b/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/tx-decl-explained.adoc @@ -38,6 +38,11 @@ within the method. A reactive transaction managed by `ReactiveTransactionManager` uses the Reactor context instead of thread-local attributes. As a consequence, all participating data access operations need to execute within the same Reactor context in the same reactive pipeline. + +When configured with a `ReactiveTransactionManager`, all transaction-demarcated methods +are expected to return a reactive pipeline. Void methods or regular return types need +to be associated with a regular `PlatformTransactionManager`, e.g. through the +`transactionManager` attribute of the corresponding `@Transactional` declarations. ==== The following image shows a conceptual view of calling a method on a transactional proxy: diff --git a/spring-tx/src/main/java/org/springframework/transaction/annotation/Transactional.java b/spring-tx/src/main/java/org/springframework/transaction/annotation/Transactional.java index e0372ba45c79..8ca962a0590a 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/annotation/Transactional.java +++ b/spring-tx/src/main/java/org/springframework/transaction/annotation/Transactional.java @@ -105,6 +105,11 @@ * all participating data access operations need to execute within the same * Reactor context in the same reactive pipeline. * + *

Note: When configured with a {@code ReactiveTransactionManager}, all + * transaction-demarcated methods are expected to return a reactive pipeline. + * Void methods or regular return types need to be associated with a regular + * {@code PlatformTransactionManager}, e.g. through {@link #transactionManager()}. + * * @author Colin Sampaleanu * @author Juergen Hoeller * @author Sam Brannen diff --git a/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java b/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java index 185c362c8969..608482d9e298 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java +++ b/spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java @@ -358,8 +358,8 @@ protected Object invokeWithinTransaction(Method method, @Nullable Class targe (isSuspendingFunction ? (hasSuspendingFlowReturnType ? Flux.class : Mono.class) : method.getReturnType()); ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(reactiveType); if (adapter == null) { - throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " + - method.getReturnType()); + throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type [" + + method.getReturnType() + "] with specified transaction manager: " + tm); } return new ReactiveTransactionSupport(adapter); });