From 966c35275c20b3107ed305710ec62d149a08885f Mon Sep 17 00:00:00 2001 From: Michael Simons Date: Wed, 27 Aug 2025 14:00:04 +0200 Subject: [PATCH] refactor: Upgrade to Driver 6, and test against last Neo4j 5.26 LTS release by default. Signed-off-by: Michael Simons --- pom.xml | 2 +- .../data/neo4j/core/ResultSummaries.java | 90 +++++++++---------- .../repository/query/AbstractNeo4jQuery.java | 11 +-- .../data/neo4j/core/Neo4jClientTests.java | 22 ++--- .../neo4j/core/ReactiveNeo4jClientTests.java | 22 ++--- .../data/neo4j/core/ResultSummariesTests.java | 31 ++++--- .../core/transaction/BookmarkForTesting.java | 13 --- .../neo4j/integration/misc/IdLoggingIT.java | 11 +-- .../data/neo4j/test/LogbackCapture.java | 3 +- .../data/neo4j/test/Neo4jExtension.java | 6 +- 10 files changed, 102 insertions(+), 109 deletions(-) diff --git a/pom.xml b/pom.xml index 4d0b5ec8c..41c1ed9f2 100644 --- a/pom.xml +++ b/pom.xml @@ -97,7 +97,7 @@ 3.1.4 3.7.1 ${java.version} - 5.28.9 + 6.0.0 2.17.3 5.26.12 3.0.1 diff --git a/src/main/java/org/springframework/data/neo4j/core/ResultSummaries.java b/src/main/java/org/springframework/data/neo4j/core/ResultSummaries.java index 07c5a5698..03ba47057 100644 --- a/src/main/java/org/springframework/data/neo4j/core/ResultSummaries.java +++ b/src/main/java/org/springframework/data/neo4j/core/ResultSummaries.java @@ -15,6 +15,7 @@ */ package org.springframework.data.neo4j.core; +import java.util.List; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.regex.Pattern; @@ -23,10 +24,9 @@ import org.apache.commons.logging.LogFactory; import org.jspecify.annotations.Nullable; -import org.neo4j.driver.NotificationCategory; +import org.neo4j.driver.NotificationClassification; import org.neo4j.driver.NotificationSeverity; -import org.neo4j.driver.summary.InputPosition; -import org.neo4j.driver.summary.Notification; +import org.neo4j.driver.summary.GqlNotification; import org.neo4j.driver.summary.Plan; import org.neo4j.driver.summary.ResultSummary; @@ -66,8 +66,15 @@ final class ResultSummaries { private static final LogAccessor cypherTopologyNotificationLog = new LogAccessor( LogFactory.getLog("org.springframework.data.neo4j.cypher.topology")); - private static final Pattern DEPRECATED_ID_PATTERN = Pattern - .compile("(?im)The query used a deprecated function[.:] \\(?[`']id.+"); + private static final LogAccessor cypherSchemaNotificationLog = new LogAccessor( + LogFactory.getLog("org.springframework.data.neo4j.cypher.schema")); + + private static final List STUFF_THAT_MIGHT_INFORM_THAT_THE_ID_FUNCTION_IS_PROBLEMATIC = Stream.of( + "(?im)The query used a deprecated function[.:] \\(?[`']id.+", + "(?im).*id is deprecated and will be removed without a replacement\\.", + "(?im).*feature deprecated with replacement\\. id is deprecated\\. It is replaced by elementId or consider using an application-generated id\\.") + .map(Pattern::compile) + .toList(); private ResultSummaries() { } @@ -86,29 +93,33 @@ static ResultSummary process(ResultSummary resultSummary) { private static void logNotifications(ResultSummary resultSummary) { - if (resultSummary.notifications().isEmpty() || !Neo4jClient.cypherLog.isWarnEnabled()) { + if (resultSummary.gqlStatusObjects().isEmpty() || !Neo4jClient.cypherLog.isWarnEnabled()) { return; } boolean supressIdDeprecations = Neo4jClient.SUPPRESS_ID_DEPRECATIONS.getAcquire(); - Predicate isDeprecationWarningForId; + Predicate isDeprecationWarningForId; try { isDeprecationWarningForId = notification -> supressIdDeprecations - && notification.category() - .orElse(NotificationCategory.UNRECOGNIZED) - .equals(NotificationCategory.DEPRECATION) - && DEPRECATED_ID_PATTERN.matcher(notification.description()).matches(); + && notification.classification() + .filter(cat -> cat == NotificationClassification.UNRECOGNIZED + || cat == NotificationClassification.DEPRECATION) + .isPresent() + && STUFF_THAT_MIGHT_INFORM_THAT_THE_ID_FUNCTION_IS_PROBLEMATIC.stream() + .anyMatch(p -> p.matcher(notification.statusDescription()).matches()); } finally { Neo4jClient.SUPPRESS_ID_DEPRECATIONS.setRelease(supressIdDeprecations); } String query = resultSummary.query().text(); - resultSummary.notifications() + resultSummary.gqlStatusObjects() .stream() + .filter(GqlNotification.class::isInstance) + .map(GqlNotification.class::cast) .filter(Predicate.not(isDeprecationWarningForId)) - .forEach(notification -> notification.severityLevel().ifPresent(severityLevel -> { - var category = notification.category().orElse(null); + .forEach(notification -> notification.severity().ifPresent(severityLevel -> { + var category = notification.classification().orElse(null); var logger = getLogAccessor(category); Consumer logFunction; @@ -130,35 +141,22 @@ else if (severityLevel == NotificationSeverity.OFF) { })); } - private static LogAccessor getLogAccessor(@Nullable NotificationCategory category) { - if (category == null) { + private static LogAccessor getLogAccessor(@Nullable NotificationClassification classification) { + if (classification == null) { return Neo4jClient.cypherLog; } - if (category.equals(NotificationCategory.HINT)) { - return cypherHintNotificationLog; - } - else if (category.equals(NotificationCategory.DEPRECATION)) { - return cypherDeprecationNotificationLog; - } - else if (category.equals(NotificationCategory.PERFORMANCE)) { - return cypherPerformanceNotificationLog; - } - else if (category.equals(NotificationCategory.GENERIC)) { - return cypherGenericNotificationLog; - } - else if (category.equals(NotificationCategory.UNSUPPORTED)) { - return cypherUnsupportedNotificationLog; - } - else if (category.equals(NotificationCategory.UNRECOGNIZED)) { - return cypherUnrecognizedNotificationLog; - } - else if (category.equals(NotificationCategory.SECURITY)) { - return cypherSecurityNotificationLog; - } - else if (category.equals(NotificationCategory.TOPOLOGY)) { - return cypherTopologyNotificationLog; - } - return Neo4jClient.cypherLog; + + return switch (classification) { + case HINT -> cypherHintNotificationLog; + case UNRECOGNIZED -> cypherUnrecognizedNotificationLog; + case UNSUPPORTED -> cypherUnsupportedNotificationLog; + case PERFORMANCE -> cypherPerformanceNotificationLog; + case DEPRECATION -> cypherDeprecationNotificationLog; + case SECURITY -> cypherSecurityNotificationLog; + case TOPOLOGY -> cypherTopologyNotificationLog; + case GENERIC -> cypherGenericNotificationLog; + case SCHEMA -> cypherSchemaNotificationLog; + }; } /** @@ -167,25 +165,23 @@ else if (category.equals(NotificationCategory.TOPOLOGY)) { * @param forQuery the query that caused the notification * @return a formatted string */ - static String format(Notification notification, String forQuery) { + static String format(GqlNotification notification, String forQuery) { - InputPosition position = notification.position(); - boolean hasPosition = position != null; + var position = notification.position().orElse(null); StringBuilder queryHint = new StringBuilder(); String[] lines = forQuery.split("(\r\n|\n)"); for (int i = 0; i < lines.length; i++) { String line = lines[i]; queryHint.append("\t").append(line).append(LINE_SEPARATOR); - if (hasPosition && i + 1 == position.line()) { + if (position != null && i + 1 == position.line()) { queryHint.append("\t") .append(Stream.generate(() -> " ").limit(position.column() - 1).collect(Collectors.joining())) .append("^") .append(System.lineSeparator()); } } - return String.format("%s: %s%n%s%s", notification.code(), notification.title(), queryHint, - notification.description()); + return String.format("%s (%s):%n%s", notification.statusDescription(), notification.gqlStatus(), queryHint); } /** diff --git a/src/main/java/org/springframework/data/neo4j/repository/query/AbstractNeo4jQuery.java b/src/main/java/org/springframework/data/neo4j/repository/query/AbstractNeo4jQuery.java index 934e3e117..04d0feb92 100644 --- a/src/main/java/org/springframework/data/neo4j/repository/query/AbstractNeo4jQuery.java +++ b/src/main/java/org/springframework/data/neo4j/repository/query/AbstractNeo4jQuery.java @@ -23,7 +23,6 @@ import java.util.function.LongSupplier; import java.util.function.Supplier; import java.util.function.UnaryOperator; -import java.util.stream.Collectors; import org.jspecify.annotations.Nullable; import org.neo4j.driver.types.MapAccessor; @@ -166,7 +165,7 @@ else if (geoNearQuery) { rawResult = newGeoResults(rawResult); } else if (this.queryMethod.isSearchQuery()) { - rawResult = createSearchResult((List) rawResult, returnedType.getReturnedType()); + rawResult = createSearchResult((List) rawResult); } return resultProcessor.processResult(rawResult, preparingConverter); @@ -207,11 +206,9 @@ private Slice createSlice(boolean incrementLimit, Neo4jParameterAccessor para } } - private SearchResults createSearchResult(List rawResult, Class returnedType) { - List> searchResults = rawResult.stream() - .map(rawValue -> (SearchResult) rawValue) - .collect(Collectors.toUnmodifiableList()); - return new SearchResults<>(searchResults); + @SuppressWarnings("unchecked") + private SearchResults createSearchResult(List rawResult) { + return new SearchResults<>(rawResult.stream().map(rawValue -> (SearchResult) rawValue).toList()); } protected abstract PreparedQuery prepareQuery(Class returnedType, diff --git a/src/test/java/org/springframework/data/neo4j/core/Neo4jClientTests.java b/src/test/java/org/springframework/data/neo4j/core/Neo4jClientTests.java index af5734997..123ea553d 100644 --- a/src/test/java/org/springframework/data/neo4j/core/Neo4jClientTests.java +++ b/src/test/java/org/springframework/data/neo4j/core/Neo4jClientTests.java @@ -141,7 +141,7 @@ void databaseSelectionShouldWorkBeforeAsUser() { verify(this.session).run(eq(cypher), MockitoHamcrest.argThat(new MapAssertionMatcher(expectedParameters))); verify(this.result).stream(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.session).close(); @@ -181,7 +181,7 @@ void databaseSelectionShouldWorkAfterAsUser() { verify(this.session).run(eq(cypher), MockitoHamcrest.argThat(new MapAssertionMatcher(expectedParameters))); verify(this.result).stream(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.session).close(); @@ -220,7 +220,7 @@ void userSelectionShouldWork() { verify(this.session).run(eq(cypher), MockitoHamcrest.argThat(new MapAssertionMatcher(expectedParameters))); verify(this.result).stream(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.session).close(); @@ -268,7 +268,7 @@ void queryCreationShouldFeelGood() { verify(this.result).stream(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.record2).asMap(); @@ -305,7 +305,7 @@ void databaseSelectionShouldBePossibleOnlyOnce() { verify(this.session).run(eq(cypher), MockitoHamcrest.argThat(new MapAssertionMatcher(expectedParameters))); verify(this.result).stream(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.session).close(); @@ -350,7 +350,7 @@ void databaseSelectionBeanShouldGetRespectedIfExisting() { verify(this.session).run(eq(query), anyMap()); verify(this.result).stream(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.session).close(); @@ -379,7 +379,7 @@ void queriesWithoutResultShouldFitInAsWell() { verify(this.session).run(eq(cypher), MockitoHamcrest.argThat(new MapAssertionMatcher(expectedParameters))); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.session).close(); } @@ -577,7 +577,7 @@ void reading() { MockitoHamcrest.argThat(new MapAssertionMatcher(expectedParameters))); verify(Neo4jClientTests.this.result).stream(); verify(Neo4jClientTests.this.result).consume(); - verify(Neo4jClientTests.this.resultSummary).notifications(); + verify(Neo4jClientTests.this.resultSummary).gqlStatusObjects(); verify(Neo4jClientTests.this.resultSummary).hasPlan(); verify(Neo4jClientTests.this.record1).get("name"); verify(Neo4jClientTests.this.session).close(); @@ -614,7 +614,7 @@ void shouldApplyNullChecksDuringReading() { MockitoHamcrest.argThat(new MapAssertionMatcher(Collections.emptyMap()))); verify(Neo4jClientTests.this.result).stream(); verify(Neo4jClientTests.this.result).consume(); - verify(Neo4jClientTests.this.resultSummary).notifications(); + verify(Neo4jClientTests.this.resultSummary).gqlStatusObjects(); verify(Neo4jClientTests.this.resultSummary).hasPlan(); verify(Neo4jClientTests.this.record1).get("name"); verify(Neo4jClientTests.this.session).close(); @@ -646,7 +646,7 @@ void writing() { verify(Neo4jClientTests.this.session).run(eq(cypher), MockitoHamcrest.argThat(new MapAssertionMatcher(expectedParameters))); verify(Neo4jClientTests.this.result).consume(); - verify(Neo4jClientTests.this.resultSummary).notifications(); + verify(Neo4jClientTests.this.resultSummary).gqlStatusObjects(); verify(Neo4jClientTests.this.resultSummary).hasPlan(); verify(Neo4jClientTests.this.session).close(); } @@ -677,7 +677,7 @@ void automaticConversion() { verify(Neo4jClientTests.this.result).hasNext(); verify(Neo4jClientTests.this.result).single(); verify(Neo4jClientTests.this.result).consume(); - verify(Neo4jClientTests.this.resultSummary).notifications(); + verify(Neo4jClientTests.this.resultSummary).gqlStatusObjects(); verify(Neo4jClientTests.this.resultSummary).hasPlan(); verify(Neo4jClientTests.this.session).close(); } diff --git a/src/test/java/org/springframework/data/neo4j/core/ReactiveNeo4jClientTests.java b/src/test/java/org/springframework/data/neo4j/core/ReactiveNeo4jClientTests.java index 0964ddee5..b92c626c5 100644 --- a/src/test/java/org/springframework/data/neo4j/core/ReactiveNeo4jClientTests.java +++ b/src/test/java/org/springframework/data/neo4j/core/ReactiveNeo4jClientTests.java @@ -135,7 +135,7 @@ void databaseSelectionShouldWorkBeforeAsUser() { MockitoHamcrest.argThat(new Neo4jClientTests.MapAssertionMatcher(expectedParameters))); verify(this.result).records(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.session).close(); @@ -175,7 +175,7 @@ void databaseSelectionShouldWorkAfterAsUser() { MockitoHamcrest.argThat(new Neo4jClientTests.MapAssertionMatcher(expectedParameters))); verify(this.result).records(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.session).close(); @@ -214,7 +214,7 @@ void userSelectionShouldWork() { MockitoHamcrest.argThat(new Neo4jClientTests.MapAssertionMatcher(expectedParameters))); verify(this.result).records(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.session).close(); @@ -265,7 +265,7 @@ void queryCreationShouldFeelGood() { verify(this.result).records(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.record2).asMap(); @@ -302,7 +302,7 @@ void databaseSelectionShouldBePossibleOnlyOnce() { MockitoHamcrest.argThat(new Neo4jClientTests.MapAssertionMatcher(expectedParameters))); verify(this.result).records(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.session).close(); @@ -350,7 +350,7 @@ void databaseSelectionBeanShouldGetRespectedIfExisting() { verify(this.session).run(eq(cypher), anyMap()); verify(this.result).records(); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.record1).asMap(); verify(this.session).close(); @@ -399,7 +399,7 @@ void queriesWithoutResultShouldFitInAsWell() { verify(this.session).run(eq(cypher), MockitoHamcrest.argThat(new Neo4jClientTests.MapAssertionMatcher(expectedParameters))); verify(this.result).consume(); - verify(this.resultSummary).notifications(); + verify(this.resultSummary).gqlStatusObjects(); verify(this.resultSummary).hasPlan(); verify(this.session).close(); } @@ -508,7 +508,7 @@ void reading() { verify(ReactiveNeo4jClientTests.this.session).run(eq(cypher), MockitoHamcrest.argThat(new Neo4jClientTests.MapAssertionMatcher(expectedParameters))); verify(ReactiveNeo4jClientTests.this.result).records(); - verify(ReactiveNeo4jClientTests.this.resultSummary).notifications(); + verify(ReactiveNeo4jClientTests.this.resultSummary).gqlStatusObjects(); verify(ReactiveNeo4jClientTests.this.resultSummary).hasPlan(); verify(ReactiveNeo4jClientTests.this.record1).get("name"); verify(ReactiveNeo4jClientTests.this.session).close(); @@ -547,7 +547,7 @@ void shouldApplyNullChecksDuringReading() { verify(ReactiveNeo4jClientTests.this.session).run(eq("MATCH (n) RETURN n"), MockitoHamcrest.argThat(new Neo4jClientTests.MapAssertionMatcher(Collections.emptyMap()))); verify(ReactiveNeo4jClientTests.this.result).records(); - verify(ReactiveNeo4jClientTests.this.resultSummary).notifications(); + verify(ReactiveNeo4jClientTests.this.resultSummary).gqlStatusObjects(); verify(ReactiveNeo4jClientTests.this.resultSummary).hasPlan(); verify(ReactiveNeo4jClientTests.this.record1).get("name"); verify(ReactiveNeo4jClientTests.this.session).close(); @@ -584,7 +584,7 @@ void writing() { verify(ReactiveNeo4jClientTests.this.session).run(eq(cypher), MockitoHamcrest.argThat(new Neo4jClientTests.MapAssertionMatcher(expectedParameters))); verify(ReactiveNeo4jClientTests.this.result).consume(); - verify(ReactiveNeo4jClientTests.this.resultSummary).notifications(); + verify(ReactiveNeo4jClientTests.this.resultSummary).gqlStatusObjects(); verify(ReactiveNeo4jClientTests.this.resultSummary).hasPlan(); verify(ReactiveNeo4jClientTests.this.session).close(); } @@ -614,7 +614,7 @@ void automaticConversion() { verifyDatabaseSelection(null); verify(ReactiveNeo4jClientTests.this.result).consume(); - verify(ReactiveNeo4jClientTests.this.resultSummary).notifications(); + verify(ReactiveNeo4jClientTests.this.resultSummary).gqlStatusObjects(); verify(ReactiveNeo4jClientTests.this.resultSummary).hasPlan(); verify(ReactiveNeo4jClientTests.this.session).run(eq(cypher), anyMap()); verify(ReactiveNeo4jClientTests.this.session).close(); diff --git a/src/test/java/org/springframework/data/neo4j/core/ResultSummariesTests.java b/src/test/java/org/springframework/data/neo4j/core/ResultSummariesTests.java index b92ca4b6a..6676d90fc 100644 --- a/src/test/java/org/springframework/data/neo4j/core/ResultSummariesTests.java +++ b/src/test/java/org/springframework/data/neo4j/core/ResultSummariesTests.java @@ -15,13 +15,18 @@ */ package org.springframework.data.neo4j.core; +import java.util.Optional; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.neo4j.driver.NotificationClassification; +import org.neo4j.driver.NotificationSeverity; +import org.neo4j.driver.internal.summary.InternalGqlNotification; +import org.neo4j.driver.summary.GqlNotification; import org.neo4j.driver.summary.InputPosition; -import org.neo4j.driver.summary.Notification; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; @@ -56,7 +61,7 @@ private static Stream params() { @ParameterizedTest(name = "{index}: Notifications for \"{0}\"") @MethodSource("params") - void shouldFormatNotifications(String query, Integer line, Integer column, String expected) { + void shouldFormatNotifications(String query, @Nullable Integer line, @Nullable Integer column, String expected) { InputPosition inputPosition; if (line == null || column == null) { @@ -68,16 +73,22 @@ void shouldFormatNotifications(String query, Integer line, Integer column, Strin given(inputPosition.column()).willReturn(column); } - Notification notification = mock(Notification.class); - given(notification.severity()).willReturn("WARNING"); - given(notification.code()).willReturn("KGQ.Warning"); - given(notification.title()).willReturn("Das ist keine gute Query."); - given(notification.description()).willReturn("Das solltest Du besser nicht mehr machen."); - given(notification.position()).willReturn(inputPosition); + // Mockito cannot mock this class: interface + // org.neo4j.driver.summary.GqlNotification. + // Sealed interfaces or abstract classes can't be mocked. Interfaces cannot be + // instantiated and cannot be subclassed for mocking purposes. + // Instead of mocking a sealed interface or an abstract class, a non-abstract + // class can be mocked and used to represent the interface. + GqlNotification notification = mock(InternalGqlNotification.class); + given(notification.severity()).willReturn(Optional.of(NotificationSeverity.WARNING)); + given(notification.gqlStatus()).willReturn("KGQ.Warning"); + given(notification.classification()).willReturn(Optional.of(NotificationClassification.UNRECOGNIZED)); + given(notification.statusDescription()).willReturn("Das solltest Du besser nicht mehr machen."); + given(notification.position()).willReturn(Optional.ofNullable(inputPosition)); String formattedNotification = ResultSummaries.format(notification, query); - assertThat(formattedNotification).isEqualTo("KGQ.Warning: Das ist keine gute Query." + LINE_SEPARATOR + expected - + "Das solltest Du besser nicht mehr machen."); + assertThat(formattedNotification) + .isEqualTo("Das solltest Du besser nicht mehr machen. (KGQ.Warning):" + LINE_SEPARATOR + expected); } } diff --git a/src/test/java/org/springframework/data/neo4j/core/transaction/BookmarkForTesting.java b/src/test/java/org/springframework/data/neo4j/core/transaction/BookmarkForTesting.java index 8c9b54b8b..2869057a7 100644 --- a/src/test/java/org/springframework/data/neo4j/core/transaction/BookmarkForTesting.java +++ b/src/test/java/org/springframework/data/neo4j/core/transaction/BookmarkForTesting.java @@ -16,7 +16,6 @@ package org.springframework.data.neo4j.core.transaction; import java.util.Objects; -import java.util.Set; import org.neo4j.driver.Bookmark; @@ -28,16 +27,4 @@ record BookmarkForTesting(String value) implements Bookmark { BookmarkForTesting { value = Objects.requireNonNull(value); } - - @Override - @SuppressWarnings({ "deprecation", "RedundantSuppression" }) - public Set values() { - return Set.of(this.value); - } - - @Override - @SuppressWarnings({ "deprecation", "RedundantSuppression" }) - public boolean isEmpty() { - return this.value.isBlank(); - } } diff --git a/src/test/java/org/springframework/data/neo4j/integration/misc/IdLoggingIT.java b/src/test/java/org/springframework/data/neo4j/integration/misc/IdLoggingIT.java index 8553e4de4..3bbcb2728 100644 --- a/src/test/java/org/springframework/data/neo4j/integration/misc/IdLoggingIT.java +++ b/src/test/java/org/springframework/data/neo4j/integration/misc/IdLoggingIT.java @@ -15,6 +15,7 @@ */ package org.springframework.data.neo4j.integration.misc; +import java.util.Set; import java.util.function.Predicate; import ch.qos.logback.classic.Level; @@ -71,8 +72,9 @@ void idWarningShouldBeSuppressed(LogbackCapture logbackCapture, @Autowired Neo4j try { assertThatCode(() -> neo4jClient.query("CREATE (n:XXXIdTest) RETURN id(n)").fetch().all()) .doesNotThrowAnyException(); - Predicate stringPredicate = msg -> msg - .contains("Neo.ClientNotification.Statement.FeatureDeprecationWarning"); + // 01N42 is the old polyfill (spotted in 5.21) + var expectedCodes = Set.of("01N00", "01N01", "01N02", "01N42"); + Predicate stringPredicate = msg -> expectedCodes.stream().anyMatch(msg::contains); if (enabled == null || enabled) { assertThat(logbackCapture.getFormattedMessages()).noneMatch(stringPredicate); @@ -104,10 +106,9 @@ void otherDeprecationsWarningsShouldNotBeSuppressed(LogbackCapture logbackCaptur assertThatCode( () -> neo4jClient.query("MATCH (n) CALL {WITH n RETURN count(n) AS cnt} RETURN *").fetch().all()) .doesNotThrowAnyException(); - assertThat(logbackCapture.getFormattedMessages()) - .anyMatch(msg -> msg.contains("Neo.ClientNotification.Statement.FeatureDeprecationWarning")) + assertThat(logbackCapture.getFormattedMessages()).anyMatch(msg -> msg.contains("01N00")) .anyMatch(msg -> msg - .contains("CALL subquery without a variable scope clause is now deprecated. Use CALL (n) { ... }")); + .contains("CALL subquery without a variable scope clause is deprecated. Use CALL (n) { ... }")); } finally { logger.setLevel(originalLevel); diff --git a/src/test/java/org/springframework/data/neo4j/test/LogbackCapture.java b/src/test/java/org/springframework/data/neo4j/test/LogbackCapture.java index f54bc32ba..a37d31f25 100644 --- a/src/test/java/org/springframework/data/neo4j/test/LogbackCapture.java +++ b/src/test/java/org/springframework/data/neo4j/test/LogbackCapture.java @@ -23,14 +23,13 @@ import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.read.ListAppender; -import org.junit.jupiter.api.extension.ExtensionContext; /** * Provides access to the formatted message captured from Logback during test run. * * @author Michael J. Simons */ -public final class LogbackCapture implements ExtensionContext.Store.CloseableResource { +public final class LogbackCapture implements AutoCloseable { private final ListAppender listAppender; diff --git a/src/test/java/org/springframework/data/neo4j/test/Neo4jExtension.java b/src/test/java/org/springframework/data/neo4j/test/Neo4jExtension.java index bac1c4325..808b5af51 100644 --- a/src/test/java/org/springframework/data/neo4j/test/Neo4jExtension.java +++ b/src/test/java/org/springframework/data/neo4j/test/Neo4jExtension.java @@ -205,7 +205,7 @@ private void checkRequiredFeatures(Neo4jConnectionSupport neo4jConnectionSupport * * @since 6.0 */ - public static final class Neo4jConnectionSupport implements ExtensionContext.Store.CloseableResource { + public static final class Neo4jConnectionSupport implements AutoCloseable { public final URI uri; @@ -227,11 +227,13 @@ public static final class Neo4jConnectionSupport implements ExtensionContext.Sto public Neo4jConnectionSupport(String url, AuthToken authToken) { this.uri = URI.create(url); this.authToken = authToken; + // noinspection deprecation this.config = Config.builder() .withLogging(Logging.slf4j()) .withMaxConnectionPoolSize(Runtime.getRuntime().availableProcessors()) .build(); var settings = new SecuritySettings(this.config.encrypted(), this.config.trustStrategy()); + // noinspection deprecation this.securityPlan = SecurityPlans.createSecurityPlan(settings, this.uri.getScheme(), null, Logging.none()); this.driverFactory = new DriverFactory(); } @@ -366,7 +368,7 @@ public void close() { } - static class ContainerAdapter implements ExtensionContext.Store.CloseableResource { + static class ContainerAdapter implements AutoCloseable { private static final String repository = Optional.ofNullable(System.getenv(SYS_PROPERTY_NEO4J_REPOSITORY)) .orElse("neo4j");