From a599a1a03c167a07e4647a4adc335e2504c6a59a Mon Sep 17 00:00:00 2001 From: Michael Simons Date: Tue, 28 Nov 2023 15:25:09 +0100 Subject: [PATCH 1/2] build: Keep eventloop around. --- .../data/neo4j/test/Neo4jExtension.java | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) 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 d8ce5ef469..4049376ecf 100644 --- a/src/test/java/org/springframework/data/neo4j/test/Neo4jExtension.java +++ b/src/test/java/org/springframework/data/neo4j/test/Neo4jExtension.java @@ -15,6 +15,9 @@ */ package org.springframework.data.neo4j.test; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultThreadFactory; import org.apache.commons.logging.Log; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; @@ -23,14 +26,17 @@ import org.junit.platform.commons.support.ReflectionSupport; import org.neo4j.driver.AccessMode; import org.neo4j.driver.AuthToken; +import org.neo4j.driver.AuthTokenManagers; import org.neo4j.driver.AuthTokens; import org.neo4j.driver.Config; import org.neo4j.driver.Driver; -import org.neo4j.driver.GraphDatabase; import org.neo4j.driver.Logging; import org.neo4j.driver.Record; import org.neo4j.driver.Session; import org.neo4j.driver.SessionConfig; +import org.neo4j.driver.internal.DriverFactory; +import org.neo4j.driver.internal.SecuritySettings; +import org.neo4j.driver.internal.security.SecurityPlans; import org.springframework.core.log.LogMessage; import org.springframework.lang.Nullable; import org.testcontainers.containers.Neo4jContainer; @@ -38,6 +44,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.net.URI; import java.util.List; import java.util.Locale; import java.util.Map; @@ -82,12 +89,14 @@ public class Neo4jExtension implements BeforeAllCallback, BeforeEachCallback { private static final String SYS_PROPERTY_FORCE_CONTAINER_REUSE = "SDN_FORCE_REUSE_OF_CONTAINERS"; private static final Log log = org.apache.commons.logging.LogFactory.getLog(Neo4jExtension.class); - private static Set COMMUNITY_EDITION_INDICATOR = Set.of("community"); + private static final Set COMMUNITY_EDITION_INDICATOR = Set.of("community"); + private static final Set COMMERCIAL_EDITION_INDICATOR = Set.of("commercial", "enterprise"); - private static Set COMMERCIAL_EDITION_INDICATOR = Set.of("commercial", "enterprise"); + private static final EventLoopGroup EVENT_LOOP_GROUP = new NioEventLoopGroup(new DefaultThreadFactory(Neo4jExtension.class, true)); @Override public void beforeAll(ExtensionContext context) throws Exception { + List injectableFields = ReflectionSupport.findFields(context.getRequiredTestClass(), field -> Modifier.isStatic(field.getModifiers()) && field.getType() == Neo4jConnectionSupport.class, HierarchyTraversalMode.BOTTOM_UP); @@ -163,6 +172,8 @@ private void checkRequiredFeatures(Neo4jConnectionSupport neo4jConnectionSupport */ public static final class Neo4jConnectionSupport implements ExtensionContext.Store.CloseableResource { + private final DriverFactory driverFactory; + public final String url; public final AuthToken authToken; @@ -182,6 +193,7 @@ public Neo4jConnectionSupport(String url, AuthToken authToken) { this.config = Config.builder().withLogging(Logging.slf4j()) .withMaxConnectionPoolSize(Runtime.getRuntime().availableProcessors()) .build(); + this.driverFactory = new DriverFactory(); } /** @@ -198,7 +210,7 @@ public Driver getDriver() { synchronized (this) { driver = this.driverInstance; if (!isUsable(driver)) { - this.driverInstance = GraphDatabase.driver(url, authToken, config); + this.driverInstance = createDriverInstance(); driver = this.driverInstance; } } @@ -206,6 +218,13 @@ public Driver getDriver() { return driver; } + private Driver createDriverInstance() { + var uri = URI.create(url); + var settings = new SecuritySettings(config.encrypted(), config.trustStrategy()); + var securityPlan = SecurityPlans.createSecurityPlan(settings, uri.getScheme()); + return this.driverFactory.newInstance(uri, AuthTokenManagers.basic(() -> authToken), config, securityPlan, EVENT_LOOP_GROUP, null); + } + /** * A driver is usable if it's not null and can verify its connectivity. This method force closes * the bean if the connectivity cannot be verified to avoid having a netty pool dangling around. From 9408d628df3fd86d2fb546c3faf24f32a3fbfb67 Mon Sep 17 00:00:00 2001 From: Michael Simons Date: Tue, 28 Nov 2023 15:28:31 +0100 Subject: [PATCH 2/2] polish --- .../data/neo4j/test/Neo4jExtension.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 4049376ecf..44dc7d5f52 100644 --- a/src/test/java/org/springframework/data/neo4j/test/Neo4jExtension.java +++ b/src/test/java/org/springframework/data/neo4j/test/Neo4jExtension.java @@ -36,6 +36,7 @@ import org.neo4j.driver.SessionConfig; import org.neo4j.driver.internal.DriverFactory; import org.neo4j.driver.internal.SecuritySettings; +import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.security.SecurityPlans; import org.springframework.core.log.LogMessage; import org.springframework.lang.Nullable; @@ -174,12 +175,14 @@ public static final class Neo4jConnectionSupport implements ExtensionContext.Sto private final DriverFactory driverFactory; - public final String url; + public final URI uri; public final AuthToken authToken; public final Config config; + private final SecurityPlan securityPlan; + private volatile ServerVersion cachedServerVersion; /** @@ -188,11 +191,13 @@ public static final class Neo4jConnectionSupport implements ExtensionContext.Sto private volatile Driver driverInstance; public Neo4jConnectionSupport(String url, AuthToken authToken) { - this.url = url; + this.uri = URI.create(url); this.authToken = authToken; this.config = Config.builder().withLogging(Logging.slf4j()) .withMaxConnectionPoolSize(Runtime.getRuntime().availableProcessors()) .build(); + var settings = new SecuritySettings(config.encrypted(), config.trustStrategy()); + this.securityPlan = SecurityPlans.createSecurityPlan(settings, uri.getScheme()); this.driverFactory = new DriverFactory(); } @@ -219,9 +224,6 @@ public Driver getDriver() { } private Driver createDriverInstance() { - var uri = URI.create(url); - var settings = new SecuritySettings(config.encrypted(), config.trustStrategy()); - var securityPlan = SecurityPlans.createSecurityPlan(settings, uri.getScheme()); return this.driverFactory.newInstance(uri, AuthTokenManagers.basic(() -> authToken), config, securityPlan, EVENT_LOOP_GROUP, null); }