Browse Source
This commit adds the support for creating a managed instance of the Neo4j Java driver. The low-level support for Neo4j is helpful in situations where the high-level abstraction of Spring Data Neo4j is not needed. See gh-22301pull/22604/head
12 changed files with 1212 additions and 2 deletions
@ -0,0 +1,193 @@
@@ -0,0 +1,193 @@
|
||||
/* |
||||
* Copyright 2012-2020 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.boot.autoconfigure.neo4j; |
||||
|
||||
import java.io.File; |
||||
import java.net.URI; |
||||
import java.time.Duration; |
||||
import java.util.Locale; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
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.internal.Scheme; |
||||
import org.neo4j.driver.net.ServerAddressResolver; |
||||
|
||||
import org.springframework.beans.BeanUtils; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties; |
||||
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* Automatic configuration of Neo4j's Java Driver. |
||||
* |
||||
* @author Michael J. Simons |
||||
* @since 2.4.0 |
||||
*/ |
||||
@Configuration(proxyBeanMethods = false) |
||||
@ConditionalOnClass(Driver.class) |
||||
@EnableConfigurationProperties(Neo4jProperties.class) |
||||
public class Neo4jAutoConfiguration { |
||||
|
||||
@Bean |
||||
@ConditionalOnMissingBean(Driver.class) |
||||
Driver neo4jDriver(Neo4jProperties properties) { |
||||
AuthToken authToken = asAuthToken(properties.getAuthentication()); |
||||
Config config = asDriverConfig(properties); |
||||
return GraphDatabase.driver(properties.getUri(), authToken, config); |
||||
} |
||||
|
||||
static AuthToken asAuthToken(Neo4jProperties.Authentication authentication) { |
||||
String username = authentication.getUsername(); |
||||
String password = authentication.getPassword(); |
||||
String kerberosTicket = authentication.getKerberosTicket(); |
||||
String realm = authentication.getRealm(); |
||||
|
||||
boolean hasUsername = StringUtils.hasText(username); |
||||
boolean hasPassword = StringUtils.hasText(password); |
||||
boolean hasKerberosTicket = StringUtils.hasText(kerberosTicket); |
||||
|
||||
if (hasUsername && hasKerberosTicket) { |
||||
throw new InvalidConfigurationPropertyValueException("org.neo4j.driver.authentication", |
||||
"username=" + username + ",kerberos-ticket=" + kerberosTicket, |
||||
"Cannot specify both username and kerberos ticket."); |
||||
} |
||||
|
||||
if (hasUsername && hasPassword) { |
||||
return AuthTokens.basic(username, password, realm); |
||||
} |
||||
|
||||
if (hasKerberosTicket) { |
||||
return AuthTokens.kerberos(kerberosTicket); |
||||
} |
||||
|
||||
return AuthTokens.none(); |
||||
} |
||||
|
||||
static Config asDriverConfig(Neo4jProperties properties) { |
||||
Config.ConfigBuilder builder = Config.builder(); |
||||
applyTo(builder, properties.getPool()); |
||||
URI uri = properties.getUri(); |
||||
String scheme = (uri != null) ? uri.getScheme() : "bolt"; |
||||
applyTo(builder, properties.getConfig(), isSimpleScheme(scheme)); |
||||
|
||||
return builder.withLogging(new Neo4jSpringJclLogging()).build(); |
||||
} |
||||
|
||||
static boolean isSimpleScheme(String scheme) { |
||||
String lowerCaseScheme = scheme.toLowerCase(Locale.ENGLISH); |
||||
try { |
||||
Scheme.validateScheme(lowerCaseScheme); |
||||
} |
||||
catch (IllegalArgumentException ex) { |
||||
throw new IllegalArgumentException(String.format("'%s' is not a supported scheme.", scheme)); |
||||
} |
||||
|
||||
return lowerCaseScheme.equals("bolt") || lowerCaseScheme.equals("neo4j"); |
||||
} |
||||
|
||||
private static void applyTo(Config.ConfigBuilder builder, Neo4jProperties.PoolSettings poolSettings) { |
||||
if (poolSettings.isLogLeakedSessions()) { |
||||
builder.withLeakedSessionsLogging(); |
||||
} |
||||
builder.withMaxConnectionPoolSize(poolSettings.getMaxConnectionPoolSize()); |
||||
Duration idleTimeBeforeConnectionTest = poolSettings.getIdleTimeBeforeConnectionTest(); |
||||
if (idleTimeBeforeConnectionTest != null) { |
||||
builder.withConnectionLivenessCheckTimeout(idleTimeBeforeConnectionTest.toMillis(), TimeUnit.MILLISECONDS); |
||||
} |
||||
builder.withMaxConnectionLifetime(poolSettings.getMaxConnectionLifetime().toMillis(), TimeUnit.MILLISECONDS); |
||||
builder.withConnectionAcquisitionTimeout(poolSettings.getConnectionAcquisitionTimeout().toMillis(), |
||||
TimeUnit.MILLISECONDS); |
||||
|
||||
if (poolSettings.isMetricsEnabled()) { |
||||
builder.withDriverMetrics(); |
||||
} |
||||
else { |
||||
builder.withoutDriverMetrics(); |
||||
} |
||||
} |
||||
|
||||
private static void applyTo(Config.ConfigBuilder builder, Neo4jProperties.DriverSettings driverSettings, |
||||
boolean withEncryptionAndTrustSettings) { |
||||
if (withEncryptionAndTrustSettings) { |
||||
applyEncryptionAndTrustSettings(builder, driverSettings); |
||||
} |
||||
|
||||
builder.withConnectionTimeout(driverSettings.getConnectionTimeout().toMillis(), TimeUnit.MILLISECONDS); |
||||
builder.withMaxTransactionRetryTime(driverSettings.getMaxTransactionRetryTime().toMillis(), |
||||
TimeUnit.MILLISECONDS); |
||||
|
||||
Class<? extends ServerAddressResolver> serverAddressResolverClass = driverSettings |
||||
.getServerAddressResolverClass(); |
||||
if (serverAddressResolverClass != null) { |
||||
builder.withResolver(BeanUtils.instantiateClass(serverAddressResolverClass)); |
||||
} |
||||
} |
||||
|
||||
private static void applyEncryptionAndTrustSettings(Config.ConfigBuilder builder, |
||||
Neo4jProperties.DriverSettings driverSettings) { |
||||
if (driverSettings.isEncrypted()) { |
||||
builder.withEncryption(); |
||||
} |
||||
else { |
||||
builder.withoutEncryption(); |
||||
} |
||||
builder.withTrustStrategy(toInternalRepresentation(driverSettings.getTrustSettings())); |
||||
} |
||||
|
||||
static Config.TrustStrategy toInternalRepresentation(Neo4jProperties.TrustSettings trustSettings) { |
||||
String propertyName = "org.neo4j.driver.config.trust-settings"; |
||||
|
||||
Config.TrustStrategy internalRepresentation; |
||||
Neo4jProperties.TrustSettings.Strategy strategy = trustSettings.getStrategy(); |
||||
switch (strategy) { |
||||
case TRUST_ALL_CERTIFICATES: |
||||
internalRepresentation = Config.TrustStrategy.trustAllCertificates(); |
||||
break; |
||||
case TRUST_SYSTEM_CA_SIGNED_CERTIFICATES: |
||||
internalRepresentation = Config.TrustStrategy.trustSystemCertificates(); |
||||
break; |
||||
case TRUST_CUSTOM_CA_SIGNED_CERTIFICATES: |
||||
File certFile = trustSettings.getCertFile(); |
||||
if (certFile == null || !certFile.isFile()) { |
||||
throw new InvalidConfigurationPropertyValueException(propertyName, strategy.name(), |
||||
"Configured trust strategy requires a certificate file."); |
||||
} |
||||
internalRepresentation = Config.TrustStrategy.trustCustomCertificateSignedBy(certFile); |
||||
break; |
||||
default: |
||||
throw new InvalidConfigurationPropertyValueException(propertyName, strategy.name(), "Unknown strategy."); |
||||
} |
||||
|
||||
if (trustSettings.isHostnameVerificationEnabled()) { |
||||
internalRepresentation.withHostnameVerification(); |
||||
} |
||||
else { |
||||
internalRepresentation.withoutHostnameVerification(); |
||||
} |
||||
|
||||
return internalRepresentation; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,357 @@
@@ -0,0 +1,357 @@
|
||||
/* |
||||
* Copyright 2012-2020 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.boot.autoconfigure.neo4j; |
||||
|
||||
import java.io.File; |
||||
import java.net.URI; |
||||
import java.time.Duration; |
||||
|
||||
import org.neo4j.driver.net.ServerAddressResolver; |
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
|
||||
/** |
||||
* Used to configure an instance of the {@link org.neo4j.driver.Driver Neo4j-Java-Driver}. |
||||
* |
||||
* @author Michael J. Simons |
||||
* @since 2.4.0 |
||||
*/ |
||||
@ConfigurationProperties(prefix = "spring.neo4j") |
||||
public class Neo4jProperties { |
||||
|
||||
/** |
||||
* Uri this driver should connect to. The driver supports bolt or neo4j as schemes. |
||||
*/ |
||||
private URI uri = URI.create("bolt://localhost:7687"); |
||||
|
||||
/** |
||||
* Authentication the driver is supposed to use. Maybe null. |
||||
*/ |
||||
private Authentication authentication = new Authentication(); |
||||
|
||||
/** |
||||
* Configuration of the connection pool. |
||||
*/ |
||||
private PoolSettings pool = new PoolSettings(); |
||||
|
||||
/** |
||||
* Detailed configuration of the driver. |
||||
*/ |
||||
private DriverSettings config = new DriverSettings(); |
||||
|
||||
public URI getUri() { |
||||
return this.uri; |
||||
} |
||||
|
||||
public void setUri(URI uri) { |
||||
this.uri = uri; |
||||
} |
||||
|
||||
public Authentication getAuthentication() { |
||||
return this.authentication; |
||||
} |
||||
|
||||
public void setAuthentication(Authentication authentication) { |
||||
this.authentication = authentication; |
||||
} |
||||
|
||||
public PoolSettings getPool() { |
||||
return this.pool; |
||||
} |
||||
|
||||
public void setPool(PoolSettings pool) { |
||||
this.pool = pool; |
||||
} |
||||
|
||||
public DriverSettings getConfig() { |
||||
return this.config; |
||||
} |
||||
|
||||
public void setConfig(DriverSettings config) { |
||||
this.config = config; |
||||
} |
||||
|
||||
public static class Authentication { |
||||
|
||||
/** |
||||
* Login of the user connecting to the database. |
||||
*/ |
||||
private String username; |
||||
|
||||
/** |
||||
* Password of the user connecting to the database. |
||||
*/ |
||||
private String password; |
||||
|
||||
/** |
||||
* Realm to connect to. |
||||
*/ |
||||
private String realm; |
||||
|
||||
/** |
||||
* Kerberos ticket for connecting to the database. Mutual exclusive with a given |
||||
* username. |
||||
*/ |
||||
private String kerberosTicket; |
||||
|
||||
public String getUsername() { |
||||
return this.username; |
||||
} |
||||
|
||||
public void setUsername(String username) { |
||||
this.username = username; |
||||
} |
||||
|
||||
public String getPassword() { |
||||
return this.password; |
||||
} |
||||
|
||||
public void setPassword(String password) { |
||||
this.password = password; |
||||
} |
||||
|
||||
public String getRealm() { |
||||
return this.realm; |
||||
} |
||||
|
||||
public void setRealm(String realm) { |
||||
this.realm = realm; |
||||
} |
||||
|
||||
public String getKerberosTicket() { |
||||
return this.kerberosTicket; |
||||
} |
||||
|
||||
public void setKerberosTicket(String kerberosTicket) { |
||||
this.kerberosTicket = kerberosTicket; |
||||
} |
||||
|
||||
} |
||||
|
||||
public static class PoolSettings { |
||||
|
||||
/** |
||||
* Flag, if metrics are enabled. |
||||
*/ |
||||
private boolean metricsEnabled = false; |
||||
|
||||
/** |
||||
* Flag, if leaked sessions logging is enabled. |
||||
*/ |
||||
private boolean logLeakedSessions = false; |
||||
|
||||
/** |
||||
* Maximum amount of connections in the connection pool towards a single database. |
||||
*/ |
||||
private int maxConnectionPoolSize = org.neo4j.driver.internal.async.pool.PoolSettings.DEFAULT_MAX_CONNECTION_POOL_SIZE; |
||||
|
||||
/** |
||||
* Pooled connections that have been idle in the pool for longer than this timeout |
||||
* will be tested before they are used again. |
||||
*/ |
||||
private Duration idleTimeBeforeConnectionTest; |
||||
|
||||
/** |
||||
* Pooled connections older than this threshold will be closed and removed from |
||||
* the pool. |
||||
*/ |
||||
private Duration maxConnectionLifetime = Duration |
||||
.ofMillis(org.neo4j.driver.internal.async.pool.PoolSettings.DEFAULT_MAX_CONNECTION_LIFETIME); |
||||
|
||||
/** |
||||
* Acquisition of new connections will be attempted for at most configured |
||||
* timeout. |
||||
*/ |
||||
private Duration connectionAcquisitionTimeout = Duration |
||||
.ofMillis(org.neo4j.driver.internal.async.pool.PoolSettings.DEFAULT_CONNECTION_ACQUISITION_TIMEOUT); |
||||
|
||||
public boolean isLogLeakedSessions() { |
||||
return this.logLeakedSessions; |
||||
} |
||||
|
||||
public void setLogLeakedSessions(boolean logLeakedSessions) { |
||||
this.logLeakedSessions = logLeakedSessions; |
||||
} |
||||
|
||||
public int getMaxConnectionPoolSize() { |
||||
return this.maxConnectionPoolSize; |
||||
} |
||||
|
||||
public void setMaxConnectionPoolSize(int maxConnectionPoolSize) { |
||||
this.maxConnectionPoolSize = maxConnectionPoolSize; |
||||
} |
||||
|
||||
public Duration getIdleTimeBeforeConnectionTest() { |
||||
return this.idleTimeBeforeConnectionTest; |
||||
} |
||||
|
||||
public void setIdleTimeBeforeConnectionTest(Duration idleTimeBeforeConnectionTest) { |
||||
this.idleTimeBeforeConnectionTest = idleTimeBeforeConnectionTest; |
||||
} |
||||
|
||||
public Duration getMaxConnectionLifetime() { |
||||
return this.maxConnectionLifetime; |
||||
} |
||||
|
||||
public void setMaxConnectionLifetime(Duration maxConnectionLifetime) { |
||||
this.maxConnectionLifetime = maxConnectionLifetime; |
||||
} |
||||
|
||||
public Duration getConnectionAcquisitionTimeout() { |
||||
return this.connectionAcquisitionTimeout; |
||||
} |
||||
|
||||
public void setConnectionAcquisitionTimeout(Duration connectionAcquisitionTimeout) { |
||||
this.connectionAcquisitionTimeout = connectionAcquisitionTimeout; |
||||
} |
||||
|
||||
public boolean isMetricsEnabled() { |
||||
return this.metricsEnabled; |
||||
} |
||||
|
||||
public void setMetricsEnabled(boolean metricsEnabled) { |
||||
this.metricsEnabled = metricsEnabled; |
||||
} |
||||
|
||||
} |
||||
|
||||
public static class DriverSettings { |
||||
|
||||
/** |
||||
* Flag, if the driver should use encrypted traffic. |
||||
*/ |
||||
private boolean encrypted = false; |
||||
|
||||
/** |
||||
* Specify how to determine the authenticity of an encryption certificate provided |
||||
* by the Neo4j instance we are connecting to. |
||||
*/ |
||||
private TrustSettings trustSettings = new TrustSettings(); |
||||
|
||||
/** |
||||
* Specify socket connection timeout. |
||||
*/ |
||||
private Duration connectionTimeout = Duration.ofSeconds(30); |
||||
|
||||
/** |
||||
* Specify the maximum time transactions are allowed to retry. |
||||
*/ |
||||
private Duration maxTransactionRetryTime = Duration |
||||
.ofMillis(org.neo4j.driver.internal.retry.RetrySettings.DEFAULT.maxRetryTimeMs()); |
||||
|
||||
/** |
||||
* Specify a custom server address resolver used by the routing driver to resolve |
||||
* the initial address used to create the driver. |
||||
*/ |
||||
private Class<? extends ServerAddressResolver> serverAddressResolverClass; |
||||
|
||||
public boolean isEncrypted() { |
||||
return this.encrypted; |
||||
} |
||||
|
||||
public void setEncrypted(boolean encrypted) { |
||||
this.encrypted = encrypted; |
||||
} |
||||
|
||||
public TrustSettings getTrustSettings() { |
||||
return this.trustSettings; |
||||
} |
||||
|
||||
public void setTrustSettings(TrustSettings trustSettings) { |
||||
this.trustSettings = trustSettings; |
||||
} |
||||
|
||||
public Duration getConnectionTimeout() { |
||||
return this.connectionTimeout; |
||||
} |
||||
|
||||
public void setConnectionTimeout(Duration connectionTimeout) { |
||||
this.connectionTimeout = connectionTimeout; |
||||
} |
||||
|
||||
public Duration getMaxTransactionRetryTime() { |
||||
return this.maxTransactionRetryTime; |
||||
} |
||||
|
||||
public void setMaxTransactionRetryTime(Duration maxTransactionRetryTime) { |
||||
this.maxTransactionRetryTime = maxTransactionRetryTime; |
||||
} |
||||
|
||||
public Class<? extends ServerAddressResolver> getServerAddressResolverClass() { |
||||
return this.serverAddressResolverClass; |
||||
} |
||||
|
||||
public void setServerAddressResolverClass(Class<? extends ServerAddressResolver> serverAddressResolverClass) { |
||||
this.serverAddressResolverClass = serverAddressResolverClass; |
||||
} |
||||
|
||||
} |
||||
|
||||
public static class TrustSettings { |
||||
|
||||
public enum Strategy { |
||||
|
||||
TRUST_ALL_CERTIFICATES, |
||||
|
||||
TRUST_CUSTOM_CA_SIGNED_CERTIFICATES, |
||||
|
||||
TRUST_SYSTEM_CA_SIGNED_CERTIFICATES |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Configures the strategy to use use. |
||||
*/ |
||||
private Strategy strategy = Strategy.TRUST_SYSTEM_CA_SIGNED_CERTIFICATES; |
||||
|
||||
/** |
||||
* File of the certificate to use. |
||||
*/ |
||||
private File certFile; |
||||
|
||||
/** |
||||
* Flag, if hostname verification is used. |
||||
*/ |
||||
private boolean hostnameVerificationEnabled = false; |
||||
|
||||
public Strategy getStrategy() { |
||||
return this.strategy; |
||||
} |
||||
|
||||
public void setStrategy(Strategy strategy) { |
||||
this.strategy = strategy; |
||||
} |
||||
|
||||
public File getCertFile() { |
||||
return this.certFile; |
||||
} |
||||
|
||||
public void setCertFile(File certFile) { |
||||
this.certFile = certFile; |
||||
} |
||||
|
||||
public boolean isHostnameVerificationEnabled() { |
||||
return this.hostnameVerificationEnabled; |
||||
} |
||||
|
||||
public void setHostnameVerificationEnabled(boolean hostnameVerificationEnabled) { |
||||
this.hostnameVerificationEnabled = hostnameVerificationEnabled; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,103 @@
@@ -0,0 +1,103 @@
|
||||
/* |
||||
* Copyright 2012-2020 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.boot.autoconfigure.neo4j; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.neo4j.driver.Logger; |
||||
import org.neo4j.driver.Logging; |
||||
|
||||
/** |
||||
* Shim to use Spring JCL implementation, delegating all the hard work of deciding the |
||||
* underlying system to Spring and Spring Boot. |
||||
* |
||||
* @author Michael J. Simons |
||||
*/ |
||||
class Neo4jSpringJclLogging implements Logging { |
||||
|
||||
/** |
||||
* This prefix gets added to the log names the driver requests to add some namespace |
||||
* around it in a bigger application scenario. |
||||
*/ |
||||
private static final String AUTOMATIC_PREFIX = "org.neo4j.driver."; |
||||
|
||||
@Override |
||||
public Logger getLog(String name) { |
||||
|
||||
String requestedLog = name; |
||||
if (!requestedLog.startsWith(AUTOMATIC_PREFIX)) { |
||||
requestedLog = AUTOMATIC_PREFIX + name; |
||||
} |
||||
Log springJclLog = LogFactory.getLog(requestedLog); |
||||
return new SpringJclLogger(springJclLog); |
||||
} |
||||
|
||||
static final class SpringJclLogger implements Logger { |
||||
|
||||
private final Log delegate; |
||||
|
||||
SpringJclLogger(Log delegate) { |
||||
this.delegate = delegate; |
||||
} |
||||
|
||||
@Override |
||||
public void error(String message, Throwable cause) { |
||||
this.delegate.error(message, cause); |
||||
} |
||||
|
||||
@Override |
||||
public void info(String format, Object... params) { |
||||
this.delegate.info(String.format(format, params)); |
||||
} |
||||
|
||||
@Override |
||||
public void warn(String format, Object... params) { |
||||
this.delegate.warn(String.format(format, params)); |
||||
} |
||||
|
||||
@Override |
||||
public void warn(String message, Throwable cause) { |
||||
this.delegate.warn(message, cause); |
||||
} |
||||
|
||||
@Override |
||||
public void debug(String format, Object... params) { |
||||
if (isDebugEnabled()) { |
||||
this.delegate.debug(String.format(format, params)); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void trace(String format, Object... params) { |
||||
if (isTraceEnabled()) { |
||||
this.delegate.trace(String.format(format, params)); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean isTraceEnabled() { |
||||
return this.delegate.isTraceEnabled(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isDebugEnabled() { |
||||
return this.delegate.isDebugEnabled(); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
/* |
||||
* Copyright 2012-2020 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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. |
||||
*/ |
||||
|
||||
/** |
||||
* Auto-configuration for Neo4j. |
||||
*/ |
||||
package org.springframework.boot.autoconfigure.neo4j; |
||||
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
/* |
||||
* Copyright 2012-2020 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.boot.autoconfigure.neo4j; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.neo4j.driver.Driver; |
||||
import org.neo4j.driver.Result; |
||||
import org.neo4j.driver.Session; |
||||
import org.neo4j.driver.Transaction; |
||||
import org.testcontainers.containers.Neo4jContainer; |
||||
import org.testcontainers.junit.jupiter.Container; |
||||
import org.testcontainers.junit.jupiter.Testcontainers; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.test.context.DynamicPropertyRegistry; |
||||
import org.springframework.test.context.DynamicPropertySource; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* @author Michael J. Simons |
||||
*/ |
||||
@SpringBootTest |
||||
@Testcontainers(disabledWithoutDocker = true) |
||||
class Neo4jAutoConfigurationIntegrationTests { |
||||
|
||||
@Container |
||||
private static Neo4jContainer<?> neo4jServer = new Neo4jContainer<>("neo4j:4.0"); |
||||
|
||||
@DynamicPropertySource |
||||
static void neo4jProperties(DynamicPropertyRegistry registry) { |
||||
registry.add("spring.neo4j.uri", neo4jServer::getBoltUrl); |
||||
registry.add("spring.neo4j.authentication.username", () -> "neo4j"); |
||||
registry.add("spring.neo4j.authentication.password", neo4jServer::getAdminPassword); |
||||
} |
||||
|
||||
private final Driver driver; |
||||
|
||||
@Autowired |
||||
Neo4jAutoConfigurationIntegrationTests(Driver driver) { |
||||
this.driver = driver; |
||||
} |
||||
|
||||
@Test |
||||
void ensureDriverIsOpen() { |
||||
|
||||
try (Session session = this.driver.session(); Transaction tx = session.beginTransaction()) { |
||||
Result statementResult = tx.run("MATCH (n:Thing) RETURN n LIMIT 1"); |
||||
assertThat(statementResult.hasNext()).isFalse(); |
||||
tx.commit(); |
||||
} |
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
@ImportAutoConfiguration(Neo4jAutoConfiguration.class) |
||||
static class TestConfiguration { |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,94 @@
@@ -0,0 +1,94 @@
|
||||
/* |
||||
* Copyright 2012-2020 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.boot.autoconfigure.neo4j; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.params.ParameterizedTest; |
||||
import org.junit.jupiter.params.provider.ValueSource; |
||||
import org.neo4j.driver.Driver; |
||||
import org.neo4j.driver.exceptions.ClientException; |
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations; |
||||
import org.springframework.boot.test.context.FilteredClassLoader; |
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.mockito.BDDMockito.mock; |
||||
import static org.mockito.BDDMockito.when; |
||||
|
||||
/** |
||||
* @author Michael J. Simons |
||||
*/ |
||||
class Neo4jAutoConfigurationTests { |
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() |
||||
.withConfiguration(AutoConfigurations.of(Neo4jAutoConfiguration.class)); |
||||
|
||||
@Test |
||||
void shouldRequireAllNeededClasses() { |
||||
|
||||
this.contextRunner.withPropertyValues("spring.neo4j.uri=bolt://localhost:4711") |
||||
.withClassLoader(new FilteredClassLoader(Driver.class)) |
||||
.run((ctx) -> assertThat(ctx).doesNotHaveBean(Driver.class)); |
||||
} |
||||
|
||||
@Test |
||||
void shouldNotRequireUri() { |
||||
|
||||
this.contextRunner.run((ctx) -> assertThat(ctx).hasSingleBean(Driver.class)); |
||||
} |
||||
|
||||
@Test |
||||
void shouldCreateDriver() { |
||||
|
||||
this.contextRunner.withPropertyValues("spring.neo4j.uri=bolt://localhost:4711") |
||||
.run((ctx) -> assertThat(ctx).hasSingleBean(Driver.class)); |
||||
} |
||||
|
||||
/** |
||||
* These tests assert correct configuration behaviour for cases in which one of the |
||||
* "advanced" schemes is used to configure the driver. If any of the schemes is used, |
||||
* than a contradicting explicit configuration will throw an error. |
||||
* @param scheme The scheme to test. |
||||
*/ |
||||
@ParameterizedTest |
||||
@ValueSource(strings = { "bolt+s", "bolt+ssc", "neo4j+s", "neo4j+ssc" }) |
||||
void schemesShouldBeApplied(String scheme) { |
||||
|
||||
this.contextRunner.withPropertyValues("spring.neo4j.uri=" + scheme + "://localhost:4711").run((ctx) -> { |
||||
assertThat(ctx).hasSingleBean(Driver.class); |
||||
|
||||
Driver driver = ctx.getBean(Driver.class); |
||||
assertThat(driver.isEncrypted()).isTrue(); |
||||
}); |
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
static class WithDriver { |
||||
|
||||
@Bean |
||||
Driver driver() { |
||||
Driver driver = mock(Driver.class); |
||||
when(driver.metrics()).thenThrow(ClientException.class); |
||||
return driver; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,319 @@
@@ -0,0 +1,319 @@
|
||||
/* |
||||
* Copyright 2012-2020 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.boot.autoconfigure.neo4j; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
import java.time.Duration; |
||||
|
||||
import org.junit.jupiter.api.Disabled; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.params.ParameterizedTest; |
||||
import org.junit.jupiter.params.provider.ValueSource; |
||||
import org.neo4j.driver.AuthTokens; |
||||
import org.neo4j.driver.Config; |
||||
import org.neo4j.driver.internal.retry.RetrySettings; |
||||
|
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jProperties.Authentication; |
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jProperties.DriverSettings; |
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jProperties.PoolSettings; |
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jProperties.TrustSettings; |
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jProperties.TrustSettings.Strategy; |
||||
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; |
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; |
||||
|
||||
/** |
||||
* @author Michael J. Simons |
||||
*/ |
||||
class Neo4jPropertiesTests { |
||||
|
||||
private static void assertDuration(Duration duration, long expectedValueInMillis) { |
||||
if (expectedValueInMillis == org.neo4j.driver.internal.async.pool.PoolSettings.NOT_CONFIGURED) { |
||||
assertThat(duration).isNull(); |
||||
} |
||||
else { |
||||
assertThat(duration.toMillis()).isEqualTo(expectedValueInMillis); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
void shouldAllowEmptyListOfURIs() { |
||||
Neo4jProperties driverProperties = new Neo4jProperties(); |
||||
assertThat(driverProperties.getAuthentication()).isNotNull(); |
||||
} |
||||
|
||||
@Test |
||||
void noAuthenticationShouldWork() { |
||||
Authentication authentication = new Authentication(); |
||||
assertThat(Neo4jAutoConfiguration.asAuthToken(authentication)).isEqualTo(AuthTokens.none()); |
||||
} |
||||
|
||||
@Test |
||||
void basicAuthShouldWork() { |
||||
Authentication authentication = new Authentication(); |
||||
authentication.setUsername("Farin"); |
||||
authentication.setPassword("Urlaub"); |
||||
|
||||
assertThat(Neo4jAutoConfiguration.asAuthToken(authentication)).isEqualTo(AuthTokens.basic("Farin", "Urlaub")); |
||||
} |
||||
|
||||
@Test |
||||
void basicAuthWithRealmShouldWork() { |
||||
Authentication authentication = new Authentication(); |
||||
authentication.setUsername("Farin"); |
||||
authentication.setPassword("Urlaub"); |
||||
authentication.setRealm("Die Ärzte"); |
||||
|
||||
assertThat(Neo4jAutoConfiguration.asAuthToken(authentication)) |
||||
.isEqualTo(AuthTokens.basic("Farin", "Urlaub", "Die Ärzte")); |
||||
} |
||||
|
||||
@Test |
||||
void kerberosAuthShouldWork() { |
||||
Authentication authentication = new Authentication(); |
||||
authentication.setKerberosTicket("AABBCCDDEE"); |
||||
|
||||
assertThat(Neo4jAutoConfiguration.asAuthToken(authentication)).isEqualTo(AuthTokens.kerberos("AABBCCDDEE")); |
||||
} |
||||
|
||||
@Test |
||||
void ambiguousShouldNotBeAllowed() { |
||||
Authentication authentication = new Authentication(); |
||||
authentication.setUsername("Farin"); |
||||
authentication.setKerberosTicket("AABBCCDDEE"); |
||||
|
||||
assertThatExceptionOfType(InvalidConfigurationPropertyValueException.class) |
||||
.isThrownBy(() -> Neo4jAutoConfiguration.asAuthToken(authentication)).withMessage( |
||||
"Property org.neo4j.driver.authentication with value 'username=Farin,kerberos-ticket=AABBCCDDEE' is invalid: Cannot specify both username and kerberos ticket."); |
||||
} |
||||
|
||||
@Test |
||||
void poolSettingsShouldDefaultToDriversValues() { |
||||
Config defaultConfig = Config.defaultConfig(); |
||||
|
||||
Neo4jProperties driverProperties = new Neo4jProperties(); |
||||
|
||||
PoolSettings poolSettings = driverProperties.getPool(); |
||||
assertThat(poolSettings.isLogLeakedSessions()).isEqualTo(defaultConfig.logLeakedSessions()); |
||||
assertThat(poolSettings.getMaxConnectionPoolSize()).isEqualTo(defaultConfig.maxConnectionPoolSize()); |
||||
assertDuration(poolSettings.getIdleTimeBeforeConnectionTest(), defaultConfig.idleTimeBeforeConnectionTest()); |
||||
assertDuration(poolSettings.getMaxConnectionLifetime(), defaultConfig.maxConnectionLifetimeMillis()); |
||||
assertDuration(poolSettings.getConnectionAcquisitionTimeout(), |
||||
defaultConfig.connectionAcquisitionTimeoutMillis()); |
||||
assertThat(poolSettings.isMetricsEnabled()).isFalse(); |
||||
} |
||||
|
||||
@Test |
||||
void logLeakedSessionsSettingsShouldWork() { |
||||
Neo4jProperties driverProperties; |
||||
|
||||
driverProperties = new Neo4jProperties(); |
||||
driverProperties.getPool().setLogLeakedSessions(true); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).logLeakedSessions()).isTrue(); |
||||
|
||||
driverProperties = new Neo4jProperties(); |
||||
driverProperties.getPool().setLogLeakedSessions(false); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).logLeakedSessions()).isFalse(); |
||||
} |
||||
|
||||
@Test |
||||
void maxConnectionPoolSizeSettingsShouldWork() { |
||||
Neo4jProperties driverProperties = new Neo4jProperties(); |
||||
driverProperties.getPool().setMaxConnectionPoolSize(4711); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).maxConnectionPoolSize()).isEqualTo(4711); |
||||
} |
||||
|
||||
@Test |
||||
void idleTimeBeforeConnectionTestSettingsShouldWork() { |
||||
Neo4jProperties driverProperties; |
||||
|
||||
driverProperties = new Neo4jProperties(); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).idleTimeBeforeConnectionTest()) |
||||
.isEqualTo(-1); |
||||
|
||||
driverProperties = new Neo4jProperties(); |
||||
driverProperties.getPool().setIdleTimeBeforeConnectionTest(Duration.ofSeconds(23)); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).idleTimeBeforeConnectionTest()) |
||||
.isEqualTo(23_000); |
||||
} |
||||
|
||||
@Test |
||||
void connectionAcquisitionTimeoutSettingsShouldWork() { |
||||
Neo4jProperties driverProperties = new Neo4jProperties(); |
||||
driverProperties.getPool().setConnectionAcquisitionTimeout(Duration.ofSeconds(23)); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).connectionAcquisitionTimeoutMillis()) |
||||
.isEqualTo(23_000); |
||||
} |
||||
|
||||
@Test |
||||
void enableMetricsShouldWork() { |
||||
Neo4jProperties driverProperties = new Neo4jProperties(); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).isMetricsEnabled()).isFalse(); |
||||
|
||||
driverProperties.getPool().setMetricsEnabled(true); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).isMetricsEnabled()).isTrue(); |
||||
} |
||||
|
||||
@Test |
||||
void driverSettingsShouldDefaultToDriversValues() { |
||||
Config defaultConfig = Config.defaultConfig(); |
||||
|
||||
Neo4jProperties driverProperties = new Neo4jProperties(); |
||||
|
||||
DriverSettings driverSettings = driverProperties.getConfig(); |
||||
assertThat(driverSettings.isEncrypted()).isEqualTo(defaultConfig.encrypted()); |
||||
assertThat(driverSettings.getTrustSettings().getStrategy().name()) |
||||
.isEqualTo(defaultConfig.trustStrategy().strategy().name()); |
||||
assertDuration(driverSettings.getConnectionTimeout(), defaultConfig.connectionTimeoutMillis()); |
||||
assertDuration(driverSettings.getMaxTransactionRetryTime(), RetrySettings.DEFAULT.maxRetryTimeMs()); |
||||
assertThat(driverSettings.getServerAddressResolverClass()).isNull(); |
||||
} |
||||
|
||||
@Test |
||||
void encryptedSettingsShouldWork() { |
||||
Neo4jProperties driverProperties; |
||||
|
||||
driverProperties = new Neo4jProperties(); |
||||
driverProperties.getConfig().setEncrypted(true); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).encrypted()).isTrue(); |
||||
|
||||
driverProperties = new Neo4jProperties(); |
||||
driverProperties.getConfig().setEncrypted(false); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).encrypted()).isFalse(); |
||||
} |
||||
|
||||
@Test |
||||
void trustSettingsShouldWork() { |
||||
Neo4jProperties driverProperties = new Neo4jProperties(); |
||||
TrustSettings trustSettings = new TrustSettings(); |
||||
trustSettings.setStrategy(Strategy.TRUST_SYSTEM_CA_SIGNED_CERTIFICATES); |
||||
driverProperties.getConfig().setTrustSettings(trustSettings); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).trustStrategy().strategy()) |
||||
.isEqualTo(Config.TrustStrategy.Strategy.TRUST_SYSTEM_CA_SIGNED_CERTIFICATES); |
||||
} |
||||
|
||||
@Test |
||||
void connectionTimeoutSettingsShouldWork() { |
||||
Neo4jProperties driverProperties = new Neo4jProperties(); |
||||
driverProperties.getConfig().setConnectionTimeout(Duration.ofSeconds(23)); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).connectionTimeoutMillis()).isEqualTo(23_000); |
||||
} |
||||
|
||||
@Test |
||||
@Disabled("The internal driver has no means of retrieving that value back again") |
||||
void maxTransactionRetryTimeSettingsShouldWork() { |
||||
DriverSettings driverSettings = new DriverSettings(); |
||||
driverSettings.setMaxTransactionRetryTime(Duration.ofSeconds(23)); |
||||
} |
||||
|
||||
@Test |
||||
void serverAddressResolverClassSettingsShouldWork() { |
||||
Neo4jProperties driverProperties = new Neo4jProperties(); |
||||
driverProperties.getConfig().setServerAddressResolverClass(TestServerAddressResolver.class); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).resolver()).isNotNull() |
||||
.isInstanceOf(TestServerAddressResolver.class); |
||||
} |
||||
|
||||
@Test |
||||
void shouldUseSpringJclLogging() { |
||||
Neo4jProperties driverProperties = new Neo4jProperties(); |
||||
assertThat(Neo4jAutoConfiguration.asDriverConfig(driverProperties).logging()).isNotNull() |
||||
.isInstanceOf(Neo4jSpringJclLogging.class); |
||||
} |
||||
|
||||
@Test |
||||
void trustAllCertificatesShouldWork() { |
||||
TrustSettings settings = new TrustSettings(); |
||||
settings.setStrategy(Strategy.TRUST_ALL_CERTIFICATES); |
||||
|
||||
assertThat(Neo4jAutoConfiguration.toInternalRepresentation(settings).strategy()) |
||||
.isEqualTo(Config.TrustStrategy.Strategy.TRUST_ALL_CERTIFICATES); |
||||
} |
||||
|
||||
@Test |
||||
void shouldEnableHostnameVerification() { |
||||
TrustSettings settings = new TrustSettings(); |
||||
settings.setStrategy(Strategy.TRUST_ALL_CERTIFICATES); |
||||
settings.setHostnameVerificationEnabled(true); |
||||
|
||||
assertThat(Neo4jAutoConfiguration.toInternalRepresentation(settings).isHostnameVerificationEnabled()).isTrue(); |
||||
} |
||||
|
||||
@Test |
||||
void trustSystemCertificatesShouldWork() { |
||||
|
||||
TrustSettings settings = new TrustSettings(); |
||||
settings.setStrategy(Strategy.TRUST_SYSTEM_CA_SIGNED_CERTIFICATES); |
||||
|
||||
assertThat(Neo4jAutoConfiguration.toInternalRepresentation(settings).strategy()) |
||||
.isEqualTo(Config.TrustStrategy.Strategy.TRUST_SYSTEM_CA_SIGNED_CERTIFICATES); |
||||
} |
||||
|
||||
@Test |
||||
void trustCustomCertificatesShouldWork() throws IOException { |
||||
File certFile = File.createTempFile("neo4j-driver", ".cert"); |
||||
|
||||
TrustSettings settings = new TrustSettings(); |
||||
settings.setStrategy(Strategy.TRUST_CUSTOM_CA_SIGNED_CERTIFICATES); |
||||
settings.setCertFile(certFile); |
||||
|
||||
Config.TrustStrategy trustStrategy = Neo4jAutoConfiguration.toInternalRepresentation(settings); |
||||
assertThat(trustStrategy.strategy()) |
||||
.isEqualTo(Config.TrustStrategy.Strategy.TRUST_CUSTOM_CA_SIGNED_CERTIFICATES); |
||||
assertThat(trustStrategy.certFile()).isEqualTo(certFile); |
||||
} |
||||
|
||||
@Test |
||||
void trustCustomCertificatesShouldFailWithoutCertificate() { |
||||
TrustSettings settings = new TrustSettings(); |
||||
settings.setStrategy(Strategy.TRUST_CUSTOM_CA_SIGNED_CERTIFICATES); |
||||
|
||||
assertThatExceptionOfType(InvalidConfigurationPropertyValueException.class) |
||||
.isThrownBy(() -> Neo4jAutoConfiguration.toInternalRepresentation(settings)).withMessage( |
||||
"Property org.neo4j.driver.config.trust-settings with value 'TRUST_CUSTOM_CA_SIGNED_CERTIFICATES' is invalid: Configured trust strategy requires a certificate file."); |
||||
} |
||||
|
||||
@Test |
||||
void shouldAssumeDefaultValuesForUrl() { |
||||
Neo4jProperties driverProperties = new Neo4jProperties(); |
||||
assertThat(driverProperties.getUri()).isEqualTo(URI.create("bolt://localhost:7687")); |
||||
} |
||||
|
||||
@ParameterizedTest |
||||
@ValueSource(strings = { "bolt", "Bolt", "neo4j", "Neo4J" }) |
||||
void shouldDetectSimpleSchemes(String aSimpleScheme) { |
||||
assertThat(Neo4jAutoConfiguration.isSimpleScheme(aSimpleScheme)).isTrue(); |
||||
} |
||||
|
||||
@ParameterizedTest |
||||
@ValueSource(strings = { "bolt+s", "Bolt+ssc", "neo4j+s", "Neo4J+ssc" }) |
||||
void shouldDetectAdvancedSchemes(String anAdvancedScheme) { |
||||
assertThat(Neo4jAutoConfiguration.isSimpleScheme(anAdvancedScheme)).isFalse(); |
||||
} |
||||
|
||||
@ParameterizedTest |
||||
@ValueSource(strings = { "bolt+routing", "bolt+x", "neo4j+wth" }) |
||||
void shouldFailEarlyOnInvalidSchemes(String invalidScheme) { |
||||
assertThatIllegalArgumentException().isThrownBy(() -> Neo4jAutoConfiguration.isSimpleScheme(invalidScheme)) |
||||
.withMessage("'%s' is not a supported scheme.", invalidScheme); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
/* |
||||
* Copyright 2012-2020 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.boot.autoconfigure.neo4j; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.Set; |
||||
|
||||
import org.neo4j.driver.net.ServerAddress; |
||||
import org.neo4j.driver.net.ServerAddressResolver; |
||||
|
||||
/** |
||||
* Resolver used only for configuration tests. |
||||
* |
||||
* @author Michael J. Simons |
||||
*/ |
||||
class TestServerAddressResolver implements ServerAddressResolver { |
||||
|
||||
@Override |
||||
public Set<ServerAddress> resolve(ServerAddress address) { |
||||
return Collections.emptySet(); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue