From d4ba55f8d687b4e1e851d171e28ff501fbc240f1 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 13 Aug 2020 16:56:39 +0200 Subject: [PATCH] Do not configure a ReactiveNeo4jTransactionManager The current arrangement with Neo4j does not allow us to know for sure that the user intends to use `@Transactional` for reactive or imperative operations. The main reason for that is that the only trigger for the reactive auto-configuration is the presence of reactor on the classpath given that the Neo4j driver ships with both styles in the same jar. And reactor can be on the classpath for a number of reasons that are unrelated to imperative access (typically `WebClient`). This commits removes the auto-configuration of the ReactiveNeo4jAutoConfiguration and makes sure that if the user defines one, the regular `PlatformTransactionManager` backs off. This is a temporarily situation until we can provide a better signal that the user intends to primarily use imperative repositories. Closes gh-22940 --- .../data/neo4j/Neo4jDataAutoConfiguration.java | 3 ++- .../Neo4jReactiveDataAutoConfiguration.java | 11 +---------- .../neo4j/Neo4jDataAutoConfigurationTests.java | 9 +++++++++ ...Neo4jReactiveDataAutoConfigurationTests.java | 17 +++-------------- ...ctiveRepositoriesAutoConfigurationTests.java | 6 +++--- 5 files changed, 18 insertions(+), 28 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java index cd5f3a917b..64fc8e523c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java @@ -47,6 +47,7 @@ import org.springframework.data.neo4j.core.schema.Node; import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager; import org.springframework.data.neo4j.repository.config.Neo4jRepositoryConfigurationExtension; import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionManager; /** * {@link EnableAutoConfiguration Auto-configuration} for Spring Data Neo4j. @@ -106,7 +107,7 @@ public class Neo4jDataAutoConfiguration { } @Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME) - @ConditionalOnMissingBean(PlatformTransactionManager.class) + @ConditionalOnMissingBean(TransactionManager.class) public Neo4jTransactionManager transactionManager(Driver driver, DatabaseSelectionProvider databaseNameProvider, ObjectProvider optionalCustomizers) { Neo4jTransactionManager transactionManager = new Neo4jTransactionManager(driver, databaseNameProvider); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfiguration.java index 58bcb406d2..4f073ed1c1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfiguration.java @@ -33,7 +33,6 @@ import org.springframework.data.neo4j.core.ReactiveNeo4jClient; import org.springframework.data.neo4j.core.ReactiveNeo4jOperations; import org.springframework.data.neo4j.core.ReactiveNeo4jTemplate; import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext; -import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager; import org.springframework.data.neo4j.repository.config.ReactiveNeo4jRepositoryConfigurationExtension; import org.springframework.transaction.ReactiveTransactionManager; @@ -46,8 +45,7 @@ import org.springframework.transaction.ReactiveTransactionManager; * @since 2.4.0 */ @Configuration(proxyBeanMethods = false) -@ConditionalOnClass({ Driver.class, ReactiveNeo4jTransactionManager.class, ReactiveTransactionManager.class, - Flux.class }) +@ConditionalOnClass({ Driver.class, ReactiveNeo4jTemplate.class, ReactiveTransactionManager.class, Flux.class }) @ConditionalOnBean(Driver.class) @AutoConfigureAfter(Neo4jDataAutoConfiguration.class) @Import(Neo4jDefaultReactiveCallbacksRegistrar.class) @@ -74,11 +72,4 @@ public class Neo4jReactiveDataAutoConfiguration { return new ReactiveNeo4jTemplate(neo4jClient, neo4jMappingContext, databaseNameProvider); } - @Bean(ReactiveNeo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME) - @ConditionalOnMissingBean(ReactiveTransactionManager.class) - public ReactiveTransactionManager reactiveTransactionManager(Driver driver, - ReactiveDatabaseSelectionProvider databaseNameProvider) { - return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider); - } - } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java index 686ade7e25..5206a3ca5a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java @@ -31,6 +31,8 @@ import org.springframework.data.neo4j.core.Neo4jTemplate; import org.springframework.data.neo4j.core.convert.Neo4jConversions; import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager; import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.ReactiveTransactionManager; +import org.springframework.transaction.TransactionManager; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -119,6 +121,13 @@ class Neo4jDataAutoConfigurationTests { }); } + @Test + void shouldBackoffIfReactiveTransactionManagerIsSet() { + this.contextRunner.withBean(ReactiveTransactionManager.class, () -> mock(ReactiveTransactionManager.class)) + .run((context) -> assertThat(context).doesNotHaveBean(Neo4jTransactionManager.class) + .hasSingleBean(TransactionManager.class)); + } + @Test void shouldReuseExistingTransactionManager() { this.contextRunner diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfigurationTests.java index b4e7c5ac04..69096db962 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfigurationTests.java @@ -30,8 +30,8 @@ import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider; import org.springframework.data.neo4j.core.ReactiveNeo4jClient; import org.springframework.data.neo4j.core.ReactiveNeo4jOperations; import org.springframework.data.neo4j.core.ReactiveNeo4jTemplate; -import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager; import org.springframework.transaction.ReactiveTransactionManager; +import org.springframework.transaction.TransactionManager; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -113,23 +113,12 @@ class Neo4jReactiveDataAutoConfigurationTests { } @Test - void shouldProvideReactiveTransactionManager() { - this.contextRunner.withUserConfiguration(CustomReactiveDatabaseSelectionProviderConfiguration.class) - .run((context) -> { - assertThat(context).hasSingleBean(ReactiveNeo4jTransactionManager.class); - assertThat(context.getBean(ReactiveNeo4jTransactionManager.class)) - .extracting("databaseSelectionProvider") - .isSameAs(context.getBean(ReactiveDatabaseSelectionProvider.class)); - }); - } - - @Test - void shouldReuseExistingReactiveTransactionManager() { + void shouldUseExistingReactiveTransactionManager() { this.contextRunner .withBean("myCustomReactiveTransactionManager", ReactiveTransactionManager.class, () -> mock(ReactiveTransactionManager.class)) .run((context) -> assertThat(context).hasSingleBean(ReactiveTransactionManager.class) - .hasBean("myCustomReactiveTransactionManager")); + .hasSingleBean(TransactionManager.class)); } @Configuration(proxyBeanMethods = false) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveRepositoriesAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveRepositoriesAutoConfigurationTests.java index 05584cfc7d..66afb613f5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveRepositoriesAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveRepositoriesAutoConfigurationTests.java @@ -28,7 +28,7 @@ import org.springframework.boot.autoconfigure.data.neo4j.country.CountryReposito import org.springframework.boot.autoconfigure.data.neo4j.country.ReactiveCountryRepository; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Configuration; -import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager; +import org.springframework.data.neo4j.core.ReactiveNeo4jTemplate; import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository; import org.springframework.data.neo4j.repository.config.EnableReactiveNeo4jRepositories; @@ -57,7 +57,7 @@ public class Neo4jReactiveRepositoriesAutoConfigurationTests { @Test void configurationWithNoRepositories() { this.contextRunner.withUserConfiguration(EmptyConfiguration.class).run((context) -> assertThat(context) - .hasSingleBean(ReactiveNeo4jTransactionManager.class).doesNotHaveBean(ReactiveNeo4jRepository.class)); + .hasSingleBean(ReactiveNeo4jTemplate.class).doesNotHaveBean(ReactiveNeo4jRepository.class)); } @Test @@ -70,7 +70,7 @@ public class Neo4jReactiveRepositoriesAutoConfigurationTests { @Test void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() { this.contextRunner.withUserConfiguration(SortOfInvalidCustomConfiguration.class) - .run((context) -> assertThat(context).hasSingleBean(ReactiveNeo4jTransactionManager.class) + .run((context) -> assertThat(context).hasSingleBean(ReactiveNeo4jTemplate.class) .doesNotHaveBean(ReactiveNeo4jRepository.class)); }