Promote ConnectionFactoryBuilder to the "spring-boot" module
Closes gh-25492
This commit is contained in:
committed by
Andy Wilkinson
parent
9ba2cd3be7
commit
54e7d7f060
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2021 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,9 +16,10 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.r2dbc;
|
||||
|
||||
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBuilder.ConnectionFactoryBeanCreationException;
|
||||
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsInitializer.ConnectionFactoryBeanCreationException;
|
||||
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
|
||||
import org.springframework.boot.diagnostics.FailureAnalysis;
|
||||
import org.springframework.boot.r2dbc.EmbeddedDatabaseConnection;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -17,17 +17,12 @@
|
||||
package org.springframework.boot.autoconfigure.r2dbc;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import io.r2dbc.spi.ConnectionFactories;
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
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.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Builder for {@link ConnectionFactory}.
|
||||
@@ -36,7 +31,10 @@ import org.springframework.util.StringUtils;
|
||||
* @author Tadaya Tsuyukubo
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.3.0
|
||||
* @deprecated since 2.5.0 in favor of
|
||||
* {@link org.springframework.boot.r2dbc.ConnectionFactoryBuilder}
|
||||
*/
|
||||
@Deprecated
|
||||
public final class ConnectionFactoryBuilder {
|
||||
|
||||
private final ConnectionFactoryOptions.Builder optionsBuilder;
|
||||
@@ -59,7 +57,7 @@ public final class ConnectionFactoryBuilder {
|
||||
public static ConnectionFactoryBuilder of(R2dbcProperties properties,
|
||||
Supplier<EmbeddedDatabaseConnection> embeddedDatabaseConnection) {
|
||||
return new ConnectionFactoryBuilder(
|
||||
new ConnectionFactoryOptionsInitializer().initializeOptions(properties, embeddedDatabaseConnection));
|
||||
new ConnectionFactoryOptionsInitializer().initialize(properties, adapt(embeddedDatabaseConnection)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,127 +131,13 @@ public final class ConnectionFactoryBuilder {
|
||||
return this.optionsBuilder.build();
|
||||
}
|
||||
|
||||
static class ConnectionFactoryOptionsInitializer {
|
||||
|
||||
/**
|
||||
* Initialize a {@link io.r2dbc.spi.ConnectionFactoryOptions.Builder
|
||||
* ConnectionFactoryOptions.Builder} using the specified properties.
|
||||
* @param properties the properties 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 initializeOptions(R2dbcProperties properties,
|
||||
Supplier<EmbeddedDatabaseConnection> embeddedDatabaseConnection) {
|
||||
if (StringUtils.hasText(properties.getUrl())) {
|
||||
return initializeRegularOptions(properties);
|
||||
}
|
||||
EmbeddedDatabaseConnection embeddedConnection = embeddedDatabaseConnection.get();
|
||||
if (embeddedConnection != EmbeddedDatabaseConnection.NONE) {
|
||||
return initializeEmbeddedOptions(properties, embeddedConnection);
|
||||
}
|
||||
throw connectionFactoryBeanCreationException("Failed to determine a suitable R2DBC Connection URL",
|
||||
properties, 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 ConnectionFactoryOptions.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);
|
||||
}
|
||||
Builder builder = ConnectionFactoryOptions.parse(url).mutate();
|
||||
String username = determineEmbeddedUsername(properties);
|
||||
if (StringUtils.hasText(username)) {
|
||||
builder.option(ConnectionFactoryOptions.USER, username);
|
||||
}
|
||||
if (StringUtils.hasText(properties.getPassword())) {
|
||||
builder.option(ConnectionFactoryOptions.PASSWORD, properties.getPassword());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private String determineDatabaseName(R2dbcProperties properties) {
|
||||
if (properties.isGenerateUniqueName()) {
|
||||
return properties.determineUniqueName();
|
||||
}
|
||||
if (StringUtils.hasLength(properties.getName())) {
|
||||
return properties.getName();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
private String ifHasText(String candidate) {
|
||||
return (StringUtils.hasText(candidate)) ? candidate : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class ConnectionFactoryBeanCreationException extends BeanCreationException {
|
||||
|
||||
private final R2dbcProperties properties;
|
||||
|
||||
private final EmbeddedDatabaseConnection embeddedDatabaseConnection;
|
||||
|
||||
ConnectionFactoryBeanCreationException(String message, R2dbcProperties properties,
|
||||
EmbeddedDatabaseConnection embeddedDatabaseConnection) {
|
||||
super(message);
|
||||
this.properties = properties;
|
||||
this.embeddedDatabaseConnection = embeddedDatabaseConnection;
|
||||
}
|
||||
|
||||
EmbeddedDatabaseConnection getEmbeddedDatabaseConnection() {
|
||||
return this.embeddedDatabaseConnection;
|
||||
}
|
||||
|
||||
R2dbcProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
private static Supplier<org.springframework.boot.r2dbc.EmbeddedDatabaseConnection> adapt(
|
||||
Supplier<EmbeddedDatabaseConnection> embeddedDatabaseConnection) {
|
||||
return () -> {
|
||||
EmbeddedDatabaseConnection connection = embeddedDatabaseConnection.get();
|
||||
return (connection != null)
|
||||
? org.springframework.boot.r2dbc.EmbeddedDatabaseConnection.valueOf(connection.name()) : null;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -30,6 +30,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.boot.r2dbc.EmbeddedDatabaseConnection;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
@@ -50,7 +51,9 @@ abstract class ConnectionFactoryConfigurations {
|
||||
|
||||
protected static ConnectionFactory createConnectionFactory(R2dbcProperties properties, ClassLoader classLoader,
|
||||
List<ConnectionFactoryOptionsBuilderCustomizer> optionsCustomizers) {
|
||||
return ConnectionFactoryBuilder.of(properties, () -> EmbeddedDatabaseConnection.get(classLoader))
|
||||
return org.springframework.boot.r2dbc.ConnectionFactoryBuilder
|
||||
.withOptions(new ConnectionFactoryOptionsInitializer().initialize(properties,
|
||||
() -> EmbeddedDatabaseConnection.get(classLoader)))
|
||||
.configure((options) -> {
|
||||
for (ConnectionFactoryOptionsBuilderCustomizer optionsCustomizer : optionsCustomizers) {
|
||||
optionsCustomizer.customize(options);
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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 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;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Initialize a {@link ConnectionFactoryOptions.Builder} based on {@link R2dbcProperties}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class ConnectionFactoryOptionsInitializer {
|
||||
|
||||
/**
|
||||
* Initialize a {@link io.r2dbc.spi.ConnectionFactoryOptions.Builder
|
||||
* ConnectionFactoryOptions.Builder} using the specified properties.
|
||||
* @param properties the properties 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,
|
||||
Supplier<EmbeddedDatabaseConnection> embeddedDatabaseConnection) {
|
||||
if (StringUtils.hasText(properties.getUrl())) {
|
||||
return initializeRegularOptions(properties);
|
||||
}
|
||||
EmbeddedDatabaseConnection embeddedConnection = embeddedDatabaseConnection.get();
|
||||
if (embeddedConnection != EmbeddedDatabaseConnection.NONE) {
|
||||
return initializeEmbeddedOptions(properties, embeddedConnection);
|
||||
}
|
||||
throw connectionFactoryBeanCreationException("Failed to determine a suitable R2DBC Connection URL", properties,
|
||||
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);
|
||||
}
|
||||
Builder builder = ConnectionFactoryOptions.parse(url).mutate();
|
||||
String username = determineEmbeddedUsername(properties);
|
||||
if (StringUtils.hasText(username)) {
|
||||
builder.option(ConnectionFactoryOptions.USER, username);
|
||||
}
|
||||
if (StringUtils.hasText(properties.getPassword())) {
|
||||
builder.option(ConnectionFactoryOptions.PASSWORD, properties.getPassword());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private String determineDatabaseName(R2dbcProperties properties) {
|
||||
if (properties.isGenerateUniqueName()) {
|
||||
return properties.determineUniqueName();
|
||||
}
|
||||
if (StringUtils.hasLength(properties.getName())) {
|
||||
return properties.getName();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
private String ifHasText(String candidate) {
|
||||
return (StringUtils.hasText(candidate)) ? candidate : null;
|
||||
}
|
||||
|
||||
static class ConnectionFactoryBeanCreationException extends BeanCreationException {
|
||||
|
||||
private final R2dbcProperties properties;
|
||||
|
||||
private final EmbeddedDatabaseConnection embeddedDatabaseConnection;
|
||||
|
||||
ConnectionFactoryBeanCreationException(String message, R2dbcProperties properties,
|
||||
EmbeddedDatabaseConnection embeddedDatabaseConnection) {
|
||||
super(message);
|
||||
this.properties = properties;
|
||||
this.embeddedDatabaseConnection = embeddedDatabaseConnection;
|
||||
}
|
||||
|
||||
EmbeddedDatabaseConnection getEmbeddedDatabaseConnection() {
|
||||
return this.embeddedDatabaseConnection;
|
||||
}
|
||||
|
||||
R2dbcProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,7 +25,10 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Mark Paluch
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.3.0
|
||||
* @deprecated since 2.5.0 in favor of
|
||||
* {@link org.springframework.boot.r2dbc.EmbeddedDatabaseConnection}
|
||||
*/
|
||||
@Deprecated
|
||||
public enum EmbeddedDatabaseConnection {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -20,7 +20,7 @@ import io.r2dbc.spi.ConnectionFactoryOptions;
|
||||
import io.r2dbc.spi.Option;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBuilder.ConnectionFactoryBeanCreationException;
|
||||
import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsInitializer.ConnectionFactoryBeanCreationException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
@@ -33,6 +33,7 @@ import static org.assertj.core.api.Assertions.fail;
|
||||
* @author Tadaya Tsuyukubo
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Deprecated
|
||||
class ConnectionFactoryBuilderTests {
|
||||
|
||||
@Test
|
||||
@@ -51,7 +52,8 @@ class ConnectionFactoryBuilderTests {
|
||||
fail("Should have thrown a " + ConnectionFactoryBeanCreationException.class.getName());
|
||||
}
|
||||
catch (ConnectionFactoryBeanCreationException ex) {
|
||||
assertThat(ex.getEmbeddedDatabaseConnection()).isEqualTo(EmbeddedDatabaseConnection.NONE);
|
||||
assertThat(ex.getEmbeddedDatabaseConnection())
|
||||
.isEqualTo(org.springframework.boot.r2dbc.EmbeddedDatabaseConnection.NONE);
|
||||
assertThat(ex.getProperties()).isSameAs(properties);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -35,6 +35,7 @@ import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.r2dbc.SimpleConnectionFactoryProvider.SimpleTestConnectionFactory;
|
||||
import org.springframework.boot.r2dbc.EmbeddedDatabaseConnection;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
Reference in New Issue
Block a user