diff --git a/driver/src/main/java/org/neo4j/driver/Driver.java b/driver/src/main/java/org/neo4j/driver/Driver.java index 09ec97631f..b5f4d409dd 100644 --- a/driver/src/main/java/org/neo4j/driver/Driver.java +++ b/driver/src/main/java/org/neo4j/driver/Driver.java @@ -60,8 +60,6 @@ * * * - * - * @since 1.0 (Modified and Added {@link AsyncSession} and {@link RxSession} since 2.0) */ public interface Driver extends AutoCloseable { /** diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/Neo4jFeature.java b/driver/src/test/java/org/neo4j/driver/internal/util/Neo4jFeature.java index 216f179de6..5cac4e0253 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/util/Neo4jFeature.java +++ b/driver/src/test/java/org/neo4j/driver/internal/util/Neo4jFeature.java @@ -24,6 +24,7 @@ public enum Neo4jFeature { SPATIAL_TYPES(new Version(3, 4, 0)), TEMPORAL_TYPES(new Version(3, 4, 0)), + SERVER_SIDE_ROUTING_ENABLED_BY_DEFAULT(new Version(5, 0, 0)), BOLT_V3(new Version(3, 5, 0)), BOLT_V4(new Version(4, 0, 0)), BOLT_V51(new Version(5, 5, 0)); diff --git a/examples/src/main/java/org/neo4j/docs/driver/ConfigCustomResolverExample.java b/examples/src/main/java/org/neo4j/docs/driver/ConfigCustomResolverExample.java index d95402dbe4..6f05297383 100644 --- a/examples/src/main/java/org/neo4j/docs/driver/ConfigCustomResolverExample.java +++ b/examples/src/main/java/org/neo4j/docs/driver/ConfigCustomResolverExample.java @@ -18,66 +18,37 @@ */ package org.neo4j.docs.driver; -import org.neo4j.driver.AccessMode; import org.neo4j.driver.AuthToken; import org.neo4j.driver.AuthTokens; import org.neo4j.driver.Config; -import org.neo4j.driver.Driver; import org.neo4j.driver.GraphDatabase; import org.neo4j.driver.net.ServerAddress; -import java.util.Arrays; -import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; -import static org.neo4j.driver.SessionConfig.builder; -import static org.neo4j.driver.Values.parameters; - -public class ConfigCustomResolverExample implements AutoCloseable { - private final Driver driver; - - public ConfigCustomResolverExample(String virtualUri, AuthToken authToken, ServerAddress... addresses) { - var config = Config.builder() - .withResolver(address -> new HashSet<>(Arrays.asList(addresses))) - .build(); - - driver = GraphDatabase.driver(virtualUri, authToken, config); +public class ConfigCustomResolverExample { + @SuppressWarnings("unused") + // tag::config-custom-resolver[] + public void addExampleNode() { + var addresses = Set.of( + ServerAddress.of("a.example.com", 7676), + ServerAddress.of("b.example.com", 8787), + ServerAddress.of("c.example.com", 9898) + ); + addNode("neo4j://x.example.com", AuthTokens.basic("neo4j", "some password"), addresses, UUID.randomUUID().toString()); } - // tag::config-custom-resolver[] - @SuppressWarnings("SameParameterValue") - private Driver createDriver(String virtualUri, String user, String password, ServerAddress... addresses) { + public void addNode(String virtualUri, AuthToken authToken, Set addresses, String id) { var config = Config.builder() - .withResolver(address -> new HashSet<>(Arrays.asList(addresses))) + .withResolver(address -> addresses) .build(); - - return GraphDatabase.driver(virtualUri, AuthTokens.basic(user, password), config); - } - - private void addPerson(String name) { - var username = "neo4j"; - var password = "some password"; - - try (var driver = createDriver( - "neo4j://x.example.com", - username, - password, - ServerAddress.of("a.example.com", 7676), - ServerAddress.of("b.example.com", 8787), - ServerAddress.of("c.example.com", 9898))) { - try (var session = driver.session(builder().withDefaultAccessMode(AccessMode.WRITE).build())) { - session.run("CREATE (a:Person {name: $name})", parameters("name", name)); - } + try (var driver = GraphDatabase.driver(virtualUri, authToken, config)) { + driver.executableQuery("CREATE ({id: $id})") + .withParameters(Map.of("id", id)) + .execute(); } } // end::config-custom-resolver[] - - @Override - public void close() throws RuntimeException { - driver.close(); - } - - public boolean canConnect() { - var result = driver.session(builder().withDefaultAccessMode(AccessMode.READ).build()).run("RETURN 1"); - return result.single().get(0).asInt() == 1; - } } diff --git a/examples/src/test/java/org/neo4j/docs/driver/RoutingExamplesIT.java b/examples/src/test/java/org/neo4j/docs/driver/RoutingExamplesIT.java index 0d3a70f482..0c8022f917 100644 --- a/examples/src/test/java/org/neo4j/docs/driver/RoutingExamplesIT.java +++ b/examples/src/test/java/org/neo4j/docs/driver/RoutingExamplesIT.java @@ -21,15 +21,23 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIfSystemProperty; import org.neo4j.driver.AuthTokens; +import org.neo4j.driver.GraphDatabase; +import org.neo4j.driver.internal.util.EnabledOnNeo4jWith; +import org.neo4j.driver.internal.util.Neo4jFeature; import org.neo4j.driver.net.ServerAddress; import org.testcontainers.containers.Neo4jContainer; import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import java.net.URI; +import java.util.Map; import java.util.Optional; +import java.util.Set; +import java.util.UUID; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +@Testcontainers(disabledWithoutDocker = true) @DisabledIfSystemProperty(named = "skipDockerTests", matches = "^true$") class RoutingExamplesIT { private static final String NEO4J_VERSION = @@ -40,17 +48,31 @@ class RoutingExamplesIT { private static final Neo4jContainer NEO4J_CONTAINER = new Neo4jContainer<>( String.format("neo4j:%s-enterprise", NEO4J_VERSION)) .withEnv("NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes") + // in this testing deployment the server runs inside a container and its Bolt port is exposed to the test(s) + // on a random port that might not match the port in the routing table + // this setting leads to the server echoing back the routing context address supplied by the driver + // the test(s) may define the routing context address via the URI + .withNeo4jConfig("dbms.routing.default_router", "SERVER") .withAdminPassword(null); @Test + @EnabledOnNeo4jWith(Neo4jFeature.SERVER_SIDE_ROUTING_ENABLED_BY_DEFAULT) void testShouldRunConfigCustomResolverExample() { // Given var boltUri = URI.create(NEO4J_CONTAINER.getBoltUrl()); - var neo4jUrl = String.format("neo4j://%s:%d", boltUri.getHost(), boltUri.getPort()); - try (var example = new ConfigCustomResolverExample( - neo4jUrl, AuthTokens.none(), ServerAddress.of(boltUri.getHost(), boltUri.getPort()))) { - // Then - assertTrue(example.canConnect()); + var id = UUID.randomUUID().toString(); + var example = new ConfigCustomResolverExample(); + var neo4j = String.format("neo4j://%s:%d", boltUri.getHost(), boltUri.getPort()); + + // When + example.addNode(neo4j, AuthTokens.none(), Set.of(ServerAddress.of(boltUri.getHost(), boltUri.getPort())), id); + + // Then + try(var driver = GraphDatabase.driver(boltUri, AuthTokens.none())) { + var num = driver.executableQuery("MATCH (n{id: $id}) RETURN count(n)") + .withParameters(Map.of("id", id)) + .execute(); + assertEquals(1, num.records().get(0).get(0).asInt()); } } }