diff --git a/driver/src/main/java/org/neo4j/driver/Config.java b/driver/src/main/java/org/neo4j/driver/Config.java
index 1f1b2b3b16..ef5094441f 100644
--- a/driver/src/main/java/org/neo4j/driver/Config.java
+++ b/driver/src/main/java/org/neo4j/driver/Config.java
@@ -24,12 +24,14 @@
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
+import org.neo4j.driver.internal.DefaultDomainNameResolver;
import org.neo4j.driver.internal.RevocationStrategy;
import org.neo4j.driver.internal.SecuritySettings;
import org.neo4j.driver.internal.async.pool.PoolSettings;
import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.handlers.pulln.FetchSizeUtil;
import org.neo4j.driver.internal.retry.RetrySettings;
+import org.neo4j.driver.net.DomainNameResolver;
import org.neo4j.driver.net.ServerAddressResolver;
import org.neo4j.driver.util.Immutable;
@@ -88,6 +90,7 @@ public class Config
private final int connectionTimeoutMillis;
private final RetrySettings retrySettings;
private final ServerAddressResolver resolver;
+ private final DomainNameResolver domainNameResolver;
private final boolean isMetricsEnabled;
private final int eventLoopThreads;
@@ -112,6 +115,7 @@ private Config( ConfigBuilder builder )
this.routingTablePurgeDelayMillis = builder.routingTablePurgeDelayMillis;
this.retrySettings = builder.retrySettings;
this.resolver = builder.resolver;
+ this.domainNameResolver = builder.domainNameResolver;
this.fetchSize = builder.fetchSize;
this.eventLoopThreads = builder.eventLoopThreads;
@@ -202,6 +206,16 @@ public ServerAddressResolver resolver()
return resolver;
}
+ /**
+ * Domain name resolver.
+ *
+ * @return the resolver to use.
+ */
+ public DomainNameResolver domainNameResolver()
+ {
+ return domainNameResolver;
+ }
+
/**
* Start building a {@link Config} object using a newly created builder.
*
@@ -283,6 +297,7 @@ public static class ConfigBuilder
private int connectionTimeoutMillis = (int) TimeUnit.SECONDS.toMillis( 30 );
private RetrySettings retrySettings = RetrySettings.DEFAULT;
private ServerAddressResolver resolver;
+ private DomainNameResolver domainNameResolver = new DefaultDomainNameResolver();
private boolean isMetricsEnabled = false;
private long fetchSize = FetchSizeUtil.DEFAULT_FETCH_SIZE;
private int eventLoopThreads = 0;
@@ -695,8 +710,23 @@ public ConfigBuilder withResolver( ServerAddressResolver resolver )
return this;
}
+ /**
+ * Specify a custom domain name resolver used by the driver to resolve domain names.
+ *
+ * Default implementation uses the {@link InetAddress#getAllByName(String)}.
+ *
+ * @param domainNameResolver the resolver to use.
+ * @return this builder.
+ */
+ public ConfigBuilder withDomainNameResolver( DomainNameResolver domainNameResolver )
+ {
+ this.domainNameResolver = Objects.requireNonNull( domainNameResolver, "domainNameResolver" );
+ return this;
+ }
+
/**
* Enable driver metrics. The metrics can be obtained afterwards via {@link Driver#metrics()}.
+ *
* @return this builder.
*/
public ConfigBuilder withDriverMetrics()
diff --git a/driver/src/main/java/org/neo4j/driver/internal/BoltServerAddress.java b/driver/src/main/java/org/neo4j/driver/internal/BoltServerAddress.java
index e851ba20eb..40d7b1759f 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/BoltServerAddress.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/BoltServerAddress.java
@@ -22,15 +22,11 @@
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URI;
-import java.net.UnknownHostException;
-import java.util.List;
import java.util.Objects;
-import java.util.stream.Stream;
import org.neo4j.driver.net.ServerAddress;
import static java.util.Objects.requireNonNull;
-import static java.util.stream.Collectors.toList;
/**
* Holds a host and port pair that denotes a Bolt server address.
@@ -44,8 +40,6 @@ public class BoltServerAddress implements ServerAddress
private final int port;
private final String stringValue;
- private InetAddress resolved;
-
public BoltServerAddress( String address )
{
this( uriFrom( address ) );
@@ -57,16 +51,10 @@ public BoltServerAddress( URI uri )
}
public BoltServerAddress( String host, int port )
- {
- this( host, null, port );
- }
-
- private BoltServerAddress( String host, InetAddress resolved, int port )
{
this.host = requireNonNull( host, "host" );
- this.resolved = resolved;
this.port = requireValidPort( port );
- this.stringValue = resolved != null ? String.format( "%s(%s):%d", host, resolved.getHostAddress(), port ) : String.format( "%s:%d", host, port );
+ this.stringValue = String.format( "%s:%d", host, port );
}
public static BoltServerAddress from( ServerAddress address )
@@ -112,33 +100,7 @@ public String toString()
*/
public SocketAddress toSocketAddress()
{
- return resolved == null ? new InetSocketAddress( host, port ) : new InetSocketAddress( resolved, port );
- }
-
- /**
- * Resolve the host name down to an IP address
- *
- * @return a new address instance
- * @throws UnknownHostException if no IP address for the host could be found
- * @see InetAddress#getByName(String)
- */
- public BoltServerAddress resolve() throws UnknownHostException
- {
- return new BoltServerAddress( host, InetAddress.getByName( host ), port );
- }
-
- /**
- * Resolve the host name down to all IP addresses that can be resolved to
- *
- * @return an array of new address instances that holds resolved addresses
- * @throws UnknownHostException if no IP address for the host could be found
- * @see InetAddress#getAllByName(String)
- */
- public List resolveAll() throws UnknownHostException
- {
- return Stream.of( InetAddress.getAllByName( host ) )
- .map( address -> new BoltServerAddress( host, address, port ) )
- .collect( toList() );
+ return new InetSocketAddress( host, port );
}
@Override
@@ -153,11 +115,6 @@ public int port()
return port;
}
- public boolean isResolved()
- {
- return resolved != null;
- }
-
private static String hostFrom( URI uri )
{
String host = uri.getHost();
diff --git a/driver/src/main/java/org/neo4j/driver/internal/DefaultDomainNameResolver.java b/driver/src/main/java/org/neo4j/driver/internal/DefaultDomainNameResolver.java
new file mode 100644
index 0000000000..665a523bcf
--- /dev/null
+++ b/driver/src/main/java/org/neo4j/driver/internal/DefaultDomainNameResolver.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) "Neo4j"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.neo4j.driver.internal;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.neo4j.driver.net.DomainNameResolver;
+
+public class DefaultDomainNameResolver implements DomainNameResolver
+{
+ @Override
+ public InetAddress[] resolve( String name ) throws UnknownHostException
+ {
+ return InetAddress.getAllByName( name );
+ }
+}
diff --git a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java
index df6f919b52..1f9f115923 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java
@@ -127,7 +127,7 @@ protected static MetricsProvider createDriverMetrics( Config config, Clock clock
protected ChannelConnector createConnector( ConnectionSettings settings, SecurityPlan securityPlan,
Config config, Clock clock, RoutingContext routingContext )
{
- return new ChannelConnectorImpl( settings, securityPlan, config.logging(), clock, routingContext );
+ return new ChannelConnectorImpl( settings, securityPlan, config.logging(), clock, routingContext, config.domainNameResolver() );
}
private InternalDriver createDriver( URI uri, SecurityPlan securityPlan, BoltServerAddress address, ConnectionPool connectionPool,
@@ -210,7 +210,7 @@ protected LoadBalancer createLoadBalancer( BoltServerAddress address, Connection
LoadBalancingStrategy loadBalancingStrategy = new LeastConnectedLoadBalancingStrategy( connectionPool, config.logging() );
ServerAddressResolver resolver = createResolver( config );
return new LoadBalancer( address, routingSettings, connectionPool, eventExecutorGroup, createClock(),
- config.logging(), loadBalancingStrategy, resolver );
+ config.logging(), loadBalancingStrategy, resolver, config.domainNameResolver() );
}
private static ServerAddressResolver createResolver( Config config )
diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/connection/ChannelConnectorImpl.java b/driver/src/main/java/org/neo4j/driver/internal/async/connection/ChannelConnectorImpl.java
index d927b8c9ec..339270fe11 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/async/connection/ChannelConnectorImpl.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/async/connection/ChannelConnectorImpl.java
@@ -24,9 +24,14 @@
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
+import io.netty.resolver.AddressResolverGroup;
-import java.util.Map;
+import java.net.InetSocketAddress;
+import org.neo4j.driver.AuthToken;
+import org.neo4j.driver.AuthTokens;
+import org.neo4j.driver.Logging;
+import org.neo4j.driver.exceptions.ClientException;
import org.neo4j.driver.internal.BoltServerAddress;
import org.neo4j.driver.internal.ConnectionSettings;
import org.neo4j.driver.internal.async.inbound.ConnectTimeoutHandler;
@@ -34,11 +39,7 @@
import org.neo4j.driver.internal.security.InternalAuthToken;
import org.neo4j.driver.internal.security.SecurityPlan;
import org.neo4j.driver.internal.util.Clock;
-import org.neo4j.driver.AuthToken;
-import org.neo4j.driver.AuthTokens;
-import org.neo4j.driver.Logging;
-import org.neo4j.driver.Value;
-import org.neo4j.driver.exceptions.ClientException;
+import org.neo4j.driver.net.DomainNameResolver;
import static java.util.Objects.requireNonNull;
@@ -52,15 +53,17 @@ public class ChannelConnectorImpl implements ChannelConnector
private final int connectTimeoutMillis;
private final Logging logging;
private final Clock clock;
+ private final AddressResolverGroup addressResolverGroup;
public ChannelConnectorImpl( ConnectionSettings connectionSettings, SecurityPlan securityPlan, Logging logging,
- Clock clock, RoutingContext routingContext )
+ Clock clock, RoutingContext routingContext, DomainNameResolver domainNameResolver )
{
- this( connectionSettings, securityPlan, new ChannelPipelineBuilderImpl(), logging, clock, routingContext );
+ this( connectionSettings, securityPlan, new ChannelPipelineBuilderImpl(), logging, clock, routingContext, domainNameResolver );
}
public ChannelConnectorImpl( ConnectionSettings connectionSettings, SecurityPlan securityPlan,
- ChannelPipelineBuilder pipelineBuilder, Logging logging, Clock clock, RoutingContext routingContext )
+ ChannelPipelineBuilder pipelineBuilder, Logging logging, Clock clock, RoutingContext routingContext,
+ DomainNameResolver domainNameResolver )
{
this.userAgent = connectionSettings.userAgent();
this.authToken = requireValidAuthToken( connectionSettings.authToken() );
@@ -70,6 +73,7 @@ public ChannelConnectorImpl( ConnectionSettings connectionSettings, SecurityPlan
this.pipelineBuilder = pipelineBuilder;
this.logging = requireNonNull( logging );
this.clock = requireNonNull( clock );
+ this.addressResolverGroup = new NettyDomainNameResolverGroup( requireNonNull( domainNameResolver ) );
}
@Override
@@ -77,6 +81,7 @@ public ChannelFuture connect( BoltServerAddress address, Bootstrap bootstrap )
{
bootstrap.option( ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeoutMillis );
bootstrap.handler( new NettyChannelInitializer( address, securityPlan, connectTimeoutMillis, clock, logging ) );
+ bootstrap.resolver( addressResolverGroup );
ChannelFuture channelConnected = bootstrap.connect( address.toSocketAddress() );
diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/connection/NettyDomainNameResolver.java b/driver/src/main/java/org/neo4j/driver/internal/async/connection/NettyDomainNameResolver.java
new file mode 100644
index 0000000000..d06bcdd0b2
--- /dev/null
+++ b/driver/src/main/java/org/neo4j/driver/internal/async/connection/NettyDomainNameResolver.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) "Neo4j"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.neo4j.driver.internal.async.connection;
+
+import io.netty.resolver.InetNameResolver;
+import io.netty.util.concurrent.EventExecutor;
+import io.netty.util.concurrent.Promise;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.neo4j.driver.net.DomainNameResolver;
+
+public class NettyDomainNameResolver extends InetNameResolver
+{
+ private final DomainNameResolver domainNameResolver;
+
+ public NettyDomainNameResolver( EventExecutor executor, DomainNameResolver domainNameResolver )
+ {
+ super( executor );
+ this.domainNameResolver = domainNameResolver;
+ }
+
+ @Override
+ protected void doResolve( String inetHost, Promise promise )
+ {
+ try
+ {
+ promise.setSuccess( domainNameResolver.resolve( inetHost )[0] );
+ }
+ catch ( UnknownHostException e )
+ {
+ promise.setFailure( e );
+ }
+ }
+
+ @Override
+ protected void doResolveAll( String inetHost, Promise> promise )
+ {
+ try
+ {
+ promise.setSuccess( Arrays.asList( domainNameResolver.resolve( inetHost ) ) );
+ }
+ catch ( UnknownHostException e )
+ {
+ promise.setFailure( e );
+ }
+ }
+}
diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/connection/NettyDomainNameResolverGroup.java b/driver/src/main/java/org/neo4j/driver/internal/async/connection/NettyDomainNameResolverGroup.java
new file mode 100644
index 0000000000..1ce5b15a50
--- /dev/null
+++ b/driver/src/main/java/org/neo4j/driver/internal/async/connection/NettyDomainNameResolverGroup.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) "Neo4j"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.neo4j.driver.internal.async.connection;
+
+import io.netty.resolver.AddressResolver;
+import io.netty.resolver.AddressResolverGroup;
+import io.netty.util.concurrent.EventExecutor;
+
+import java.net.InetSocketAddress;
+
+import org.neo4j.driver.net.DomainNameResolver;
+
+public class NettyDomainNameResolverGroup extends AddressResolverGroup
+{
+ private final DomainNameResolver domainNameResolver;
+
+ public NettyDomainNameResolverGroup( DomainNameResolver domainNameResolver )
+ {
+ this.domainNameResolver = domainNameResolver;
+ }
+
+ @Override
+ protected AddressResolver newResolver( EventExecutor executor ) throws Exception
+ {
+ return new NettyDomainNameResolver( executor, domainNameResolver ).asAddressResolver();
+ }
+}
diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java
index c9288c54cd..82a062d7c9 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java
@@ -18,6 +18,7 @@
*/
package org.neo4j.driver.internal.cluster;
+import java.net.UnknownHostException;
import java.util.List;
import java.util.concurrent.CompletionStage;
@@ -29,5 +30,5 @@ public interface Rediscovery
{
CompletionStage lookupClusterComposition( RoutingTable routingTable, ConnectionPool connectionPool, Bookmark bookmark );
- List resolve();
+ List resolve() throws UnknownHostException;
}
diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java
index 777d97c213..db8224150c 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java
@@ -20,15 +20,16 @@
import io.netty.util.concurrent.EventExecutorGroup;
+import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
-import java.util.stream.Stream;
import org.neo4j.driver.Bookmark;
import org.neo4j.driver.Logger;
@@ -40,12 +41,14 @@
import org.neo4j.driver.internal.spi.Connection;
import org.neo4j.driver.internal.spi.ConnectionPool;
import org.neo4j.driver.internal.util.Futures;
+import org.neo4j.driver.net.DomainNameResolver;
+import org.neo4j.driver.net.ServerAddress;
import org.neo4j.driver.net.ServerAddressResolver;
import static java.lang.String.format;
import static java.util.Collections.emptySet;
+import static java.util.Objects.requireNonNull;
import static java.util.concurrent.CompletableFuture.completedFuture;
-import static java.util.stream.Collectors.toList;
import static org.neo4j.driver.internal.util.Futures.completedWithNull;
import static org.neo4j.driver.internal.util.Futures.failedFuture;
@@ -64,9 +67,10 @@ public class RediscoveryImpl implements Rediscovery
private final ClusterCompositionProvider provider;
private final ServerAddressResolver resolver;
private final EventExecutorGroup eventExecutorGroup;
+ private final DomainNameResolver domainNameResolver;
public RediscoveryImpl( BoltServerAddress initialRouter, RoutingSettings settings, ClusterCompositionProvider provider,
- EventExecutorGroup eventExecutorGroup, ServerAddressResolver resolver, Logger logger )
+ EventExecutorGroup eventExecutorGroup, ServerAddressResolver resolver, Logger logger, DomainNameResolver domainNameResolver )
{
this.initialRouter = initialRouter;
this.settings = settings;
@@ -74,6 +78,7 @@ public RediscoveryImpl( BoltServerAddress initialRouter, RoutingSettings setting
this.provider = provider;
this.resolver = resolver;
this.eventExecutorGroup = eventExecutorGroup;
+ this.domainNameResolver = requireNonNull( domainNameResolver );
}
/**
@@ -265,24 +270,17 @@ private ClusterComposition handleRoutingProcedureError( Throwable error, Routing
}
@Override
- public List resolve()
+ public List resolve() throws UnknownHostException
{
- return resolver.resolve( initialRouter )
- .stream()
- .map( BoltServerAddress::from )
- .collect( toList() ); // collect to list to preserve the order
- }
-
- private Stream resolveAll( BoltServerAddress address )
- {
- try
+ List resolvedAddresses = new LinkedList<>();
+ for ( ServerAddress serverAddress : resolver.resolve( initialRouter ) )
{
- return address.resolveAll().stream();
- }
- catch ( UnknownHostException e )
- {
- logger.error( "Failed to resolve address `" + address + "` to IPs due to error: " + e.getMessage(), e );
- return Stream.of( address );
+ for ( InetAddress inetAddress : domainNameResolver.resolve( serverAddress.host() ) )
+ {
+ resolvedAddresses.add( new BoltServerAddress( inetAddress.getHostAddress(), serverAddress.port() ) );
+ }
}
+
+ return resolvedAddresses;
}
}
diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancer.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancer.java
index 34b4dce032..356ec5ce0a 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancer.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancer.java
@@ -47,9 +47,11 @@
import org.neo4j.driver.internal.spi.ConnectionProvider;
import org.neo4j.driver.internal.util.Clock;
import org.neo4j.driver.internal.util.Futures;
+import org.neo4j.driver.net.DomainNameResolver;
import org.neo4j.driver.net.ServerAddressResolver;
import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
import static org.neo4j.driver.internal.async.ImmutableConnectionContext.simple;
import static org.neo4j.driver.internal.messaging.request.MultiDatabaseUtil.supportsMultiDatabase;
import static org.neo4j.driver.internal.util.Futures.completedWithNull;
@@ -68,22 +70,24 @@ public class LoadBalancer implements ConnectionProvider
private final Rediscovery rediscovery;
public LoadBalancer( BoltServerAddress initialRouter, RoutingSettings settings, ConnectionPool connectionPool,
- EventExecutorGroup eventExecutorGroup, Clock clock, Logging logging,
- LoadBalancingStrategy loadBalancingStrategy, ServerAddressResolver resolver )
+ EventExecutorGroup eventExecutorGroup, Clock clock, Logging logging,
+ LoadBalancingStrategy loadBalancingStrategy, ServerAddressResolver resolver, DomainNameResolver domainNameResolver )
{
- this( connectionPool, createRediscovery( eventExecutorGroup, initialRouter, resolver, settings, clock, logging ), settings, loadBalancingStrategy,
- eventExecutorGroup, clock, loadBalancerLogger( logging ) );
+ this( connectionPool, createRediscovery( eventExecutorGroup, initialRouter, resolver, settings, clock, logging, requireNonNull( domainNameResolver ) ),
+ settings,
+ loadBalancingStrategy,
+ eventExecutorGroup, clock, loadBalancerLogger( logging ) );
}
private LoadBalancer( ConnectionPool connectionPool, Rediscovery rediscovery, RoutingSettings settings, LoadBalancingStrategy loadBalancingStrategy,
- EventExecutorGroup eventExecutorGroup, Clock clock, Logger log )
+ EventExecutorGroup eventExecutorGroup, Clock clock, Logger log )
{
this( connectionPool, createRoutingTables( connectionPool, rediscovery, settings, clock, log ), rediscovery, loadBalancingStrategy, eventExecutorGroup,
- log );
+ log );
}
LoadBalancer( ConnectionPool connectionPool, RoutingTableRegistry routingTables, Rediscovery rediscovery, LoadBalancingStrategy loadBalancingStrategy,
- EventExecutorGroup eventExecutorGroup, Logger log )
+ EventExecutorGroup eventExecutorGroup, Logger log )
{
this.connectionPool = connectionPool;
this.routingTables = routingTables;
@@ -252,11 +256,11 @@ private static RoutingTableRegistry createRoutingTables( ConnectionPool connecti
}
private static Rediscovery createRediscovery( EventExecutorGroup eventExecutorGroup, BoltServerAddress initialRouter, ServerAddressResolver resolver,
- RoutingSettings settings, Clock clock, Logging logging )
+ RoutingSettings settings, Clock clock, Logging logging, DomainNameResolver domainNameResolver )
{
Logger log = loadBalancerLogger( logging );
ClusterCompositionProvider clusterCompositionProvider = new RoutingProcedureClusterCompositionProvider( clock, settings.routingContext() );
- return new RediscoveryImpl( initialRouter, settings, clusterCompositionProvider, eventExecutorGroup, resolver, log );
+ return new RediscoveryImpl( initialRouter, settings, clusterCompositionProvider, eventExecutorGroup, resolver, log, domainNameResolver );
}
private static Logger loadBalancerLogger( Logging logging )
diff --git a/driver/src/main/java/org/neo4j/driver/net/DomainNameResolver.java b/driver/src/main/java/org/neo4j/driver/net/DomainNameResolver.java
new file mode 100644
index 0000000000..55e15992e5
--- /dev/null
+++ b/driver/src/main/java/org/neo4j/driver/net/DomainNameResolver.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) "Neo4j"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.neo4j.driver.net;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * A resolver function used by the driver to resolve domain names.
+ */
+@FunctionalInterface
+public interface DomainNameResolver
+{
+ /**
+ * Resolve the given domain name to a set of addresses.
+ *
+ * @param name the name to resolve.
+ * @return the resolved addresses.
+ * @throws UnknownHostException must be thrown if the given name can not be resolved to at least one address.
+ */
+ InetAddress[] resolve( String name ) throws UnknownHostException;
+}
diff --git a/driver/src/test/java/org/neo4j/driver/integration/ChannelConnectorImplIT.java b/driver/src/test/java/org/neo4j/driver/integration/ChannelConnectorImplIT.java
index a8b6c8051b..8aff7f99c7 100644
--- a/driver/src/test/java/org/neo4j/driver/integration/ChannelConnectorImplIT.java
+++ b/driver/src/test/java/org/neo4j/driver/integration/ChannelConnectorImplIT.java
@@ -42,14 +42,15 @@
import org.neo4j.driver.exceptions.ServiceUnavailableException;
import org.neo4j.driver.internal.BoltServerAddress;
import org.neo4j.driver.internal.ConnectionSettings;
+import org.neo4j.driver.internal.DefaultDomainNameResolver;
import org.neo4j.driver.internal.RevocationStrategy;
import org.neo4j.driver.internal.async.connection.BootstrapFactory;
import org.neo4j.driver.internal.async.connection.ChannelConnector;
import org.neo4j.driver.internal.async.connection.ChannelConnectorImpl;
import org.neo4j.driver.internal.async.inbound.ConnectTimeoutHandler;
import org.neo4j.driver.internal.cluster.RoutingContext;
-import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.security.SecurityPlan;
+import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.util.FakeClock;
import org.neo4j.driver.util.DatabaseExtension;
import org.neo4j.driver.util.ParallelizableIT;
@@ -233,7 +234,7 @@ private ChannelConnectorImpl newConnector( AuthToken authToken, SecurityPlan sec
int connectTimeoutMillis )
{
ConnectionSettings settings = new ConnectionSettings( authToken, "test", connectTimeoutMillis );
- return new ChannelConnectorImpl( settings, securityPlan, DEV_NULL_LOGGING, new FakeClock(), RoutingContext.EMPTY );
+ return new ChannelConnectorImpl( settings, securityPlan, DEV_NULL_LOGGING, new FakeClock(), RoutingContext.EMPTY, new DefaultDomainNameResolver() );
}
private static SecurityPlan trustAllCertificates() throws GeneralSecurityException
diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplIT.java b/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplIT.java
index 12b1e493f8..4a51124a3c 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplIT.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/async/pool/ConnectionPoolImplIT.java
@@ -30,6 +30,7 @@
import org.neo4j.driver.exceptions.ServiceUnavailableException;
import org.neo4j.driver.internal.BoltServerAddress;
import org.neo4j.driver.internal.ConnectionSettings;
+import org.neo4j.driver.internal.DefaultDomainNameResolver;
import org.neo4j.driver.internal.async.connection.BootstrapFactory;
import org.neo4j.driver.internal.async.connection.ChannelConnector;
import org.neo4j.driver.internal.async.connection.ChannelConnectorImpl;
@@ -147,7 +148,7 @@ private ConnectionPoolImpl newPool() throws Exception
FakeClock clock = new FakeClock();
ConnectionSettings connectionSettings = new ConnectionSettings( neo4j.authToken(), "test", 5000 );
ChannelConnector connector = new ChannelConnectorImpl( connectionSettings, SecurityPlanImpl.insecure(),
- DEV_NULL_LOGGING, clock, RoutingContext.EMPTY );
+ DEV_NULL_LOGGING, clock, RoutingContext.EMPTY, new DefaultDomainNameResolver() );
PoolSettings poolSettings = newSettings();
Bootstrap bootstrap = BootstrapFactory.newBootstrap( 1 );
return new ConnectionPoolImpl( connector, bootstrap, poolSettings, DEV_NULL_METRICS, DEV_NULL_LOGGING, clock, true );
diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolIT.java b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolIT.java
index 693738af70..990d793b11 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolIT.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolIT.java
@@ -35,11 +35,12 @@
import org.neo4j.driver.Value;
import org.neo4j.driver.exceptions.AuthenticationException;
import org.neo4j.driver.internal.ConnectionSettings;
+import org.neo4j.driver.internal.DefaultDomainNameResolver;
import org.neo4j.driver.internal.async.connection.BootstrapFactory;
import org.neo4j.driver.internal.async.connection.ChannelConnectorImpl;
import org.neo4j.driver.internal.cluster.RoutingContext;
-import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.security.InternalAuthToken;
+import org.neo4j.driver.internal.security.SecurityPlanImpl;
import org.neo4j.driver.internal.util.FakeClock;
import org.neo4j.driver.internal.util.ImmediateSchedulingEventExecutor;
import org.neo4j.driver.util.DatabaseExtension;
@@ -184,7 +185,7 @@ private NettyChannelPool newPool( AuthToken authToken, int maxConnections )
{
ConnectionSettings settings = new ConnectionSettings( authToken, "test", 5_000 );
ChannelConnectorImpl connector = new ChannelConnectorImpl( settings, SecurityPlanImpl.insecure(), DEV_NULL_LOGGING,
- new FakeClock(), RoutingContext.EMPTY );
+ new FakeClock(), RoutingContext.EMPTY, new DefaultDomainNameResolver() );
return new NettyChannelPool( neo4j.address(), connector, bootstrap, poolHandler, ChannelHealthChecker.ACTIVE,
1_000, maxConnections );
}
diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java
index 19b1174909..0a70ca19ac 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java
@@ -23,6 +23,8 @@
import org.mockito.ArgumentCaptor;
import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -35,11 +37,13 @@
import org.neo4j.driver.exceptions.SessionExpiredException;
import org.neo4j.driver.internal.BoltServerAddress;
import org.neo4j.driver.internal.DatabaseName;
+import org.neo4j.driver.internal.DefaultDomainNameResolver;
import org.neo4j.driver.internal.InternalBookmark;
import org.neo4j.driver.internal.spi.Connection;
import org.neo4j.driver.internal.spi.ConnectionPool;
import org.neo4j.driver.internal.util.FakeClock;
import org.neo4j.driver.internal.util.ImmediateSchedulingEventExecutor;
+import org.neo4j.driver.net.DomainNameResolver;
import org.neo4j.driver.net.ServerAddressResolver;
import static java.util.Arrays.asList;
@@ -50,7 +54,6 @@
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
@@ -375,8 +378,9 @@ void shouldRetryConfiguredNumberOfTimesWithDelay()
ImmediateSchedulingEventExecutor eventExecutor = new ImmediateSchedulingEventExecutor();
RoutingSettings settings = new RoutingSettings( maxRoutingFailures, retryTimeoutDelay, 0 );
- Rediscovery rediscovery = new RediscoveryImpl( A, settings, compositionProvider, eventExecutor, resolver, DEV_NULL_LOGGER );
- RoutingTable table = routingTableMock(A, B );
+ Rediscovery rediscovery =
+ new RediscoveryImpl( A, settings, compositionProvider, eventExecutor, resolver, DEV_NULL_LOGGER, new DefaultDomainNameResolver() );
+ RoutingTable table = routingTableMock( A, B );
ClusterComposition actualComposition = await( rediscovery.lookupClusterComposition( table, pool, empty() ) );
@@ -399,7 +403,7 @@ void shouldNotLogWhenSingleRetryAttemptFails()
ImmediateSchedulingEventExecutor eventExecutor = new ImmediateSchedulingEventExecutor();
RoutingSettings settings = new RoutingSettings( maxRoutingFailures, retryTimeoutDelay, 0 );
Logger logger = mock( Logger.class );
- Rediscovery rediscovery = new RediscoveryImpl( A, settings, compositionProvider, eventExecutor, resolver, logger );
+ Rediscovery rediscovery = new RediscoveryImpl( A, settings, compositionProvider, eventExecutor, resolver, logger, new DefaultDomainNameResolver() );
RoutingTable table = routingTableMock( A );
ServiceUnavailableException e =
@@ -412,16 +416,20 @@ void shouldNotLogWhenSingleRetryAttemptFails()
}
@Test
- void shouldNotResolveToIPs()
+ void shouldNotResolveToIPs() throws UnknownHostException
{
ServerAddressResolver resolver = resolverMock( A, A );
- Rediscovery rediscovery = new RediscoveryImpl( A, null, null, null, resolver, null );
+ DomainNameResolver domainNameResolver = mock( DomainNameResolver.class );
+ InetAddress localhost = InetAddress.getLocalHost();
+ when( domainNameResolver.resolve( A.host() ) ).thenReturn( new InetAddress[]{localhost} );
+ Rediscovery rediscovery = new RediscoveryImpl( A, null, null, null, resolver, null, domainNameResolver );
List addresses = rediscovery.resolve();
verify( resolver, times( 1 ) ).resolve( A );
+ verify( domainNameResolver, times( 1 ) ).resolve( A.host() );
assertEquals( 1, addresses.size() );
- assertFalse( addresses.get( 0 ).isResolved() );
+ assertEquals( addresses.get( 0 ), new BoltServerAddress( localhost.getHostAddress(), A.port() ) );
}
private Rediscovery newRediscovery( BoltServerAddress initialRouter, ClusterCompositionProvider compositionProvider,
@@ -434,7 +442,8 @@ private Rediscovery newRediscovery( BoltServerAddress initialRouter, ClusterComp
ServerAddressResolver resolver, Logger logger )
{
RoutingSettings settings = new RoutingSettings( 1, 0, 0 );
- return new RediscoveryImpl( initialRouter, settings, compositionProvider, GlobalEventExecutor.INSTANCE, resolver, logger );
+ return new RediscoveryImpl( initialRouter, settings, compositionProvider, GlobalEventExecutor.INSTANCE, resolver, logger,
+ new DefaultDomainNameResolver() );
}
@SuppressWarnings( "unchecked" )
diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancerTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancerTest.java
index be9e1449e5..520c81946c 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancerTest.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/LoadBalancerTest.java
@@ -414,7 +414,7 @@ private static LoadBalancer newLoadBalancer( ConnectionPool connectionPool, Rout
when( routingTables.ensureRoutingTable( any( ConnectionContext.class ) ) ).thenReturn( CompletableFuture.completedFuture( handler ) );
Rediscovery rediscovery = mock( Rediscovery.class );
return new LoadBalancer( connectionPool, routingTables, rediscovery, new LeastConnectedLoadBalancingStrategy( connectionPool, DEV_NULL_LOGGING ),
- GlobalEventExecutor.INSTANCE, DEV_NULL_LOGGER );
+ GlobalEventExecutor.INSTANCE, DEV_NULL_LOGGER );
}
private static LoadBalancer newLoadBalancer( ConnectionPool connectionPool, Rediscovery rediscovery )
@@ -428,6 +428,6 @@ private static LoadBalancer newLoadBalancer( ConnectionPool connectionPool, Rout
{
// Used only in testing
return new LoadBalancer( connectionPool, routingTables, rediscovery, new LeastConnectedLoadBalancingStrategy( connectionPool, DEV_NULL_LOGGING ),
- GlobalEventExecutor.INSTANCE, DEV_NULL_LOGGER );
+ GlobalEventExecutor.INSTANCE, DEV_NULL_LOGGER );
}
}
diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/RoutingTableAndConnectionPoolTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/RoutingTableAndConnectionPoolTest.java
index 61172275c0..5cf047d49c 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/RoutingTableAndConnectionPoolTest.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/loadbalancing/RoutingTableAndConnectionPoolTest.java
@@ -326,7 +326,7 @@ private LoadBalancer newLoadBalancer( ConnectionPool connectionPool, RoutingTabl
{
Rediscovery rediscovery = mock( Rediscovery.class );
return new LoadBalancer( connectionPool, routingTables, rediscovery, new LeastConnectedLoadBalancingStrategy( connectionPool, logging ),
- GlobalEventExecutor.INSTANCE, logging.getLog( "LB" ) );
+ GlobalEventExecutor.INSTANCE, logging.getLog( "LB" ) );
}
private CompletableFuture clusterComposition( BoltServerAddress... addresses )
diff --git a/driver/src/test/java/org/neo4j/driver/internal/net/BoltServerAddressTest.java b/driver/src/test/java/org/neo4j/driver/internal/net/BoltServerAddressTest.java
index 8b92004c29..5f3af8eede 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/net/BoltServerAddressTest.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/net/BoltServerAddressTest.java
@@ -22,20 +22,11 @@
import java.net.SocketAddress;
import java.net.URI;
-import java.util.List;
import org.neo4j.driver.internal.BoltServerAddress;
import org.neo4j.driver.net.ServerAddress;
import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.Matchers.anyOf;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.endsWith;
-import static org.hamcrest.Matchers.everyItem;
-import static org.hamcrest.Matchers.greaterThanOrEqualTo;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.not;
-import static org.hamcrest.Matchers.startsWith;
import static org.hamcrest.junit.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotSame;
@@ -146,58 +137,10 @@ void shouldUseUriWithHostAndPort()
assertEquals( 12345, address.port() );
}
- @Test
- void shouldResolveDNSToIPs() throws Exception
- {
- BoltServerAddress address = new BoltServerAddress( "google.com", 80 );
- List resolved = address.resolveAll();
- assertThat( resolved, hasSize( greaterThanOrEqualTo( 1 ) ) );
- assertThat( resolved, everyItem( equalTo( address ) ) );
- }
-
- @Test
- void shouldResolveLocalhostIPDNSToIPs() throws Exception
- {
- BoltServerAddress address = new BoltServerAddress( "127.0.0.1", 80 );
- List resolved = address.resolveAll();
- assertThat( resolved, hasSize( 1 ) );
- assertThat( resolved, everyItem( equalTo( address ) ) );
- }
-
- @Test
- void shouldResolveLocalhostDNSToIPs() throws Exception
- {
- BoltServerAddress address = new BoltServerAddress( "localhost", 80 );
- List resolved = address.resolveAll();
- assertThat( resolved, hasSize( greaterThanOrEqualTo( 1 ) ) );
- assertThat( resolved, everyItem( equalTo( address ) ) );
- }
-
- @Test
- void shouldResolveIPv6LocalhostDNSToIPs() throws Exception
- {
- BoltServerAddress address = new BoltServerAddress( "[::1]", 80 );
- List resolved = address.resolveAll();
- assertThat( resolved, hasSize( greaterThanOrEqualTo( 1 ) ) );
- assertThat( resolved, everyItem( equalTo( address ) ) );
- }
-
@Test
void shouldIncludeHostAndPortInToString()
{
BoltServerAddress address = new BoltServerAddress( "localhost", 8081 );
assertThat( address.toString(), equalTo( "localhost:8081" ) );
}
-
- @Test
- void shouldIncludeHostResolvedIPAndPortInToStringWhenResolved() throws Exception
- {
- BoltServerAddress address = new BoltServerAddress( "localhost", 8081 );
- BoltServerAddress resolved = address.resolve();
-
- assertThat( resolved.toString(), not( equalTo( "localhost:8081" ) ) );
- assertThat( resolved.toString(), anyOf( containsString( "(127.0.0.1)" ), containsString( "(::1)" ) ) );
- assertThat( resolved.toString(), startsWith( "localhost" ) );
- assertThat( resolved.toString(), endsWith( "8081" ) );
- }
}
diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/ClusterCompositionUtil.java b/driver/src/test/java/org/neo4j/driver/internal/util/ClusterCompositionUtil.java
index 53804f82b1..86698f0bc6 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/util/ClusterCompositionUtil.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/util/ClusterCompositionUtil.java
@@ -29,16 +29,18 @@
public final class ClusterCompositionUtil
{
- private ClusterCompositionUtil() {}
+ private ClusterCompositionUtil()
+ {
+ }
public static final long NEVER_EXPIRE = System.currentTimeMillis() + TimeUnit.HOURS.toMillis( 1 );
- public static final BoltServerAddress A = new BoltServerAddress( "1111:11" );
- public static final BoltServerAddress B = new BoltServerAddress( "2222:22" );
- public static final BoltServerAddress C = new BoltServerAddress( "3333:33" );
- public static final BoltServerAddress D = new BoltServerAddress( "4444:44" );
- public static final BoltServerAddress E = new BoltServerAddress( "5555:55" );
- public static final BoltServerAddress F = new BoltServerAddress( "6666:66" );
+ public static final BoltServerAddress A = new BoltServerAddress( "192.168.100.100:11" );
+ public static final BoltServerAddress B = new BoltServerAddress( "192.168.100.101:22" );
+ public static final BoltServerAddress C = new BoltServerAddress( "192.168.100.102:33" );
+ public static final BoltServerAddress D = new BoltServerAddress( "192.168.100.103:44" );
+ public static final BoltServerAddress E = new BoltServerAddress( "192.168.100.104:55" );
+ public static final BoltServerAddress F = new BoltServerAddress( "192.168.100.105:66" );
public static final List EMPTY = new ArrayList<>();
diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/MessageRecordingDriverFactory.java b/driver/src/test/java/org/neo4j/driver/internal/util/MessageRecordingDriverFactory.java
index fc650673ca..5bdd1a73d1 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/util/MessageRecordingDriverFactory.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/util/MessageRecordingDriverFactory.java
@@ -28,7 +28,10 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
+import org.neo4j.driver.Config;
+import org.neo4j.driver.Logging;
import org.neo4j.driver.internal.ConnectionSettings;
+import org.neo4j.driver.internal.DefaultDomainNameResolver;
import org.neo4j.driver.internal.DriverFactory;
import org.neo4j.driver.internal.async.connection.ChannelConnector;
import org.neo4j.driver.internal.async.connection.ChannelConnectorImpl;
@@ -39,8 +42,6 @@
import org.neo4j.driver.internal.messaging.Message;
import org.neo4j.driver.internal.messaging.MessageFormat;
import org.neo4j.driver.internal.security.SecurityPlan;
-import org.neo4j.driver.Config;
-import org.neo4j.driver.Logging;
public class MessageRecordingDriverFactory extends DriverFactory
{
@@ -56,7 +57,7 @@ protected ChannelConnector createConnector( ConnectionSettings settings, Securit
RoutingContext routingContext )
{
ChannelPipelineBuilder pipelineBuilder = new MessageRecordingChannelPipelineBuilder();
- return new ChannelConnectorImpl( settings, securityPlan, pipelineBuilder, config.logging(), clock, routingContext );
+ return new ChannelConnectorImpl( settings, securityPlan, pipelineBuilder, config.logging(), clock, routingContext, new DefaultDomainNameResolver() );
}
private class MessageRecordingChannelPipelineBuilder extends ChannelPipelineBuilderImpl
diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/io/ChannelTrackingDriverFactoryWithFailingMessageFormat.java b/driver/src/test/java/org/neo4j/driver/internal/util/io/ChannelTrackingDriverFactoryWithFailingMessageFormat.java
index e36720ffbd..97da437117 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/util/io/ChannelTrackingDriverFactoryWithFailingMessageFormat.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/util/io/ChannelTrackingDriverFactoryWithFailingMessageFormat.java
@@ -18,14 +18,15 @@
*/
package org.neo4j.driver.internal.util.io;
+import org.neo4j.driver.Config;
import org.neo4j.driver.internal.ConnectionSettings;
+import org.neo4j.driver.internal.DefaultDomainNameResolver;
import org.neo4j.driver.internal.async.connection.ChannelConnector;
import org.neo4j.driver.internal.async.connection.ChannelConnectorImpl;
import org.neo4j.driver.internal.cluster.RoutingContext;
import org.neo4j.driver.internal.security.SecurityPlan;
import org.neo4j.driver.internal.util.Clock;
import org.neo4j.driver.internal.util.FailingMessageFormat;
-import org.neo4j.driver.Config;
public class ChannelTrackingDriverFactoryWithFailingMessageFormat extends ChannelTrackingDriverFactory
{
@@ -40,7 +41,7 @@ public ChannelTrackingDriverFactoryWithFailingMessageFormat( Clock clock )
protected ChannelConnector createRealConnector( ConnectionSettings settings, SecurityPlan securityPlan,
Config config, Clock clock, RoutingContext routingContext )
{
- return new ChannelConnectorImpl( settings, securityPlan, pipelineBuilder, config.logging(), clock, routingContext );
+ return new ChannelConnectorImpl( settings, securityPlan, pipelineBuilder, config.logging(), clock, routingContext, new DefaultDomainNameResolver() );
}
public FailingMessageFormat getFailingMessageFormat()
diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/Cluster.java b/driver/src/test/java/org/neo4j/driver/util/cc/Cluster.java
index 8f02f3207d..9fdd6cdbb6 100644
--- a/driver/src/test/java/org/neo4j/driver/util/cc/Cluster.java
+++ b/driver/src/test/java/org/neo4j/driver/util/cc/Cluster.java
@@ -19,6 +19,7 @@
package org.neo4j.driver.util.cc;
import java.io.FileNotFoundException;
+import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.nio.file.Path;
@@ -29,10 +30,10 @@
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
+import org.neo4j.driver.Bookmark;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Record;
import org.neo4j.driver.internal.BoltServerAddress;
-import org.neo4j.driver.Bookmark;
import org.neo4j.driver.util.TestUtil;
import org.neo4j.driver.util.cc.ClusterMemberRoleDiscoveryFactory.ClusterMemberRoleDiscovery;
@@ -400,7 +401,7 @@ private static BoltServerAddress newBoltServerAddress( URI uri )
{
try
{
- return new BoltServerAddress( uri ).resolve();
+ return new BoltServerAddress( InetAddress.getByName( uri.getHost() ).getHostAddress(), uri.getPort() );
}
catch ( UnknownHostException e )
{
diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMember.java b/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMember.java
index e64b2d551f..68ec80aa1f 100644
--- a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMember.java
+++ b/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMember.java
@@ -20,6 +20,7 @@
import java.io.File;
import java.io.FileNotFoundException;
+import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.nio.file.Path;
@@ -111,7 +112,7 @@ private static BoltServerAddress newBoltServerAddress( URI uri )
{
try
{
- return new BoltServerAddress( uri ).resolve();
+ return new BoltServerAddress( InetAddress.getByName( uri.getHost() ).getHostAddress(), uri.getPort() );
}
catch ( UnknownHostException e )
{
diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMemberRoleDiscoveryFactory.java b/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMemberRoleDiscoveryFactory.java
index 6803df576a..0b48f2a299 100644
--- a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMemberRoleDiscoveryFactory.java
+++ b/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMemberRoleDiscoveryFactory.java
@@ -18,6 +18,7 @@
*/
package org.neo4j.driver.util.cc;
+import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.HashMap;
@@ -27,14 +28,14 @@
import org.neo4j.driver.AccessMode;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Record;
-import org.neo4j.driver.Session;
import org.neo4j.driver.Result;
+import org.neo4j.driver.Session;
import org.neo4j.driver.Values;
import org.neo4j.driver.internal.BoltServerAddress;
import org.neo4j.driver.internal.util.ServerVersion;
-import static org.neo4j.driver.Values.parameters;
import static org.neo4j.driver.SessionConfig.builder;
+import static org.neo4j.driver.Values.parameters;
import static org.neo4j.driver.internal.util.Iterables.single;
public class ClusterMemberRoleDiscoveryFactory
@@ -145,7 +146,7 @@ private static BoltServerAddress newBoltServerAddress( URI uri )
{
try
{
- return new BoltServerAddress( uri ).resolve();
+ return new BoltServerAddress( InetAddress.getByName( uri.getHost() ).getHostAddress(), uri.getPort() );
}
catch ( UnknownHostException e )
{
diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java
index 1d966da508..1fa3cbee34 100644
--- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java
+++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java
@@ -21,7 +21,9 @@
import lombok.Getter;
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;
+import java.net.InetAddress;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
@@ -45,6 +47,7 @@ public class TestkitState
private final Consumer responseWriter;
private final Supplier processor;
private final Map> idToServerAddresses = new HashMap<>();
+ private final Map> idToResolvedAddresses = new HashMap<>();
public TestkitState( Consumer responseWriter, Supplier processor )
{
diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/DomainNameResolutionCompleted.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/DomainNameResolutionCompleted.java
new file mode 100644
index 0000000000..92fe4397cb
--- /dev/null
+++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/DomainNameResolutionCompleted.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) "Neo4j"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package neo4j.org.testkit.backend.messages.requests;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import neo4j.org.testkit.backend.TestkitState;
+import neo4j.org.testkit.backend.messages.responses.TestkitResponse;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Setter
+@Getter
+@NoArgsConstructor
+public class DomainNameResolutionCompleted implements TestkitRequest
+{
+ private DomainNameResolutionCompletedBody data;
+
+ @Override
+ public TestkitResponse process( TestkitState testkitState )
+ {
+ testkitState.getIdToResolvedAddresses().put(
+ data.getRequestId(),
+ data.getAddresses()
+ .stream()
+ .map(
+ addr ->
+ {
+ try
+ {
+ return InetAddress.getByName( addr );
+ }
+ catch ( UnknownHostException e )
+ {
+ throw new RuntimeException( e );
+ }
+ } )
+ .collect( Collectors.toCollection( LinkedList::new ) ) );
+ return null;
+ }
+
+ @Setter
+ @Getter
+ @NoArgsConstructor
+ private static class DomainNameResolutionCompletedBody
+ {
+ private String requestId;
+ private List addresses;
+ }
+}
diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java
index c34bafc40d..e5bc28e29d 100644
--- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java
+++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java
@@ -22,17 +22,20 @@
import lombok.NoArgsConstructor;
import lombok.Setter;
import neo4j.org.testkit.backend.TestkitState;
+import neo4j.org.testkit.backend.messages.responses.DomainNameResolutionRequired;
import neo4j.org.testkit.backend.messages.responses.Driver;
import neo4j.org.testkit.backend.messages.responses.ResolverResolutionRequired;
import neo4j.org.testkit.backend.messages.responses.TestkitErrorResponse;
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;
import java.util.Optional;
+import java.util.concurrent.TimeUnit;
import org.neo4j.driver.AuthToken;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Config;
import org.neo4j.driver.GraphDatabase;
+import org.neo4j.driver.net.DomainNameResolver;
import org.neo4j.driver.net.ServerAddressResolver;
@Setter
@@ -65,7 +68,12 @@ public TestkitResponse process( TestkitState testkitState )
{
configBuilder.withResolver( callbackResolver( testkitState ) );
}
+ if ( data.isDomainNameResolverRegistered() )
+ {
+ configBuilder.withDomainNameResolver( callbackDomainNameResolver( testkitState ) );
+ }
Optional.ofNullable( data.userAgent ).ifPresent( configBuilder::withUserAgent );
+ Optional.ofNullable( data.connectionTimeoutMs ).ifPresent( timeout -> configBuilder.withConnectionTimeout( timeout, TimeUnit.MILLISECONDS ) );
testkitState.getDrivers().putIfAbsent( id, GraphDatabase.driver( data.uri, authToken, configBuilder.build() ) );
return Driver.builder().data( Driver.DriverBody.builder().id( id ).build() ).build();
}
@@ -90,6 +98,26 @@ private ServerAddressResolver callbackResolver( TestkitState testkitState )
};
}
+ private DomainNameResolver callbackDomainNameResolver( TestkitState testkitState )
+ {
+ return address ->
+ {
+ String callbackId = testkitState.newId();
+ DomainNameResolutionRequired.DomainNameResolutionRequiredBody body =
+ DomainNameResolutionRequired.DomainNameResolutionRequiredBody.builder()
+ .id( callbackId )
+ .name( address )
+ .build();
+ DomainNameResolutionRequired response =
+ DomainNameResolutionRequired.builder()
+ .data( body )
+ .build();
+ testkitState.getResponseWriter().accept( response );
+ testkitState.getProcessor().get();
+ return testkitState.getIdToResolvedAddresses().remove( callbackId );
+ };
+ }
+
@Setter
@Getter
@NoArgsConstructor
@@ -99,5 +127,7 @@ public static class NewDriverBody
private AuthorizationToken authorizationToken;
private String userAgent;
private boolean resolverRegistered;
+ private boolean domainNameResolverRegistered;
+ private Long connectionTimeoutMs;
}
}
diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitRequest.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitRequest.java
index 7d74966fa5..4f7d053948 100644
--- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitRequest.java
+++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitRequest.java
@@ -33,7 +33,8 @@
@JsonSubTypes.Type( TransactionRun.class ), @JsonSubTypes.Type( RetryablePositive.class ),
@JsonSubTypes.Type( SessionBeginTransaction.class ), @JsonSubTypes.Type( TransactionCommit.class ),
@JsonSubTypes.Type( SessionLastBookmarks.class ), @JsonSubTypes.Type( SessionWriteTransaction.class ),
- @JsonSubTypes.Type( ResolverResolutionCompleted.class ), @JsonSubTypes.Type( CheckMultiDBSupport.class )
+ @JsonSubTypes.Type( ResolverResolutionCompleted.class ), @JsonSubTypes.Type( CheckMultiDBSupport.class ),
+ @JsonSubTypes.Type( DomainNameResolutionCompleted.class )
} )
public interface TestkitRequest
{
diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/DomainNameResolutionRequired.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/DomainNameResolutionRequired.java
new file mode 100644
index 0000000000..3f803cc021
--- /dev/null
+++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/responses/DomainNameResolutionRequired.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) "Neo4j"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package neo4j.org.testkit.backend.messages.responses;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+@Builder
+public class DomainNameResolutionRequired implements TestkitResponse
+{
+ private DomainNameResolutionRequiredBody data;
+
+ @Override
+ public String testkitName()
+ {
+ return "DomainNameResolutionRequired";
+ }
+
+ @Setter
+ @Getter
+ @Builder
+ public static class DomainNameResolutionRequiredBody
+ {
+ private String id;
+
+ private String name;
+ }
+}