mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-15 01:07:30 +08:00
Add ConnectionDetail support to R2DBC auto-configuration
Update R2DBC auto-configuration so that `R2dbcConnectionDetails` beans may be optionally used to provide connection details. See gh-34657 Co-Authored-By: Mortitz Halbritter <mkammerer@vmware.com> Co-Authored-By: Phillip Webb <pwebb@vmware.com>
This commit is contained in:
parent
d09ac00824
commit
61e9fe8cd4
@ -237,6 +237,7 @@ dependencies {
|
||||
testImplementation("org.mockito:mockito-core")
|
||||
testImplementation("org.mockito:mockito-junit-jupiter")
|
||||
testImplementation("org.postgresql:postgresql")
|
||||
testImplementation("org.postgresql:r2dbc-postgresql")
|
||||
testImplementation("org.skyscreamer:jsonassert")
|
||||
testImplementation("org.springframework:spring-test")
|
||||
testImplementation("org.springframework:spring-core-test")
|
||||
|
@ -53,7 +53,7 @@ class ConnectionFactoryBeanCreationFailureAnalyzer
|
||||
private String getDescription(ConnectionFactoryBeanCreationException cause) {
|
||||
StringBuilder description = new StringBuilder();
|
||||
description.append("Failed to configure a ConnectionFactory: ");
|
||||
if (!StringUtils.hasText(cause.getProperties().getUrl())) {
|
||||
if (!StringUtils.hasText(cause.getUrl())) {
|
||||
description.append("'url' attribute is not specified and ");
|
||||
}
|
||||
description.append(String.format("no embedded database could be configured.%n"));
|
||||
|
@ -51,14 +51,18 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Paluch
|
||||
* @author Stephane Nicoll
|
||||
* @author Rodolpho S. Couto
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
abstract class ConnectionFactoryConfigurations {
|
||||
|
||||
protected static ConnectionFactory createConnectionFactory(R2dbcProperties properties, ClassLoader classLoader,
|
||||
protected static ConnectionFactory createConnectionFactory(R2dbcProperties properties,
|
||||
R2dbcConnectionDetails connectionDetails, ClassLoader classLoader,
|
||||
List<ConnectionFactoryOptionsBuilderCustomizer> optionsCustomizers) {
|
||||
try {
|
||||
return org.springframework.boot.r2dbc.ConnectionFactoryBuilder
|
||||
.withOptions(new ConnectionFactoryOptionsInitializer().initialize(properties,
|
||||
.withOptions(new ConnectionFactoryOptionsInitializer().initialize(properties, connectionDetails,
|
||||
() -> EmbeddedDatabaseConnection.get(classLoader)))
|
||||
.configure((options) -> {
|
||||
for (ConnectionFactoryOptionsBuilderCustomizer optionsCustomizer : optionsCustomizers) {
|
||||
@ -87,10 +91,12 @@ abstract class ConnectionFactoryConfigurations {
|
||||
static class PooledConnectionFactoryConfiguration {
|
||||
|
||||
@Bean(destroyMethod = "dispose")
|
||||
ConnectionPool connectionFactory(R2dbcProperties properties, ResourceLoader resourceLoader,
|
||||
ConnectionPool connectionFactory(R2dbcProperties properties,
|
||||
ObjectProvider<R2dbcConnectionDetails> connectionDetails, ResourceLoader resourceLoader,
|
||||
ObjectProvider<ConnectionFactoryOptionsBuilderCustomizer> customizers) {
|
||||
ConnectionFactory connectionFactory = createConnectionFactory(properties,
|
||||
resourceLoader.getClassLoader(), customizers.orderedStream().toList());
|
||||
connectionDetails.getIfAvailable(), resourceLoader.getClassLoader(),
|
||||
customizers.orderedStream().toList());
|
||||
R2dbcProperties.Pool pool = properties.getPool();
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
ConnectionPoolConfiguration.Builder builder = ConnectionPoolConfiguration.builder(connectionFactory);
|
||||
@ -116,10 +122,11 @@ abstract class ConnectionFactoryConfigurations {
|
||||
static class GenericConfiguration {
|
||||
|
||||
@Bean
|
||||
ConnectionFactory connectionFactory(R2dbcProperties properties, ResourceLoader resourceLoader,
|
||||
ConnectionFactory connectionFactory(R2dbcProperties properties,
|
||||
ObjectProvider<R2dbcConnectionDetails> connectionDetails, ResourceLoader resourceLoader,
|
||||
ObjectProvider<ConnectionFactoryOptionsBuilderCustomizer> customizers) {
|
||||
return createConnectionFactory(properties, resourceLoader.getClassLoader(),
|
||||
customizers.orderedStream().toList());
|
||||
return createConnectionFactory(properties, connectionDetails.getIfAvailable(),
|
||||
resourceLoader.getClassLoader(), customizers.orderedStream().toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,12 +16,10 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.r2dbc;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import io.r2dbc.spi.ConnectionFactoryOptions;
|
||||
import io.r2dbc.spi.ConnectionFactoryOptions.Builder;
|
||||
import io.r2dbc.spi.Option;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.boot.r2dbc.EmbeddedDatabaseConnection;
|
||||
@ -31,6 +29,9 @@ import org.springframework.util.StringUtils;
|
||||
* Initialize a {@link Builder} based on {@link R2dbcProperties}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ConnectionFactoryOptionsInitializer {
|
||||
|
||||
@ -38,45 +39,31 @@ class ConnectionFactoryOptionsInitializer {
|
||||
* Initialize a {@link Builder ConnectionFactoryOptions.Builder} using the specified
|
||||
* properties.
|
||||
* @param properties the properties to use to initialize the builder
|
||||
* @param connectionDetails the connection details to use to initialize the builder
|
||||
* @param embeddedDatabaseConnection the embedded connection to use as a fallback
|
||||
* @return an initialized builder
|
||||
* @throws ConnectionFactoryBeanCreationException if no suitable connection could be
|
||||
* determined
|
||||
*/
|
||||
ConnectionFactoryOptions.Builder initialize(R2dbcProperties properties,
|
||||
ConnectionFactoryOptions.Builder initialize(R2dbcProperties properties, R2dbcConnectionDetails connectionDetails,
|
||||
Supplier<EmbeddedDatabaseConnection> embeddedDatabaseConnection) {
|
||||
if (StringUtils.hasText(properties.getUrl())) {
|
||||
return initializeRegularOptions(properties);
|
||||
if (connectionDetails != null) {
|
||||
return connectionDetails.getConnectionFactoryOptions().mutate();
|
||||
}
|
||||
EmbeddedDatabaseConnection embeddedConnection = embeddedDatabaseConnection.get();
|
||||
if (embeddedConnection != EmbeddedDatabaseConnection.NONE) {
|
||||
return initializeEmbeddedOptions(properties, embeddedConnection);
|
||||
}
|
||||
throw connectionFactoryBeanCreationException("Failed to determine a suitable R2DBC Connection URL", properties,
|
||||
throw connectionFactoryBeanCreationException("Failed to determine a suitable R2DBC Connection URL", null,
|
||||
embeddedConnection);
|
||||
}
|
||||
|
||||
private ConnectionFactoryOptions.Builder initializeRegularOptions(R2dbcProperties properties) {
|
||||
ConnectionFactoryOptions urlOptions = ConnectionFactoryOptions.parse(properties.getUrl());
|
||||
Builder optionsBuilder = urlOptions.mutate();
|
||||
configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.USER, properties::getUsername,
|
||||
StringUtils::hasText);
|
||||
configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.PASSWORD, properties::getPassword,
|
||||
StringUtils::hasText);
|
||||
configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.DATABASE,
|
||||
() -> determineDatabaseName(properties), StringUtils::hasText);
|
||||
if (properties.getProperties() != null) {
|
||||
properties.getProperties().forEach((key, value) -> optionsBuilder.option(Option.valueOf(key), value));
|
||||
}
|
||||
return optionsBuilder;
|
||||
}
|
||||
|
||||
private Builder initializeEmbeddedOptions(R2dbcProperties properties,
|
||||
EmbeddedDatabaseConnection embeddedDatabaseConnection) {
|
||||
String url = embeddedDatabaseConnection.getUrl(determineEmbeddedDatabaseName(properties));
|
||||
if (url == null) {
|
||||
throw connectionFactoryBeanCreationException("Failed to determine a suitable R2DBC Connection URL",
|
||||
properties, embeddedDatabaseConnection);
|
||||
throw connectionFactoryBeanCreationException("Failed to determine a suitable R2DBC Connection URL", url,
|
||||
embeddedDatabaseConnection);
|
||||
}
|
||||
Builder builder = ConnectionFactoryOptions.parse(url).mutate();
|
||||
String username = determineEmbeddedUsername(properties);
|
||||
@ -89,6 +76,11 @@ class ConnectionFactoryOptionsInitializer {
|
||||
return builder;
|
||||
}
|
||||
|
||||
private String determineEmbeddedDatabaseName(R2dbcProperties properties) {
|
||||
String databaseName = determineDatabaseName(properties);
|
||||
return (databaseName != null) ? databaseName : "testdb";
|
||||
}
|
||||
|
||||
private String determineDatabaseName(R2dbcProperties properties) {
|
||||
if (properties.isGenerateUniqueName()) {
|
||||
return properties.determineUniqueName();
|
||||
@ -99,30 +91,14 @@ class ConnectionFactoryOptionsInitializer {
|
||||
return null;
|
||||
}
|
||||
|
||||
private String determineEmbeddedDatabaseName(R2dbcProperties properties) {
|
||||
String databaseName = determineDatabaseName(properties);
|
||||
return (databaseName != null) ? databaseName : "testdb";
|
||||
}
|
||||
|
||||
private String determineEmbeddedUsername(R2dbcProperties properties) {
|
||||
String username = ifHasText(properties.getUsername());
|
||||
return (username != null) ? username : "sa";
|
||||
}
|
||||
|
||||
private <T extends CharSequence> void configureIf(Builder optionsBuilder, ConnectionFactoryOptions originalOptions,
|
||||
Option<T> option, Supplier<T> valueSupplier, Predicate<T> setIf) {
|
||||
if (originalOptions.hasOption(option)) {
|
||||
return;
|
||||
}
|
||||
T value = valueSupplier.get();
|
||||
if (setIf.test(value)) {
|
||||
optionsBuilder.option(option, value);
|
||||
}
|
||||
}
|
||||
|
||||
private ConnectionFactoryBeanCreationException connectionFactoryBeanCreationException(String message,
|
||||
R2dbcProperties properties, EmbeddedDatabaseConnection embeddedDatabaseConnection) {
|
||||
return new ConnectionFactoryBeanCreationException(message, properties, embeddedDatabaseConnection);
|
||||
String r2dbcUrl, EmbeddedDatabaseConnection embeddedDatabaseConnection) {
|
||||
return new ConnectionFactoryBeanCreationException(message, r2dbcUrl, embeddedDatabaseConnection);
|
||||
}
|
||||
|
||||
private String ifHasText(String candidate) {
|
||||
@ -131,25 +107,25 @@ class ConnectionFactoryOptionsInitializer {
|
||||
|
||||
static class ConnectionFactoryBeanCreationException extends BeanCreationException {
|
||||
|
||||
private final R2dbcProperties properties;
|
||||
private final String url;
|
||||
|
||||
private final EmbeddedDatabaseConnection embeddedDatabaseConnection;
|
||||
|
||||
ConnectionFactoryBeanCreationException(String message, R2dbcProperties properties,
|
||||
ConnectionFactoryBeanCreationException(String message, String url,
|
||||
EmbeddedDatabaseConnection embeddedDatabaseConnection) {
|
||||
super(message);
|
||||
this.properties = properties;
|
||||
this.url = url;
|
||||
this.embeddedDatabaseConnection = embeddedDatabaseConnection;
|
||||
}
|
||||
|
||||
String getUrl() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
EmbeddedDatabaseConnection getEmbeddedDatabaseConnection() {
|
||||
return this.embeddedDatabaseConnection;
|
||||
}
|
||||
|
||||
R2dbcProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,16 +16,26 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.r2dbc;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
import io.r2dbc.spi.ConnectionFactoryOptions;
|
||||
import io.r2dbc.spi.ConnectionFactoryOptions.Builder;
|
||||
import io.r2dbc.spi.Option;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for R2DBC.
|
||||
@ -42,4 +52,63 @@ import org.springframework.context.annotation.Import;
|
||||
ConnectionFactoryConfigurations.GenericConfiguration.class, ConnectionFactoryDependentConfiguration.class })
|
||||
public class R2dbcAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(R2dbcConnectionDetails.class)
|
||||
@ConditionalOnProperty("spring.r2dbc.url")
|
||||
PropertiesR2dbcConnectionDetails propertiesR2dbcConnectionDetails(R2dbcProperties properties) {
|
||||
return new PropertiesR2dbcConnectionDetails(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts {@link R2dbcProperties} to {@link R2dbcConnectionDetails}.
|
||||
*/
|
||||
static class PropertiesR2dbcConnectionDetails implements R2dbcConnectionDetails {
|
||||
|
||||
private final R2dbcProperties properties;
|
||||
|
||||
PropertiesR2dbcConnectionDetails(R2dbcProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionFactoryOptions getConnectionFactoryOptions() {
|
||||
ConnectionFactoryOptions urlOptions = ConnectionFactoryOptions.parse(this.properties.getUrl());
|
||||
Builder optionsBuilder = urlOptions.mutate();
|
||||
configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.USER, this.properties::getUsername,
|
||||
StringUtils::hasText);
|
||||
configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.PASSWORD, this.properties::getPassword,
|
||||
StringUtils::hasText);
|
||||
configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.DATABASE,
|
||||
() -> determineDatabaseName(this.properties), StringUtils::hasText);
|
||||
if (this.properties.getProperties() != null) {
|
||||
this.properties.getProperties()
|
||||
.forEach((key, value) -> optionsBuilder.option(Option.valueOf(key), value));
|
||||
}
|
||||
return optionsBuilder.build();
|
||||
}
|
||||
|
||||
private <T extends CharSequence> void configureIf(Builder optionsBuilder,
|
||||
ConnectionFactoryOptions originalOptions, Option<T> option, Supplier<T> valueSupplier,
|
||||
Predicate<T> setIf) {
|
||||
if (originalOptions.hasOption(option)) {
|
||||
return;
|
||||
}
|
||||
T value = valueSupplier.get();
|
||||
if (setIf.test(value)) {
|
||||
optionsBuilder.option(option, value);
|
||||
}
|
||||
}
|
||||
|
||||
private String determineDatabaseName(R2dbcProperties properties) {
|
||||
if (properties.isGenerateUniqueName()) {
|
||||
return properties.determineUniqueName();
|
||||
}
|
||||
if (StringUtils.hasLength(properties.getName())) {
|
||||
return properties.getName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.r2dbc;
|
||||
|
||||
import io.r2dbc.spi.ConnectionFactoryOptions;
|
||||
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
|
||||
|
||||
/**
|
||||
* Details required to establish a connection to an SQL service using R2DBC.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public interface R2dbcConnectionDetails extends ConnectionDetails {
|
||||
|
||||
/**
|
||||
* Connection factory options for connecting to the database.
|
||||
* @return the connection factory options
|
||||
*/
|
||||
ConnectionFactoryOptions getConnectionFactoryOptions();
|
||||
|
||||
}
|
@ -27,6 +27,7 @@ import io.r2dbc.h2.H2ConnectionFactory;
|
||||
import io.r2dbc.pool.ConnectionPool;
|
||||
import io.r2dbc.pool.PoolMetrics;
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
import io.r2dbc.spi.ConnectionFactoryOptions;
|
||||
import io.r2dbc.spi.ConnectionFactoryProvider;
|
||||
import io.r2dbc.spi.Option;
|
||||
import io.r2dbc.spi.Wrapped;
|
||||
@ -54,6 +55,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Stephane Nicoll
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class R2dbcAutoConfigurationTests {
|
||||
|
||||
@ -68,7 +72,7 @@ class R2dbcAutoConfigurationTests {
|
||||
assertThat(context.getBean(ConnectionPool.class)).extracting(ConnectionPool::unwrap)
|
||||
.satisfies((connectionFactory) -> assertThat(connectionFactory)
|
||||
.asInstanceOf(type(OptionsCapableConnectionFactory.class))
|
||||
.extracting(Wrapped<ConnectionFactory>::unwrap)
|
||||
.extracting(Wrapped::unwrap)
|
||||
.isExactlyInstanceOf(H2ConnectionFactory.class));
|
||||
});
|
||||
}
|
||||
@ -306,6 +310,64 @@ class R2dbcAutoConfigurationTests {
|
||||
.doesNotHaveBean(DatabaseClient.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseCustomConnectionDetailsIfAvailable() {
|
||||
this.contextRunner.withPropertyValues("spring.r2dbc.pool.enabled=false")
|
||||
.withUserConfiguration(ConnectionDetailsConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConnectionFactory.class);
|
||||
OptionsCapableConnectionFactory connectionFactory = context
|
||||
.getBean(OptionsCapableConnectionFactory.class);
|
||||
ConnectionFactoryOptions options = connectionFactory.getOptions();
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.DRIVER)).isEqualTo("postgresql");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.HOST)).isEqualTo("postgres.example.com");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.PORT)).isEqualTo(12345);
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.DATABASE)).isEqualTo("database-1");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.USER)).isEqualTo("user-1");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.PASSWORD)).isEqualTo("password-1");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void configureWithUsernamePasswordAndUrlWithoutUserInfoUsesUsernameAndPassword() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.r2dbc.pool.enabled=false",
|
||||
"spring.r2dbc.url:r2dbc:postgresql://postgres.example.com:4321/db", "spring.r2dbc.username=alice",
|
||||
"spring.r2dbc.password=secret")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConnectionFactory.class);
|
||||
OptionsCapableConnectionFactory connectionFactory = context
|
||||
.getBean(OptionsCapableConnectionFactory.class);
|
||||
ConnectionFactoryOptions options = connectionFactory.getOptions();
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.DRIVER)).isEqualTo("postgresql");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.HOST)).isEqualTo("postgres.example.com");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.PORT)).isEqualTo(4321);
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.DATABASE)).isEqualTo("db");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.USER)).isEqualTo("alice");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.PASSWORD)).isEqualTo("secret");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void configureWithUsernamePasswordAndUrlWithUserInfoUsesUserInfo() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.r2dbc.pool.enabled=false",
|
||||
"spring.r2dbc.url:r2dbc:postgresql://bob:password@postgres.example.com:9876/db",
|
||||
"spring.r2dbc.username=alice", "spring.r2dbc.password=secret")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConnectionFactory.class);
|
||||
OptionsCapableConnectionFactory connectionFactory = context
|
||||
.getBean(OptionsCapableConnectionFactory.class);
|
||||
ConnectionFactoryOptions options = connectionFactory.getOptions();
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.DRIVER)).isEqualTo("postgresql");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.HOST)).isEqualTo("postgres.example.com");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.PORT)).isEqualTo(9876);
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.DATABASE)).isEqualTo("db");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.USER)).isEqualTo("bob");
|
||||
assertThat(options.getValue(ConnectionFactoryOptions.PASSWORD)).isEqualTo("password");
|
||||
});
|
||||
}
|
||||
|
||||
private <T> InstanceOfAssertFactory<T, ObjectAssert<T>> type(Class<T> type) {
|
||||
return InstanceOfAssertFactories.type(type);
|
||||
}
|
||||
@ -342,4 +404,22 @@ class R2dbcAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class ConnectionDetailsConfiguration {
|
||||
|
||||
@Bean
|
||||
R2dbcConnectionDetails r2dbcConnectionDetails() {
|
||||
return new R2dbcConnectionDetails() {
|
||||
|
||||
@Override
|
||||
public ConnectionFactoryOptions getConnectionFactoryOptions() {
|
||||
return ConnectionFactoryOptions
|
||||
.parse("r2dbc:postgresql://user-1:password-1@postgres.example.com:12345/database-1");
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user