-
Notifications
You must be signed in to change notification settings - Fork 41.5k
Update Neo4j support to require Neo4j Java Driver 6.0.0 #47381
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,9 +21,12 @@ | |
import java.time.Duration; | ||
import java.util.List; | ||
import java.util.Locale; | ||
import java.util.ServiceLoader; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import io.micrometer.observation.ObservationRegistry; | ||
import org.jspecify.annotations.Nullable; | ||
import org.neo4j.bolt.connection.BoltConnectionProviderFactory; | ||
import org.neo4j.driver.AuthToken; | ||
import org.neo4j.driver.AuthTokenManager; | ||
import org.neo4j.driver.AuthTokens; | ||
|
@@ -32,6 +35,7 @@ | |
import org.neo4j.driver.Driver; | ||
import org.neo4j.driver.GraphDatabase; | ||
import org.neo4j.driver.internal.Scheme; | ||
import org.neo4j.driver.observation.micrometer.MicrometerObservationProvider; | ||
|
||
import org.springframework.beans.factory.ObjectProvider; | ||
import org.springframework.boot.autoconfigure.AutoConfiguration; | ||
|
@@ -63,6 +67,20 @@ | |
@EnableConfigurationProperties(Neo4jProperties.class) | ||
public final class Neo4jAutoConfiguration { | ||
|
||
private static final boolean HAS_DRIVER_METRICS; | ||
|
||
static { | ||
boolean metricsObservationProviderFound = true; | ||
try { | ||
Class.forName("org.neo4j.driver.observation.micrometer.MicrometerObservationProvider", false, | ||
Neo4jAutoConfiguration.class.getClassLoader()); | ||
} | ||
catch (ClassNotFoundException ex) { | ||
metricsObservationProviderFound = false; | ||
} | ||
HAS_DRIVER_METRICS = metricsObservationProviderFound; | ||
} | ||
|
||
@Bean | ||
@ConditionalOnMissingBean(Neo4jConnectionDetails.class) | ||
PropertiesNeo4jConnectionDetails neo4jConnectionDetails(Neo4jProperties properties, | ||
|
@@ -73,10 +91,11 @@ PropertiesNeo4jConnectionDetails neo4jConnectionDetails(Neo4jProperties properti | |
@Bean | ||
@ConditionalOnMissingBean | ||
Driver neo4jDriver(Neo4jProperties properties, Environment environment, Neo4jConnectionDetails connectionDetails, | ||
ObjectProvider<ConfigBuilderCustomizer> configBuilderCustomizers) { | ||
ObjectProvider<ConfigBuilderCustomizer> configBuilderCustomizers, | ||
ObjectProvider<ObservationRegistry> observationRegistryProvider) { | ||
|
||
Config config = mapDriverConfig(properties, connectionDetails, | ||
configBuilderCustomizers.orderedStream().toList()); | ||
configBuilderCustomizers.orderedStream().toList(), observationRegistryProvider); | ||
AuthTokenManager authTokenManager = connectionDetails.getAuthTokenManager(); | ||
if (authTokenManager != null) { | ||
return GraphDatabase.driver(connectionDetails.getUri(), authTokenManager, config); | ||
|
@@ -86,29 +105,29 @@ Driver neo4jDriver(Neo4jProperties properties, Environment environment, Neo4jCon | |
} | ||
|
||
Config mapDriverConfig(Neo4jProperties properties, Neo4jConnectionDetails connectionDetails, | ||
List<ConfigBuilderCustomizer> customizers) { | ||
List<ConfigBuilderCustomizer> customizers, | ||
ObjectProvider<ObservationRegistry> observationRegistryProvider) { | ||
Config.ConfigBuilder builder = Config.builder(); | ||
configurePoolSettings(builder, properties.getPool()); | ||
configurePoolSettings(builder, properties.getPool(), observationRegistryProvider); | ||
URI uri = connectionDetails.getUri(); | ||
String scheme = (uri != null) ? uri.getScheme() : "bolt"; | ||
configureDriverSettings(builder, properties, isSimpleScheme(scheme)); | ||
builder.withLogging(new Neo4jSpringJclLogging()); | ||
customizers.forEach((customizer) -> customizer.customize(builder)); | ||
return builder.build(); | ||
} | ||
|
||
private boolean isSimpleScheme(String scheme) { | ||
String lowerCaseScheme = scheme.toLowerCase(Locale.ENGLISH); | ||
try { | ||
Scheme.validateScheme(lowerCaseScheme); | ||
} | ||
catch (IllegalArgumentException ex) { | ||
if (!ServiceLoader.load(BoltConnectionProviderFactory.class) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's quite a bit of ceremony here. Do we really need to invoke "any" factory this way? Also this adds an import on |
||
.stream() | ||
.anyMatch((p) -> p.get().supports(lowerCaseScheme))) { | ||
throw new IllegalArgumentException(String.format("'%s' is not a supported scheme.", scheme)); | ||
} | ||
return lowerCaseScheme.equals("bolt") || lowerCaseScheme.equals("neo4j"); | ||
return !Scheme.isSecurityScheme(lowerCaseScheme); | ||
} | ||
|
||
private void configurePoolSettings(Config.ConfigBuilder builder, Pool pool) { | ||
private void configurePoolSettings(Config.ConfigBuilder builder, Pool pool, | ||
ObjectProvider<ObservationRegistry> observationRegistryProvider) { | ||
if (pool.isLogLeakedSessions()) { | ||
builder.withLeakedSessionsLogging(); | ||
} | ||
|
@@ -120,12 +139,11 @@ private void configurePoolSettings(Config.ConfigBuilder builder, Pool pool) { | |
builder.withMaxConnectionLifetime(pool.getMaxConnectionLifetime().toMillis(), TimeUnit.MILLISECONDS); | ||
builder.withConnectionAcquisitionTimeout(pool.getConnectionAcquisitionTimeout().toMillis(), | ||
TimeUnit.MILLISECONDS); | ||
if (pool.isMetricsEnabled()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure I like that change. If metrics vs. no metrics is no longer needed, then I think the Is there a reason to keep having a flag for this or was it just an attempt at migrating what we had before? |
||
builder.withDriverMetrics(); | ||
} | ||
else { | ||
builder.withoutDriverMetrics(); | ||
} | ||
observationRegistryProvider.ifAvailable((orp) -> { | ||
if (pool.isMetricsEnabled() && HAS_DRIVER_METRICS) { | ||
builder.withObservationProvider(MicrometerObservationProvider.builder(orp).build()); | ||
} | ||
}); | ||
} | ||
|
||
private void configureDriverSettings(Config.ConfigBuilder builder, Neo4jProperties properties, | ||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't do this here. If we did then we could not configure a Neo4j driver without the observation registry on the classpath.