From d25fc73daede7840093e11918eae63b8f4d66386 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Thu, 6 Oct 2022 19:36:22 +0200 Subject: [PATCH] Upgrade to Neo4J Java Driver 5.0.0 Closes gh-32620 --- .../neo4j/Neo4jReactiveHealthIndicator.java | 18 ++++++---- .../Neo4jReactiveHealthIndicatorTests.java | 36 ++++++++++--------- .../spring-boot-dependencies/build.gradle | 2 +- .../data/nosql/neo4j/connecting/MyBean.java | 2 +- .../data/nosql/neo4j/connecting/MyBean.kt | 16 ++++----- 5 files changed, 41 insertions(+), 33 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicator.java index 2938d7c9b02..2ca3ec48ea3 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicator.java @@ -20,8 +20,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.neo4j.driver.Driver; import org.neo4j.driver.exceptions.SessionExpiredException; -import org.neo4j.driver.reactive.RxResult; -import org.neo4j.driver.reactive.RxSession; +import org.neo4j.driver.reactive.ReactiveResult; +import org.neo4j.driver.reactive.ReactiveSession; +import reactor.adapter.JdkFlowAdapter; import reactor.core.publisher.Mono; import reactor.util.retry.Retry; @@ -64,11 +65,14 @@ public final class Neo4jReactiveHealthIndicator extends AbstractReactiveHealthIn Mono runHealthCheckQuery() { // We use WRITE here to make sure UP is returned for a server that supports // all possible workloads - return Mono.using(() -> this.driver.rxSession(Neo4jHealthIndicator.DEFAULT_SESSION_CONFIG), (session) -> { - RxResult result = session.run(Neo4jHealthIndicator.CYPHER); - return Mono.from(result.records()).zipWhen((record) -> Mono.from(result.consume())) - .map((tuple) -> new Neo4jHealthDetails(tuple.getT1(), tuple.getT2())); - }, RxSession::close); + return Mono.using(() -> this.driver.reactiveSession(Neo4jHealthIndicator.DEFAULT_SESSION_CONFIG), (session) -> { + Mono resultMono = JdkFlowAdapter + .flowPublisherToFlux(session.run(Neo4jHealthIndicator.CYPHER)).single(); + return resultMono + .flatMapMany((result) -> JdkFlowAdapter.flowPublisherToFlux(result.records()) + .zipWith(JdkFlowAdapter.flowPublisherToFlux(result.consume()))) + .map((tuple) -> new Neo4jHealthDetails(tuple.getT1(), tuple.getT2())).single(); + }, ReactiveSession::close); } } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicatorTests.java index 01104dbc8d3..cba46a97f19 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicatorTests.java @@ -25,9 +25,11 @@ import org.neo4j.driver.SessionConfig; import org.neo4j.driver.Values; import org.neo4j.driver.exceptions.ServiceUnavailableException; import org.neo4j.driver.exceptions.SessionExpiredException; -import org.neo4j.driver.reactive.RxResult; -import org.neo4j.driver.reactive.RxSession; +import org.neo4j.driver.reactive.ReactiveResult; +import org.neo4j.driver.reactive.ReactiveSession; import org.neo4j.driver.summary.ResultSummary; +import reactor.adapter.JdkFlowAdapter; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -46,6 +48,7 @@ import static org.mockito.Mockito.times; * * @author Michael J. Simons * @author Stephane Nicoll + * @author Brian Clozel */ class Neo4jReactiveHealthIndicatorTests { @@ -64,17 +67,18 @@ class Neo4jReactiveHealthIndicatorTests { @Test void neo4jIsUpWithOneSessionExpiredException() { ResultSummary resultSummary = ResultSummaryMock.createResultSummary("My Home", ""); - RxSession session = mock(RxSession.class); - RxResult statementResult = mockStatementResult(resultSummary, "4711", "some edition"); + ReactiveSession session = mock(ReactiveSession.class); + ReactiveResult statementResult = mockStatementResult(resultSummary, "4711", "some edition"); AtomicInteger count = new AtomicInteger(); given(session.run(anyString())).will((invocation) -> { if (count.compareAndSet(0, 1)) { - throw new SessionExpiredException("Session expired"); + return JdkFlowAdapter + .publisherToFlowPublisher(Flux.error(new SessionExpiredException("Session expired"))); } - return statementResult; + return JdkFlowAdapter.publisherToFlowPublisher(Flux.just(statementResult)); }); Driver driver = mock(Driver.class); - given(driver.rxSession(any(SessionConfig.class))).willReturn(session); + given(driver.reactiveSession(any(SessionConfig.class))).willReturn(session); Neo4jReactiveHealthIndicator healthIndicator = new Neo4jReactiveHealthIndicator(driver); healthIndicator.health().as(StepVerifier::create).consumeNextWith((health) -> { assertThat(health.getStatus()).isEqualTo(Status.UP); @@ -87,7 +91,7 @@ class Neo4jReactiveHealthIndicatorTests { @Test void neo4jIsDown() { Driver driver = mock(Driver.class); - given(driver.rxSession(any(SessionConfig.class))).willThrow(ServiceUnavailableException.class); + given(driver.reactiveSession(any(SessionConfig.class))).willThrow(ServiceUnavailableException.class); Neo4jReactiveHealthIndicator healthIndicator = new Neo4jReactiveHealthIndicator(driver); healthIndicator.health().as(StepVerifier::create).consumeNextWith((health) -> { assertThat(health.getStatus()).isEqualTo(Status.DOWN); @@ -95,22 +99,22 @@ class Neo4jReactiveHealthIndicatorTests { }).verifyComplete(); } - private RxResult mockStatementResult(ResultSummary resultSummary, String version, String edition) { + private ReactiveResult mockStatementResult(ResultSummary resultSummary, String version, String edition) { Record record = mock(Record.class); given(record.get("edition")).willReturn(Values.value(edition)); given(record.get("version")).willReturn(Values.value(version)); - RxResult statementResult = mock(RxResult.class); - given(statementResult.records()).willReturn(Mono.just(record)); - given(statementResult.consume()).willReturn(Mono.just(resultSummary)); + ReactiveResult statementResult = mock(ReactiveResult.class); + given(statementResult.records()).willReturn(JdkFlowAdapter.publisherToFlowPublisher(Mono.just(record))); + given(statementResult.consume()).willReturn(JdkFlowAdapter.publisherToFlowPublisher(Mono.just(resultSummary))); return statementResult; } private Driver mockDriver(ResultSummary resultSummary, String version, String edition) { - RxResult statementResult = mockStatementResult(resultSummary, version, edition); - RxSession session = mock(RxSession.class); - given(session.run(anyString())).willReturn(statementResult); + ReactiveResult statementResult = mockStatementResult(resultSummary, version, edition); + ReactiveSession session = mock(ReactiveSession.class); + given(session.run(anyString())).willReturn(JdkFlowAdapter.publisherToFlowPublisher(Mono.just(statementResult))); Driver driver = mock(Driver.class); - given(driver.rxSession(any(SessionConfig.class))).willReturn(session); + given(driver.reactiveSession(any(SessionConfig.class))).willReturn(session); return driver; } diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 84a9eb1ba6b..1642e3b866f 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1086,7 +1086,7 @@ bom { ] } } - library("Neo4j Java Driver", "4.4.9") { + library("Neo4j Java Driver", "5.0.0") { group("org.neo4j.driver") { modules = [ "neo4j-java-driver" diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/data/nosql/neo4j/connecting/MyBean.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/data/nosql/neo4j/connecting/MyBean.java index 1fa1035b27d..0db72a3fffb 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/data/nosql/neo4j/connecting/MyBean.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/data/nosql/neo4j/connecting/MyBean.java @@ -34,7 +34,7 @@ public class MyBean { // @fold:on // ... public String someMethod(String message) { try (Session session = this.driver.session()) { - return session.writeTransaction((transaction) -> transaction + return session.executeWrite((transaction) -> transaction .run("CREATE (a:Greeting) SET a.message = $message RETURN a.message + ', from node ' + id(a)", Values.parameters("message", message)) .single().get(0).asString()); diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/data/nosql/neo4j/connecting/MyBean.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/data/nosql/neo4j/connecting/MyBean.kt index 08cc2311cea..f9386ae855f 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/data/nosql/neo4j/connecting/MyBean.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/data/nosql/neo4j/connecting/MyBean.kt @@ -16,9 +16,7 @@ package org.springframework.boot.docs.data.nosql.neo4j.connecting -import org.neo4j.driver.Driver -import org.neo4j.driver.Transaction -import org.neo4j.driver.Values +import org.neo4j.driver.* import org.springframework.stereotype.Component @Component @@ -26,11 +24,13 @@ class MyBean(private val driver: Driver) { // @fold:on // ... fun someMethod(message: String?): String { driver.session().use { session -> - return@someMethod session.writeTransaction { transaction: Transaction -> - transaction.run( - "CREATE (a:Greeting) SET a.message = \$message RETURN a.message + ', from node ' + id(a)", - Values.parameters("message", message) - ).single()[0].asString() + return@someMethod session.executeWrite { transaction: TransactionContext -> + transaction + .run( + "CREATE (a:Greeting) SET a.message = \$message RETURN a.message + ', from node ' + id(a)", + Values.parameters("message", message) + ) + .single()[0].asString() } } }