Advanced connection information
Connection URI
The driver supports connection to URIs of the form
<SCHEME>://<HOST>[:<PORT>[?policy=<POLICY-NAME>]]
-
<SCHEME>
is one amongneo4j
,neo4j+s
,neo4j+ssc
,bolt
,bolt+s
,bolt+ssc
. -
<HOST>
is the host name where the Neo4j server is located. -
<PORT>
is optional, and denotes the port the Bolt protocol is available at. -
<POLICY-NAME>
is an optional server policy name. Server policies need to be set up prior to usage.
The driver does not support connection to a nested path, such as example.com/neo4j/ .
The server must be reachable from the domain root.
|
Connection protocols and security
Communication between the driver and the server is mediated by Bolt. The scheme of the server URI determines whether the connection is encrypted and, if so, what type of certificates are accepted.
URL scheme | Encryption | Comment |
---|---|---|
neo4j |
Default for local setups |
|
neo4j+s |
(only CA-signed certificates) |
Default for Aura |
neo4j+ssc |
(CA- and self-signed certificates) |
The driver receives a routing table from the server upon successful connection, regardless of whether the instance is a proper cluster environment or a single-machine environment.
The driver’s routing behavior works in tandem with Neo4j’s clustering by directing read/write transactions to appropriate cluster members.
If you want to target a specific machine, use the bolt , bolt+s , or bolt+ssc URI schemes instead.
|
The connection scheme to use is not your choice, but is rather determined by the server requirements. You must know the right server scheme upfront, as no metadata is exposed prior to connection. If you are unsure, ask the database administrator.
Authentication methods
Basic authentication (default)
The basic authentication scheme relies on traditional username and password. These can either be the credentials for your local installation, or the ones provided with an Aura instance.
// import org.neo4j.driver.AuthTokens;
// import org.neo4j.driver.GraphDatabase;
GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword));
The basic authentication scheme can also be used to authenticate against an LDAP server (Enterprise Edition only).
Kerberos authentication
The Kerberos authentication scheme requires a base64-encoded ticket. It can only be used if the server has the Kerberos Add-on installed.
// import org.neo4j.driver.AuthTokens;
// import org.neo4j.driver.GraphDatabase;
GraphDatabase.driver(dbUri, AuthTokens.kerberos(ticket));
Bearer authentication
The bearer authentication scheme requires a base64-encoded token provided by an Identity Provider through Neo4j’s Single Sign-On feature.
// import org.neo4j.driver.AuthTokens;
// import org.neo4j.driver.GraphDatabase;
GraphDatabase.driver(dbUri, AuthTokens.bearer(ticket));
The bearer authentication scheme requires configuring Single Sign-On on the server. Once configured, clients can discover Neo4j’s configuration through the Discovery API. |
Custom authentication
Use AuthTokens.custom()
to log into a server having a custom authentication scheme.
// import org.neo4j.driver.AuthTokens;
// import org.neo4j.driver.GraphDatabase;
GraphDatabase.driver(dbUri, AuthTokens.custom(principal, credentials, realm, scheme, parameters));
Rotating authentication tokens
It is possible to rotate authentication tokens that are expected to expire (e.g. SSO).
You need to provide a AuthTokenManager
instance when instantiating the Driver
, rather than a static authentication token.
The easiest way to get started is to use one of built-in AuthTokenManager
implementations. AuthTokenManagers work with AuthToken
objects.
// import java.time.Clock;
// import java.util.concurrent.TimeUnit;
// import org.neo4j.driver.AuthTokenManagers;
// import org.neo4j.driver.AuthTokens;
// import org.neo4j.driver.GraphDatabase;
void rotatingBearerDriver() {
var tokenManager = AuthTokenManagers.bearer(() -> {
var token = AuthTokens.bearer(getToken());
// Assume we know tokens expire every 60 seconds
var expiresIn = TimeUnit.SECONDS.toMillis(60);
// Include a little buffer so that new token is fetched before the old one expires
var expiration = Clock.systemUTC().millis() + (expiresIn - TimeUnit.SECONDS.toMillis(10));
return token.expiringAt(expiration);
});
var driver = GraphDatabase.driver(dbUri, tokenManager);
}
// Some way to get a token
private String getToken() {
return "token-string";
}
This API must not be used for switching users. Auth managers must always return tokens for the same identity. You can switch users at both query level and session level. |
AuthTokenManager objects must not interact with the driver in any way, as this can cause deadlocks and undefined behavior.
|
Logging
By default, the driver logs INFO
messages through the Java logging framework java.util.logging
.
To change the driver’s logging behavior, use the .withLogging()
method when creating a Driver
object.
// import java.util.logging.Level;
// import org.neo4j.driver.AuthTokens;
// import org.neo4j.driver.Config;
// import org.neo4j.driver.GraphDatabase;
// import org.neo4j.driver.Logging;
try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword),
Config.builder().withLogging(Logging.console(Level.FINE)).build())) {
driver.verifyConnectivity();
}
2023-12-22T10:36:39.997882867 INFO org.neo4j.driver.internal.DriverFactory - Routing driver instance 1651855867 created for server address localhost:7687
2023-12-22T10:36:40.03430944 FINE io.netty.channel.DefaultChannelId - -Dio.netty.processId: 23665 (auto-detected)
2023-12-22T10:36:40.036871656 FINE io.netty.util.NetUtil - -Djava.net.preferIPv4Stack: false
2023-12-22T10:36:40.037023871 FINE io.netty.util.NetUtil - -Djava.net.preferIPv6Addresses: false
2023-12-22T10:36:40.03827624 FINE io.netty.util.NetUtilInitializations - Loopback interface: lo (lo, 0:0:0:0:0:0:0:1%lo)
2023-12-22T10:36:40.038877108 FINE io.netty.util.NetUtil - /proc/sys/net/core/somaxconn: 4096
2023-12-22T10:36:40.03958947 FINE io.netty.channel.DefaultChannelId - -Dio.netty.machineId: 04:cf:4b:ff:fe:0e:ee:99 (auto-detected)
2023-12-22T10:36:40.04531968 FINE io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.level: simple
2023-12-22T10:36:40.045471749 FINE io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.targetRecords: 4
2023-12-22T10:36:40.059848221 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numHeapArenas: 40
2023-12-22T10:36:40.060000842 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numDirectArenas: 40
2023-12-22T10:36:40.060113675 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.pageSize: 8192
2023-12-22T10:36:40.060219802 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxOrder: 9
2023-12-22T10:36:40.060324679 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.chunkSize: 4194304
2023-12-22T10:36:40.060442554 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.smallCacheSize: 256
2023-12-22T10:36:40.060547232 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.normalCacheSize: 64
2023-12-22T10:36:40.060648929 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedBufferCapacity: 32768
2023-12-22T10:36:40.060750268 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimInterval: 8192
2023-12-22T10:36:40.060858214 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimIntervalMillis: 0
2023-12-22T10:36:40.060965492 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.useCacheForAllThreads: false
2023-12-22T10:36:40.061068878 FINE io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedByteBuffersPerChunk: 1023
2023-12-22T10:36:40.069792775 FINE io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: pooled
2023-12-22T10:36:40.069957048 FINE io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 0
2023-12-22T10:36:40.070070891 FINE io.netty.buffer.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 16384
2023-12-22T10:36:40.102235419 FINE io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkAccessible: true
2023-12-22T10:36:40.102408774 FINE io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkBounds: true
2023-12-22T10:36:40.103026138 FINE io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@1a67b908
2023-12-22T10:36:40.104721387 FINE org.neo4j.driver.internal.async.connection.ChannelConnectedListener - [0xb354eed2][localhost(127.0.0.1):7687][] C: [Bolt Handshake] [0x6060b017, 263173, 132100, 260, 3]
2023-12-22T10:36:40.106645202 FINE io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096
2023-12-22T10:36:40.106785483 FINE io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
2023-12-22T10:36:40.106887674 FINE io.netty.util.Recycler - -Dio.netty.recycler.chunkSize: 32
2023-12-22T10:36:40.106993748 FINE io.netty.util.Recycler - -Dio.netty.recycler.blocking: false
2023-12-22T10:36:40.107096042 FINE io.netty.util.Recycler - -Dio.netty.recycler.batchFastThreadLocalOnly: true
2023-12-22T10:36:40.11603651 FINE org.neo4j.driver.internal.async.connection.HandshakeHandler - [0xb354eed2][localhost(127.0.0.1):7687][] S: [Bolt Handshake] 5.4
2023-12-22T10:36:40.128082306 FINE org.neo4j.driver.internal.async.outbound.OutboundMessageHandler - [0xb354eed2][localhost(127.0.0.1):7687][] C: HELLO {routing={address: "localhost:7687"}, bolt_agent={product: "neo4j-java/dev", language: "Java/17.0.9", language_details: "Optional[Eclipse Adoptium; OpenJDK 64-Bit Server VM; 17.0.9+9]", platform: "Linux; 5.15.0-91-generic; amd64"}, user_agent="neo4j-java/dev"}
2023-12-22T10:36:40.130350166 FINE org.neo4j.driver.internal.async.pool.NettyChannelTracker - Channel [0xb354eed2] created. Local address: /127.0.0.1:32794, remote address: /127.0.0.1:7687
2023-12-22T10:36:40.130746872 FINE org.neo4j.driver.internal.async.pool.NettyChannelTracker - Channel [0xb354eed2] acquired from the pool. Local address: /127.0.0.1:32794, remote address: /127.0.0.1:7687
2023-12-22T10:36:40.133652153 FINE org.neo4j.driver.internal.async.outbound.OutboundMessageHandler - [0xb354eed2][localhost(127.0.0.1):7687][] C: LOGON {principal="neo4j", scheme="basic", credentials="******"}
2023-12-22T10:36:40.140017819 FINE org.neo4j.driver.internal.async.inbound.InboundMessageDispatcher - [0xb354eed2][localhost(127.0.0.1):7687][] S: SUCCESS {server="Neo4j/5.16.0", connection_id="bolt-5", hints={connection.recv_timeout_seconds: 120}}
2023-12-22T10:36:40.142229689 FINE org.neo4j.driver.internal.async.inbound.InboundMessageDispatcher - [0xb354eed2][localhost(127.0.0.1):7687][bolt-5] S: SUCCESS {}
2023-12-22T10:36:40.14568667 FINE org.neo4j.driver.internal.async.outbound.OutboundMessageHandler - [0xb354eed2][localhost(127.0.0.1):7687][bolt-5] C: RESET
2023-12-22T10:36:40.146897982 FINE org.neo4j.driver.internal.async.NetworkConnection - Added ConnectionReadTimeoutHandler
2023-12-22T10:36:40.14753571 FINE org.neo4j.driver.internal.async.inbound.InboundMessageDispatcher - [0xb354eed2][localhost(127.0.0.1):7687][bolt-5] S: SUCCESS {}
2023-12-22T10:36:40.147813446 FINE org.neo4j.driver.internal.async.NetworkConnection - Removed ConnectionReadTimeoutHandler
2023-12-22T10:36:40.14895232 FINE org.neo4j.driver.internal.async.pool.NettyChannelTracker - Channel [0xb354eed2] released back to the pool
2023-12-22T10:36:40.15199869 FINE org.neo4j.driver.internal.cluster.RoutingTableRegistryImpl - Routing table handler for database 'system' is added.
2023-12-22T10:36:40.152613749 FINE org.neo4j.driver.internal.cluster.RoutingTableHandlerImpl - Routing table for database 'system' is stale. Ttl 1703237800150, currentTime 1703237800152, routers [], writers [], readers [], database 'system'
2023-12-22T10:36:40.159510973 FINE org.neo4j.driver.internal.async.pool.NettyChannelTracker - Channel [0xb354eed2] acquired from the pool. Local address: /127.0.0.1:32794, remote address: /127.0.0.1:7687
2023-12-22T10:36:40.165704119 FINE org.neo4j.driver.internal.async.outbound.OutboundMessageHandler - [0xb354eed2][localhost(127.0.0.1):7687][bolt-5] C: ROUTE {address="localhost:7687"} [] system null
2023-12-22T10:36:40.168929698 FINE org.neo4j.driver.internal.async.NetworkConnection - Added ConnectionReadTimeoutHandler
2023-12-22T10:36:40.171700427 FINE org.neo4j.driver.internal.async.inbound.InboundMessageDispatcher - [0xb354eed2][localhost(127.0.0.1):7687][bolt-5] S: SUCCESS {rt={servers: [{addresses: ["localhost:7687"], role: "WRITE"}, {addresses: ["localhost:7687"], role: "READ"}, {addresses: ["localhost:7687"], role: "ROUTE"}], ttl: 300, db: "system"}}
2023-12-22T10:36:40.17187084 FINE org.neo4j.driver.internal.async.NetworkConnection - Removed ConnectionReadTimeoutHandler
2023-12-22T10:36:40.173921853 FINE org.neo4j.driver.internal.async.outbound.OutboundMessageHandler - [0xb354eed2][localhost(127.0.0.1):7687][bolt-5] C: RESET
2023-12-22T10:36:40.174473474 FINE org.neo4j.driver.internal.async.NetworkConnection - Added ConnectionReadTimeoutHandler
2023-12-22T10:36:40.175516332 FINE org.neo4j.driver.internal.async.inbound.InboundMessageDispatcher - [0xb354eed2][localhost(127.0.0.1):7687][bolt-5] S: SUCCESS {}
2023-12-22T10:36:40.175679271 FINE org.neo4j.driver.internal.async.NetworkConnection - Removed ConnectionReadTimeoutHandler
2023-12-22T10:36:40.175849144 FINE org.neo4j.driver.internal.async.pool.NettyChannelTracker - Channel [0xb354eed2] released back to the pool
2023-12-22T10:36:40.182085603 FINE org.neo4j.driver.internal.cluster.RoutingTableHandlerImpl - Fetched cluster composition for database 'system'. ClusterComposition{readers=[localhost:7687], writers=[localhost:7687], routers=[localhost:7687], expirationTimestamp=1703238100176, databaseName=system}
2023-12-22T10:36:40.185015699 FINE org.neo4j.driver.internal.cluster.RoutingTableHandlerImpl - Updated routing table for database 'system'. Ttl 1703238100176, currentTime 1703237800184, routers [localhost:7687], writers [localhost:7687], readers [localhost:7687], database 'system'
2023-12-22T10:36:40.18530819 INFO org.neo4j.driver.internal.InternalDriver - Closing driver instance 1651855867
2023-12-22T10:36:40.186508052 FINE org.neo4j.driver.internal.async.outbound.OutboundMessageHandler - [0xb354eed2][localhost(127.0.0.1):7687][bolt-5] C: GOODBYE
2023-12-22T10:36:40.187291369 INFO org.neo4j.driver.internal.async.pool.ConnectionPoolImpl - Closing connection pool towards localhost(127.0.0.1):7687
2023-12-22T10:36:40.189599992 FINE org.neo4j.driver.internal.async.inbound.ChannelErrorHandler - [0xb354eed2][localhost(127.0.0.1):7687][bolt-5] Channel is inactive
2023-12-22T10:36:40.395356347 FINE io.netty.buffer.PoolThreadCache - Freed 6 thread-local buffer(s) from thread: Neo4jDriverIO-2-2
Custom address resolver
When creating a Driver
object, you can specify a resolver function to resolve the connection address the driver is initialized with.
Note that addresses that the driver receives in routing tables are not resolved with the custom resolver.
You specify a resolver through the .withResolver()
config method, which works with ServerAddress
objects.
example.com
on port 9999
is resolved to localhost
on port 7687
// import java.util.Set;
// import org.neo4j.driver.AuthTokens;
// import org.neo4j.driver.Config;
// import org.neo4j.driver.GraphDatabase;
// import org.neo4j.driver.net.ServerAddress;
var addresses = Set.of(
ServerAddress.of("localhost", 7687) // omit the scheme; provide only host
);
var config = Config.builder()
.withResolver(address -> addresses)
.build();
try (var driver = GraphDatabase.driver("neo4j://example.com:9999", AuthTokens.basic(dbUser, dbPassword), config)) {
driver.verifyConnectivity();
}
OCSP stapling
If OCSP stapling is enabled on the server, the driver can be configured to check for certificate revocations during SSL handshakes. OCSP stapling improves both security and performance when using CA-signed certificates.
There are two methods implementing this feature:
-
.withVerifyIfPresentRevocationChecks()
— validate a certificate’s stapling if available, but don’t fail verification if no stapling is found. -
.withStrictRevocationChecks()
— validate a certificate’s stapling, and fail verification if no stapling is found.
Both methods act on a Config.TrustStrategy
object, so you have to be explicit about what certificates you want to trust and cannot rely on the driver to infer it from the connection URI scheme.
This means that you have to chain these methods to Config.TrustStrategy.trustSystemCertificates()
.
To avoid configuration clashes, the connection URI scheme must also be set to neo4j
(i.e. not neo4j+s
nor neo4j+ssc
).
// import org.neo4j.driver.Config;
Config config = Config.builder()
.withEncryption()
.withTrustStrategy(Config.TrustStrategy
.trustSystemCertificates()
.withVerifyIfPresentRevocationChecks())
.build();
try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword), config)) {
driver.verifyConnectivity();
}
Further connection parameters
You can find all Driver
configuration parameters in the API documentation → driver.GraphDatabase.
Glossary
- LTS
-
A Long Term Support release is one guaranteed to be supported for a number of years. Neo4j 4.4 is LTS, and Neo4j 5 will also have an LTS version.
- Aura
-
Aura is Neo4j’s fully managed cloud service. It comes with both free and paid plans.
- Cypher
-
Cypher is Neo4j’s graph query language that lets you retrieve data from the database. It is like SQL, but for graphs.
- APOC
-
Awesome Procedures On Cypher (APOC) is a library of (many) functions that can not be easily expressed in Cypher itself.
- Bolt
-
Bolt is the protocol used for interaction between Neo4j instances and drivers. It listens on port 7687 by default.
- ACID
-
Atomicity, Consistency, Isolation, Durability (ACID) are properties guaranteeing that database transactions are processed reliably. An ACID-compliant DBMS ensures that the data in the database remains accurate and consistent despite failures.
- eventual consistency
-
A database is eventually consistent if it provides the guarantee that all cluster members will, at some point in time, store the latest version of the data.
- causal consistency
-
A database is causally consistent if read and write queries are seen by every member of the cluster in the same order. This is stronger than eventual consistency.
- NULL
-
The null marker is not a type but a placeholder for absence of value. For more information, see Cypher → Working with
null
. - transaction
-
A transaction is a unit of work that is either committed in its entirety or rolled back on failure. An example is a bank transfer: it involves multiple steps, but they must all succeed or be reverted, to avoid money being subtracted from one account but not added to the other.
- backpressure
-
Backpressure is a force opposing the flow of data. It ensures that the client is not being overwhelmed by data faster than it can handle.
- transaction function
-
A transaction function is a callback executed by an
executeRead
orexecuteWrite
call. The driver automatically re-executes the callback in case of server failure. - Driver
-
A
Driver
object holds the details required to establish connections with a Neo4j database.