diff --git a/spring-test/src/main/java/org/springframework/test/context/transaction/TestContextTransactionUtils.java b/spring-test/src/main/java/org/springframework/test/context/transaction/TestContextTransactionUtils.java
index ce3271f194..3efba1e16d 100644
--- a/spring-test/src/main/java/org/springframework/test/context/transaction/TestContextTransactionUtils.java
+++ b/spring-test/src/main/java/org/springframework/test/context/transaction/TestContextTransactionUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -29,6 +29,7 @@ import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.lang.Nullable;
import org.springframework.test.context.TestContext;
import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import org.springframework.transaction.interceptor.DelegatingTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
@@ -202,7 +203,14 @@ public abstract class TestContextTransactionUtils {
Assert.state(configurers.size() <= 1,
"Only one TransactionManagementConfigurer may exist in the ApplicationContext");
if (configurers.size() == 1) {
- return configurers.values().iterator().next().annotationDrivenTransactionManager();
+ TransactionManager tm = configurers.values().iterator().next().annotationDrivenTransactionManager();
+ if (tm instanceof PlatformTransactionManager) {
+ return (PlatformTransactionManager) tm;
+ }
+ else {
+ throw new IllegalStateException(
+ "Specified transaction manager is not a PlatformTransactionManager: " + tm);
+ }
}
}
diff --git a/spring-tx/src/main/java/org/springframework/transaction/PlatformTransactionManager.java b/spring-tx/src/main/java/org/springframework/transaction/PlatformTransactionManager.java
index 3723549452..a3806200cc 100644
--- a/spring-tx/src/main/java/org/springframework/transaction/PlatformTransactionManager.java
+++ b/spring-tx/src/main/java/org/springframework/transaction/PlatformTransactionManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -43,7 +43,7 @@ import org.springframework.lang.Nullable;
* @see org.springframework.transaction.interceptor.TransactionInterceptor
* @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean
*/
-public interface PlatformTransactionManager {
+public interface PlatformTransactionManager extends TransactionManager {
/**
* Return a currently active transaction or create a new one, according to
diff --git a/spring-tx/src/main/java/org/springframework/transaction/ReactiveTransactionManager.java b/spring-tx/src/main/java/org/springframework/transaction/ReactiveTransactionManager.java
index 553e4e329f..d9d5b26835 100644
--- a/spring-tx/src/main/java/org/springframework/transaction/ReactiveTransactionManager.java
+++ b/spring-tx/src/main/java/org/springframework/transaction/ReactiveTransactionManager.java
@@ -27,9 +27,8 @@ import reactor.core.publisher.Mono;
* @author Mark Paluch
* @author Juergen Hoeller
* @since 5.2
- * @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean
*/
-public interface ReactiveTransactionManager {
+public interface ReactiveTransactionManager extends TransactionManager {
/**
* Emit a currently active reactive transaction or create a new one, according to
diff --git a/spring-tx/src/main/java/org/springframework/transaction/TransactionManager.java b/spring-tx/src/main/java/org/springframework/transaction/TransactionManager.java
new file mode 100644
index 0000000000..6504495b59
--- /dev/null
+++ b/spring-tx/src/main/java/org/springframework/transaction/TransactionManager.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2002-2019 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.transaction;
+
+/**
+ * Marker interface for Spring transaction manager implementations,
+ * either traditional or reactive.
+ *
+ * @author Juergen Hoeller
+ * @since 5.2
+ * @see PlatformTransactionManager
+ * @see ReactiveTransactionManager
+ */
+public interface TransactionManager {
+
+}
diff --git a/spring-tx/src/main/java/org/springframework/transaction/annotation/AbstractTransactionManagementConfiguration.java b/spring-tx/src/main/java/org/springframework/transaction/annotation/AbstractTransactionManagementConfiguration.java
index 93a88a80f9..460105d9ea 100644
--- a/spring-tx/src/main/java/org/springframework/transaction/annotation/AbstractTransactionManagementConfiguration.java
+++ b/spring-tx/src/main/java/org/springframework/transaction/annotation/AbstractTransactionManagementConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -27,7 +27,7 @@ import org.springframework.context.annotation.Role;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.lang.Nullable;
-import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.config.TransactionManagementConfigUtils;
import org.springframework.transaction.event.TransactionalEventListenerFactory;
import org.springframework.util.CollectionUtils;
@@ -51,7 +51,7 @@ public abstract class AbstractTransactionManagementConfiguration implements Impo
* Default transaction manager, as configured through a {@link TransactionManagementConfigurer}.
*/
@Nullable
- protected PlatformTransactionManager txManager;
+ protected TransactionManager txManager;
@Override
diff --git a/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionManagementConfigurer.java b/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionManagementConfigurer.java
index c7d6a07f46..fdab4eafa7 100644
--- a/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionManagementConfigurer.java
+++ b/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionManagementConfigurer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -16,15 +16,16 @@
package org.springframework.transaction.annotation;
-import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionManager;
/**
* Interface to be implemented by @{@link org.springframework.context.annotation.Configuration
* Configuration} classes annotated with @{@link EnableTransactionManagement} that wish to
- * or need to explicitly specify the default {@link PlatformTransactionManager} bean to be
- * used for annotation-driven transaction management, as opposed to the default approach
- * of a by-type lookup. One reason this might be necessary is if there are two
- * {@code PlatformTransactionManager} beans present in the container.
+ * (or need to) explicitly specify the default {@code PlatformTransactionManager} bean
+ * (or {@code ReactiveTransactionManager} bean) to be used for annotation-driven
+ * transaction management, as opposed to the default approach of a by-type lookup.
+ * One reason this might be necessary is if there are two {@code PlatformTransactionManager}
+ * beans present in the container.
*
*
See @{@link EnableTransactionManagement} for general examples and context;
* see {@link #annotationDrivenTransactionManager()} for detailed instructions.
@@ -40,6 +41,8 @@ import org.springframework.transaction.PlatformTransactionManager;
* @since 3.1
* @see EnableTransactionManagement
* @see org.springframework.context.annotation.Primary
+ * @see org.springframework.transaction.PlatformTransactionManager
+ * @see org.springframework.transaction.ReactiveTransactionManager
*/
public interface TransactionManagementConfigurer {
@@ -76,7 +79,9 @@ public interface TransactionManagementConfigurer {
* container as all {@code PlatformTransactionManager} implementations take advantage
* of Spring lifecycle callbacks such as {@code InitializingBean} and
* {@code BeanFactoryAware}.
+ * @return a {@link org.springframework.transaction.PlatformTransactionManager} or
+ * {@link org.springframework.transaction.ReactiveTransactionManager} implementation
*/
- PlatformTransactionManager annotationDrivenTransactionManager();
+ TransactionManager annotationDrivenTransactionManager();
}
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 262f227817..7c3a4797cb 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
@@ -23,17 +23,25 @@ import java.util.concurrent.ConcurrentMap;
import io.vavr.control.Try;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
import org.springframework.core.NamedThreadLocal;
+import org.springframework.core.ReactiveAdapter;
+import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.lang.Nullable;
import org.springframework.transaction.NoTransactionException;
import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.ReactiveTransaction;
+import org.springframework.transaction.ReactiveTransactionManager;
+import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.TransactionSystemException;
+import org.springframework.transaction.reactive.TransactionContextManager;
import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -86,6 +94,12 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
private static final boolean vavrPresent = ClassUtils.isPresent(
"io.vavr.control.Try", TransactionAspectSupport.class.getClassLoader());
+ /**
+ * Reactive Streams API present on the classpath?
+ */
+ private static final boolean reactiveStreamsPresent =
+ ClassUtils.isPresent("org.reactivestreams.Publisher", TransactionAspectSupport.class.getClassLoader());
+
/**
* Holder to support the {@code currentTransactionStatus()} method,
* and to support communication between different cooperating advices
@@ -136,11 +150,14 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
protected final Log logger = LogFactory.getLog(getClass());
+ @Nullable
+ private final ReactiveAdapterRegistry reactiveAdapterRegistry;
+
@Nullable
private String transactionManagerBeanName;
@Nullable
- private PlatformTransactionManager transactionManager;
+ private TransactionManager transactionManager;
@Nullable
private TransactionAttributeSource transactionAttributeSource;
@@ -148,12 +165,23 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
@Nullable
private BeanFactory beanFactory;
- private final ConcurrentMap