From 25e08d2dee6b9a781538679468cab107717d50ad Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Wed, 12 Aug 2020 14:04:19 +0200 Subject: [PATCH] Restore handling of certain spring.data.neo4j.* properties This commit switches the deprecation level of several properties in the spring.data.neo4j namespace from error and warning. The server URI and basic authentication can be used in a deprecated fashion to configure the new neo4j driver. Closes gh-22653 --- .../neo4j/Neo4jAutoConfiguration.java | 33 ++++++++-- .../autoconfigure/neo4j/Neo4jProperties.java | 2 +- ...itional-spring-configuration-metadata.json | 10 ++- .../neo4j/Neo4jAutoConfigurationTests.java | 66 ++++++++++++++++++- .../neo4j/Neo4jPropertiesTests.java | 7 -- 5 files changed, 100 insertions(+), 18 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/neo4j/Neo4jAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/neo4j/Neo4jAutoConfiguration.java index ffd358a846..473d6d0c84 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/neo4j/Neo4jAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/neo4j/Neo4jAutoConfiguration.java @@ -22,6 +22,7 @@ import java.time.Duration; import java.util.List; import java.util.Locale; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; import java.util.stream.Collectors; import org.neo4j.driver.AuthToken; @@ -42,6 +43,7 @@ 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.core.env.Environment; import org.springframework.util.StringUtils; /** @@ -56,19 +58,31 @@ import org.springframework.util.StringUtils; @EnableConfigurationProperties(Neo4jProperties.class) public class Neo4jAutoConfiguration { + private static final URI DEFAULT_SERVER_URI = URI.create("bolt://localhost:7687"); + @Bean @ConditionalOnMissingBean - public Driver neo4jDriver(Neo4jProperties properties, + public Driver neo4jDriver(Neo4jProperties properties, Environment environment, ObjectProvider configBuilderCustomizers) { - AuthToken authToken = mapAuthToken(properties.getAuthentication()); + AuthToken authToken = mapAuthToken(properties.getAuthentication(), environment); Config config = mapDriverConfig(properties, configBuilderCustomizers.orderedStream().collect(Collectors.toList())); - return GraphDatabase.driver(properties.getUri(), authToken, config); + URI serverUri = determineServerUri(properties, environment); + return GraphDatabase.driver(serverUri, authToken, config); } - AuthToken mapAuthToken(Neo4jProperties.Authentication authentication) { - String username = authentication.getUsername(); - String password = authentication.getPassword(); + URI determineServerUri(Neo4jProperties properties, Environment environment) { + return getOrFallback(properties.getUri(), () -> { + URI deprecatedProperty = environment.getProperty("spring.data.neo4j.uri", URI.class); + return (deprecatedProperty != null) ? deprecatedProperty : DEFAULT_SERVER_URI; + }); + } + + AuthToken mapAuthToken(Neo4jProperties.Authentication authentication, Environment environment) { + String username = getOrFallback(authentication.getUsername(), + () -> environment.getProperty("spring.data.neo4j.username", String.class)); + String password = getOrFallback(authentication.getPassword(), + () -> environment.getProperty("spring.data.neo4j.password", String.class)); String kerberosTicket = authentication.getKerberosTicket(); String realm = authentication.getRealm(); @@ -89,6 +103,13 @@ public class Neo4jAutoConfiguration { return AuthTokens.none(); } + private T getOrFallback(T value, Supplier fallback) { + if (value != null) { + return value; + } + return fallback.get(); + } + Config mapDriverConfig(Neo4jProperties properties, List customizers) { Config.ConfigBuilder builder = Config.builder(); configurePoolSettings(builder, properties.getPool()); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/neo4j/Neo4jProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/neo4j/Neo4jProperties.java index cb7b2638bb..5b856a52e9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/neo4j/Neo4jProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/neo4j/Neo4jProperties.java @@ -35,7 +35,7 @@ public class Neo4jProperties { /** * URI used by the driver. */ - private URI uri = URI.create("bolt://localhost:7687"); + private URI uri; /** * Timeout for borrowing connections from the pool. diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index acd3527413..9f87284552 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -681,7 +681,7 @@ "description": "Login password of the server.", "deprecation": { "replacement": "spring.neo4j.authentication.password", - "level": "error" + "level": "warning" } }, { @@ -706,7 +706,7 @@ "description": "URI used by the driver. Auto-detected by default.", "deprecation": { "replacement": "spring.neo4j.uri", - "level": "error" + "level": "warning" } }, { @@ -724,7 +724,7 @@ "description": "Login user of the server.", "deprecation": { "replacement": "spring.neo4j.authentication.password", - "level": "error" + "level": "warning" } }, { @@ -1506,6 +1506,10 @@ "name": "spring.mvc.locale-resolver", "defaultValue": "accept-header" }, + { + "name": "spring.neo4j.uri", + "defaultValue": "bolt://localhost:7687" + }, { "name": "spring.quartz.jdbc.comment-prefix", "defaultValue": [ diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/neo4j/Neo4jAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/neo4j/Neo4jAutoConfigurationTests.java index a10140a6ee..42af59258d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/neo4j/Neo4jAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/neo4j/Neo4jAutoConfigurationTests.java @@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.neo4j; import java.io.File; import java.io.IOException; +import java.net.URI; import java.time.Duration; import java.util.Arrays; @@ -37,6 +38,8 @@ import org.springframework.boot.autoconfigure.neo4j.Neo4jProperties.Security.Tru import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.core.env.Environment; +import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -114,6 +117,40 @@ class Neo4jAutoConfigurationTests { .hasFieldOrPropertyWithValue("maxRetryTimeMs", 2000L); } + @Test + void determineServerUriShouldDefaultToLocalhost() { + assertThat(determineServerUri(new Neo4jProperties(), new MockEnvironment())) + .isEqualTo(URI.create("bolt://localhost:7687")); + } + + @Test + void determineServerUriWithCustomUriShouldOverrideDefault() { + URI customUri = URI.create("bolt://localhost:4242"); + Neo4jProperties properties = new Neo4jProperties(); + properties.setUri(customUri); + assertThat(determineServerUri(properties, new MockEnvironment())).isEqualTo(customUri); + } + + @Test + @Deprecated + void determineServerUriWithDeprecatedPropertyShouldOverrideDefault() { + URI customUri = URI.create("bolt://localhost:4242"); + MockEnvironment environment = new MockEnvironment().withProperty("spring.data.neo4j.uri", customUri.toString()); + assertThat(determineServerUri(new Neo4jProperties(), environment)).isEqualTo(customUri); + } + + @Test + @Deprecated + void determineServerUriWithCustoUriShouldTakePrecedenceOverDeprecatedProperty() { + URI customUri = URI.create("bolt://localhost:4242"); + URI anotherCustomURI = URI.create("bolt://localhost:2424"); + Neo4jProperties properties = new Neo4jProperties(); + properties.setUri(customUri); + MockEnvironment environment = new MockEnvironment().withProperty("spring.data.neo4j.uri", + anotherCustomURI.toString()); + assertThat(determineServerUri(properties, environment)).isEqualTo(customUri); + } + @Test void authenticationShouldDefaultToNone() { assertThat(mapAuthToken(new Authentication())).isEqualTo(AuthTokens.none()); @@ -136,6 +173,25 @@ class Neo4jAutoConfigurationTests { assertThat(mapAuthToken(authentication)).isEqualTo(AuthTokens.basic("Farin", "Urlaub", "Test Realm")); } + @Test + @Deprecated + void authenticationWithUsernameUsingDeprecatedPropertiesShouldEnableBasicAuth() { + MockEnvironment environment = new MockEnvironment().withProperty("spring.data.neo4j.username", "user") + .withProperty("spring.data.neo4j.password", "secret"); + assertThat(mapAuthToken(new Authentication(), environment)).isEqualTo(AuthTokens.basic("user", "secret")); + } + + @Test + @Deprecated + void authenticationWithUsernameShouldTakePrecedenceOverDeprecatedPropertiesAndEnableBasicAuth() { + MockEnvironment environment = new MockEnvironment().withProperty("spring.data.neo4j.username", "user") + .withProperty("spring.data.neo4j.password", "secret"); + Authentication authentication = new Authentication(); + authentication.setUsername("Farin"); + authentication.setPassword("Urlaub"); + assertThat(mapAuthToken(authentication, environment)).isEqualTo(AuthTokens.basic("Farin", "Urlaub")); + } + @Test void authenticationWithKerberosTicketShouldEnableKerberos() { Authentication authentication = new Authentication(); @@ -262,8 +318,16 @@ class Neo4jAutoConfigurationTests { .isInstanceOf(Neo4jSpringJclLogging.class); } + private URI determineServerUri(Neo4jProperties properties, Environment environment) { + return new Neo4jAutoConfiguration().determineServerUri(properties, environment); + } + + private AuthToken mapAuthToken(Authentication authentication, Environment environment) { + return new Neo4jAutoConfiguration().mapAuthToken(authentication, environment); + } + private AuthToken mapAuthToken(Authentication authentication) { - return new Neo4jAutoConfiguration().mapAuthToken(authentication); + return mapAuthToken(authentication, new MockEnvironment()); } private Config mapDriverConfig(Neo4jProperties properties, ConfigBuilderCustomizer... customizers) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/neo4j/Neo4jPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/neo4j/Neo4jPropertiesTests.java index 79e14d5bce..07bdc12275 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/neo4j/Neo4jPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/neo4j/Neo4jPropertiesTests.java @@ -16,7 +16,6 @@ package org.springframework.boot.autoconfigure.neo4j; -import java.net.URI; import java.time.Duration; import org.junit.jupiter.api.Test; @@ -66,12 +65,6 @@ class Neo4jPropertiesTests { assertDuration(properties.getMaxTransactionRetryTime(), RetrySettings.DEFAULT.maxRetryTimeMs()); } - @Test - void shouldAssumeDefaultValuesForUrl() { - Neo4jProperties driverProperties = new Neo4jProperties(); - assertThat(driverProperties.getUri()).isEqualTo(URI.create("bolt://localhost:7687")); - } - private static void assertDuration(Duration duration, long expectedValueInMillis) { if (expectedValueInMillis == org.neo4j.driver.internal.async.pool.PoolSettings.NOT_CONFIGURED) { assertThat(duration).isNull();