Preserve user-provided values in MongoClientSettings
Prior to this commit, values from MongoProperties would always overwrite matching fields in MongoClientSettings. This commit preserves all values in MongoClientSettings if the client app provides the MongoClientSettings bean, and only overwrites from MongoProperties if no MongoClientSettings bean is provided. Fixes gh-22321
This commit is contained in:
parent
9c6f0d8f7e
commit
b7fdf8fe87
|
|
@ -49,12 +49,27 @@ public class MongoAutoConfiguration {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MongoClient.class)
|
||||
public MongoClient mongo(MongoProperties properties, Environment environment,
|
||||
ObjectProvider<MongoClientSettingsBuilderCustomizer> builderCustomizers,
|
||||
ObjectProvider<MongoClientSettings> settings) {
|
||||
return new MongoClientFactory(properties, environment,
|
||||
builderCustomizers.orderedStream().collect(Collectors.toList()))
|
||||
.createMongoClient(settings.getIfAvailable());
|
||||
public MongoClient mongo(ObjectProvider<MongoClientSettingsBuilderCustomizer> builderCustomizers,
|
||||
MongoClientSettings settings) {
|
||||
return new MongoClientFactory(builderCustomizers.orderedStream().collect(Collectors.toList()))
|
||||
.createMongoClient(settings);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingBean(MongoClientSettings.class)
|
||||
static class MongoClientSettingsConfiguration {
|
||||
|
||||
@Bean
|
||||
MongoClientSettings mongoClientSettings() {
|
||||
return MongoClientSettings.builder().build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
MongoPropertiesClientSettingsBuilderCustomizer mongoPropertiesCustomizer(MongoProperties properties,
|
||||
Environment environment) {
|
||||
return new MongoPropertiesClientSettingsBuilderCustomizer(properties, environment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,12 +43,11 @@ public class MongoClientFactory extends MongoClientFactorySupport<MongoClient> {
|
|||
* Construct a factory for creating a blocking {@link MongoClient}.
|
||||
* @param properties configuration properties
|
||||
* @param environment a Spring {@link Environment} containing configuration properties
|
||||
* @deprecated since 2.3.0 in favor of
|
||||
* {@link #MongoClientFactory(MongoProperties, Environment, List)}
|
||||
* @deprecated since 2.3.0 in favor of {@link #MongoClientFactory(List)}
|
||||
*/
|
||||
@Deprecated
|
||||
public MongoClientFactory(MongoProperties properties, Environment environment) {
|
||||
this(properties, environment, null);
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -56,10 +55,20 @@ public class MongoClientFactory extends MongoClientFactorySupport<MongoClient> {
|
|||
* @param properties configuration properties
|
||||
* @param environment a Spring {@link Environment} containing configuration properties
|
||||
* @param builderCustomizers a list of configuration settings customizers
|
||||
* @deprecated since 2.4.0 in favor of {@link #MongoClientFactory(List)}
|
||||
*/
|
||||
@Deprecated
|
||||
public MongoClientFactory(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> builderCustomizers) {
|
||||
super(properties, environment, builderCustomizers, MongoClients::create);
|
||||
this(builderCustomizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a factory for creating a blocking {@link MongoClient}.
|
||||
* @param builderCustomizers a list of configuration settings customizers
|
||||
*/
|
||||
public MongoClientFactory(List<MongoClientSettingsBuilderCustomizer> builderCustomizers) {
|
||||
super(builderCustomizers, MongoClients::create);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,15 +20,11 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.MongoClientSettings.Builder;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.MongoDriverInformation;
|
||||
import com.mongodb.ServerAddress;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class for setup that is common to MongoDB client factories.
|
||||
|
|
@ -40,120 +36,35 @@ import org.springframework.util.Assert;
|
|||
*/
|
||||
public abstract class MongoClientFactorySupport<T> {
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private final List<MongoClientSettingsBuilderCustomizer> builderCustomizers;
|
||||
|
||||
private final BiFunction<MongoClientSettings, MongoDriverInformation, T> clientCreator;
|
||||
|
||||
@Deprecated
|
||||
protected MongoClientFactorySupport(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> builderCustomizers,
|
||||
BiFunction<MongoClientSettings, MongoDriverInformation, T> clientCreator) {
|
||||
this.properties = properties;
|
||||
this.environment = environment;
|
||||
this(builderCustomizers, clientCreator);
|
||||
}
|
||||
|
||||
protected MongoClientFactorySupport(List<MongoClientSettingsBuilderCustomizer> builderCustomizers,
|
||||
BiFunction<MongoClientSettings, MongoDriverInformation, T> clientCreator) {
|
||||
this.builderCustomizers = (builderCustomizers != null) ? builderCustomizers : Collections.emptyList();
|
||||
this.clientCreator = clientCreator;
|
||||
}
|
||||
|
||||
public T createMongoClient(MongoClientSettings settings) {
|
||||
MongoClientSettings targetSettings = computeClientSettings(settings);
|
||||
return this.clientCreator.apply(targetSettings, driverInformation());
|
||||
Builder targetSettings = MongoClientSettings.builder(settings);
|
||||
customize(targetSettings);
|
||||
return this.clientCreator.apply(targetSettings.build(), driverInformation());
|
||||
}
|
||||
|
||||
private MongoClientSettings computeClientSettings(MongoClientSettings settings) {
|
||||
Builder settingsBuilder = (settings != null) ? MongoClientSettings.builder(settings)
|
||||
: MongoClientSettings.builder();
|
||||
validateConfiguration();
|
||||
applyUuidRepresentation(settingsBuilder);
|
||||
applyHostAndPort(settingsBuilder);
|
||||
applyCredentials(settingsBuilder);
|
||||
applyReplicaSet(settingsBuilder);
|
||||
customize(settingsBuilder);
|
||||
return settingsBuilder.build();
|
||||
}
|
||||
|
||||
private void validateConfiguration() {
|
||||
if (hasCustomAddress() || hasCustomCredentials() || hasReplicaSet()) {
|
||||
Assert.state(this.properties.getUri() == null,
|
||||
"Invalid mongo configuration, either uri or host/port/credentials/replicaSet must be specified");
|
||||
}
|
||||
}
|
||||
|
||||
private void applyUuidRepresentation(Builder settingsBuilder) {
|
||||
settingsBuilder.uuidRepresentation(this.properties.getUuidRepresentation());
|
||||
}
|
||||
|
||||
private void applyHostAndPort(MongoClientSettings.Builder settings) {
|
||||
if (isEmbedded()) {
|
||||
settings.applyConnectionString(new ConnectionString("mongodb://localhost:" + getEmbeddedPort()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasCustomAddress()) {
|
||||
String host = getOrDefault(this.properties.getHost(), "localhost");
|
||||
int port = getOrDefault(this.properties.getPort(), MongoProperties.DEFAULT_PORT);
|
||||
ServerAddress serverAddress = new ServerAddress(host, port);
|
||||
settings.applyToClusterSettings((cluster) -> cluster.hosts(Collections.singletonList(serverAddress)));
|
||||
return;
|
||||
}
|
||||
|
||||
settings.applyConnectionString(new ConnectionString(this.properties.determineUri()));
|
||||
}
|
||||
|
||||
private void applyCredentials(Builder builder) {
|
||||
if (hasCustomCredentials()) {
|
||||
String database = (this.properties.getAuthenticationDatabase() != null)
|
||||
? this.properties.getAuthenticationDatabase() : this.properties.getMongoClientDatabase();
|
||||
builder.credential((MongoCredential.createCredential(this.properties.getUsername(), database,
|
||||
this.properties.getPassword())));
|
||||
}
|
||||
}
|
||||
|
||||
private void applyReplicaSet(Builder builder) {
|
||||
if (hasReplicaSet()) {
|
||||
builder.applyToClusterSettings(
|
||||
(cluster) -> cluster.requiredReplicaSetName(this.properties.getReplicaSetName()));
|
||||
}
|
||||
}
|
||||
|
||||
private void customize(MongoClientSettings.Builder builder) {
|
||||
private void customize(Builder builder) {
|
||||
for (MongoClientSettingsBuilderCustomizer customizer : this.builderCustomizers) {
|
||||
customizer.customize(builder);
|
||||
}
|
||||
}
|
||||
|
||||
private <V> V getOrDefault(V value, V defaultValue) {
|
||||
return (value != null) ? value : defaultValue;
|
||||
}
|
||||
|
||||
private Integer getEmbeddedPort() {
|
||||
if (this.environment != null) {
|
||||
String localPort = this.environment.getProperty("local.mongo.port");
|
||||
if (localPort != null) {
|
||||
return Integer.valueOf(localPort);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isEmbedded() {
|
||||
return getEmbeddedPort() != null;
|
||||
}
|
||||
|
||||
private boolean hasCustomCredentials() {
|
||||
return this.properties.getUsername() != null && this.properties.getPassword() != null;
|
||||
}
|
||||
|
||||
private boolean hasReplicaSet() {
|
||||
return this.properties.getReplicaSetName() != null;
|
||||
}
|
||||
|
||||
private boolean hasCustomAddress() {
|
||||
return this.properties.getHost() != null || this.properties.getPort() != null;
|
||||
}
|
||||
|
||||
private MongoDriverInformation driverInformation() {
|
||||
return MongoDriverInformation.builder(MongoDriverInformation.builder().build()).driverName("spring-boot")
|
||||
.build();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* 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.mongo;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link MongoClientSettingsBuilderCustomizer} that applies properties from a
|
||||
* {@link MongoProperties} to a {@link MongoClientSettings}.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public class MongoPropertiesClientSettingsBuilderCustomizer implements MongoClientSettingsBuilderCustomizer, Ordered {
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private int order = 0;
|
||||
|
||||
public MongoPropertiesClientSettingsBuilderCustomizer(MongoProperties properties, Environment environment) {
|
||||
this.properties = properties;
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(MongoClientSettings.Builder settingsBuilder) {
|
||||
validateConfiguration();
|
||||
applyUuidRepresentation(settingsBuilder);
|
||||
applyHostAndPort(settingsBuilder);
|
||||
applyCredentials(settingsBuilder);
|
||||
applyReplicaSet(settingsBuilder);
|
||||
}
|
||||
|
||||
private void validateConfiguration() {
|
||||
if (hasCustomAddress() || hasCustomCredentials() || hasReplicaSet()) {
|
||||
Assert.state(this.properties.getUri() == null,
|
||||
"Invalid mongo configuration, either uri or host/port/credentials/replicaSet must be specified");
|
||||
}
|
||||
}
|
||||
|
||||
private void applyUuidRepresentation(MongoClientSettings.Builder settingsBuilder) {
|
||||
settingsBuilder.uuidRepresentation(this.properties.getUuidRepresentation());
|
||||
}
|
||||
|
||||
private void applyHostAndPort(MongoClientSettings.Builder settings) {
|
||||
if (getEmbeddedPort() != null) {
|
||||
settings.applyConnectionString(new ConnectionString("mongodb://localhost:" + getEmbeddedPort()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasCustomAddress()) {
|
||||
String host = getOrDefault(this.properties.getHost(), "localhost");
|
||||
int port = getOrDefault(this.properties.getPort(), MongoProperties.DEFAULT_PORT);
|
||||
ServerAddress serverAddress = new ServerAddress(host, port);
|
||||
settings.applyToClusterSettings((cluster) -> cluster.hosts(Collections.singletonList(serverAddress)));
|
||||
return;
|
||||
}
|
||||
|
||||
settings.applyConnectionString(new ConnectionString(this.properties.determineUri()));
|
||||
}
|
||||
|
||||
private void applyCredentials(MongoClientSettings.Builder builder) {
|
||||
if (hasCustomCredentials()) {
|
||||
String database = (this.properties.getAuthenticationDatabase() != null)
|
||||
? this.properties.getAuthenticationDatabase() : this.properties.getMongoClientDatabase();
|
||||
builder.credential((MongoCredential.createCredential(this.properties.getUsername(), database,
|
||||
this.properties.getPassword())));
|
||||
}
|
||||
}
|
||||
|
||||
private void applyReplicaSet(MongoClientSettings.Builder builder) {
|
||||
if (hasReplicaSet()) {
|
||||
builder.applyToClusterSettings(
|
||||
(cluster) -> cluster.requiredReplicaSetName(this.properties.getReplicaSetName()));
|
||||
}
|
||||
}
|
||||
|
||||
private <V> V getOrDefault(V value, V defaultValue) {
|
||||
return (value != null) ? value : defaultValue;
|
||||
}
|
||||
|
||||
private Integer getEmbeddedPort() {
|
||||
if (this.environment != null) {
|
||||
String localPort = this.environment.getProperty("local.mongo.port");
|
||||
if (localPort != null) {
|
||||
return Integer.valueOf(localPort);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean hasCustomCredentials() {
|
||||
return this.properties.getUsername() != null && this.properties.getPassword() != null;
|
||||
}
|
||||
|
||||
private boolean hasCustomAddress() {
|
||||
return this.properties.getHost() != null || this.properties.getPort() != null;
|
||||
}
|
||||
|
||||
private boolean hasReplicaSet() {
|
||||
return this.properties.getReplicaSetName() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the order value of this object.
|
||||
* @param order the new order value
|
||||
* @see #getOrder()
|
||||
*/
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* 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.
|
||||
|
|
@ -44,6 +44,7 @@ import org.springframework.core.env.Environment;
|
|||
*
|
||||
* @author Mark Paluch
|
||||
* @author Stephane Nicoll
|
||||
* @author Scott Frederick
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
|
@ -53,12 +54,28 @@ public class MongoReactiveAutoConfiguration {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MongoClient reactiveStreamsMongoClient(MongoProperties properties, Environment environment,
|
||||
ObjectProvider<MongoClientSettingsBuilderCustomizer> builderCustomizers,
|
||||
ObjectProvider<MongoClientSettings> settings) {
|
||||
ReactiveMongoClientFactory factory = new ReactiveMongoClientFactory(properties, environment,
|
||||
public MongoClient reactiveStreamsMongoClient(
|
||||
ObjectProvider<MongoClientSettingsBuilderCustomizer> builderCustomizers, MongoClientSettings settings) {
|
||||
ReactiveMongoClientFactory factory = new ReactiveMongoClientFactory(
|
||||
builderCustomizers.orderedStream().collect(Collectors.toList()));
|
||||
return factory.createMongoClient(settings.getIfAvailable());
|
||||
return factory.createMongoClient(settings);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingBean(MongoClientSettings.class)
|
||||
static class MongoClientSettingsConfiguration {
|
||||
|
||||
@Bean
|
||||
MongoClientSettings mongoClientSettings() {
|
||||
return MongoClientSettings.builder().build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
MongoPropertiesClientSettingsBuilderCustomizer mongoPropertiesCustomizer(MongoProperties properties,
|
||||
Environment environment) {
|
||||
return new MongoPropertiesClientSettingsBuilderCustomizer(properties, environment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
|
|
|||
|
|
@ -33,9 +33,25 @@ import org.springframework.core.env.Environment;
|
|||
*/
|
||||
public class ReactiveMongoClientFactory extends MongoClientFactorySupport<MongoClient> {
|
||||
|
||||
/**
|
||||
* Construct a factory for creating a {@link MongoClient}.
|
||||
* @param properties configuration properties
|
||||
* @param environment a Spring {@link Environment} containing configuration properties
|
||||
* @param builderCustomizers a list of configuration settings customizers
|
||||
* @deprecated since 2.4.0 in favor of {@link #ReactiveMongoClientFactory(List)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ReactiveMongoClientFactory(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> builderCustomizers) {
|
||||
super(properties, environment, builderCustomizers, MongoClients::create);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a factory for creating a {@link MongoClient}.
|
||||
* @param builderCustomizers a list of configuration settings customizers
|
||||
*/
|
||||
public ReactiveMongoClientFactory(List<MongoClientSettingsBuilderCustomizer> builderCustomizers) {
|
||||
super(builderCustomizers, MongoClients::create);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,20 +21,14 @@ import java.util.List;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
import org.bson.UuidRepresentation;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
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.assertThatIllegalStateException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
|
@ -52,10 +46,6 @@ import static org.mockito.Mockito.verify;
|
|||
*/
|
||||
abstract class MongoClientFactorySupportTests<T> {
|
||||
|
||||
private final MongoProperties properties = new MongoProperties();
|
||||
|
||||
private final MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
@Test
|
||||
void canBindCharArrayPassword() {
|
||||
// gh-1572
|
||||
|
|
@ -103,124 +93,6 @@ abstract class MongoClientFactorySupportTests<T> {
|
|||
assertThat(wrapped.getSslSettings().isEnabled()).isEqualTo(settings.getSslSettings().isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void portCanBeCustomized() {
|
||||
this.properties.setPort(12345);
|
||||
T client = createMongoClient();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 12345);
|
||||
}
|
||||
|
||||
@Test
|
||||
void hostCanBeCustomized() {
|
||||
this.properties.setHost("mongo.example.com");
|
||||
T client = createMongoClient();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "mongo.example.com", 27017);
|
||||
}
|
||||
|
||||
@Test
|
||||
void credentialsCanBeCustomized() {
|
||||
this.properties.setUsername("user");
|
||||
this.properties.setPassword("secret".toCharArray());
|
||||
T client = createMongoClient();
|
||||
assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void replicaSetCanBeCustomized() {
|
||||
this.properties.setReplicaSetName("test");
|
||||
T client = createMongoClient();
|
||||
assertThat(getClientSettings(client).getClusterSettings().getRequiredReplicaSetName()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void databaseCanBeCustomized() {
|
||||
this.properties.setDatabase("foo");
|
||||
this.properties.setUsername("user");
|
||||
this.properties.setPassword("secret".toCharArray());
|
||||
T client = createMongoClient();
|
||||
assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uuidRepresentationDefaultToJavaLegacy() {
|
||||
T client = createMongoClient();
|
||||
assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.JAVA_LEGACY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uuidRepresentationCanBeCustomized() {
|
||||
this.properties.setUuidRepresentation(UuidRepresentation.STANDARD);
|
||||
T client = createMongoClient();
|
||||
assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.STANDARD);
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticationDatabaseCanBeCustomized() {
|
||||
this.properties.setAuthenticationDatabase("foo");
|
||||
this.properties.setUsername("user");
|
||||
this.properties.setPassword("secret".toCharArray());
|
||||
T client = createMongoClient();
|
||||
assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCanBeCustomized() {
|
||||
this.properties.setUri("mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test");
|
||||
T client = createMongoClient();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(2);
|
||||
assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
|
||||
assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456);
|
||||
assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriIsIgnoredInEmbeddedMode() {
|
||||
this.properties.setUri("mongodb://mongo.example.com:1234/mydb");
|
||||
this.environment.setProperty("local.mongo.port", "4000");
|
||||
T client = createMongoClient();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 4000);
|
||||
}
|
||||
|
||||
@Test
|
||||
void retryWritesIsPropagatedFromUri() {
|
||||
this.properties.setUri("mongodb://localhost/test?retryWrites=true");
|
||||
T client = createMongoClient();
|
||||
assertThat(getClientSettings(client).getRetryWrites()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCannotBeSetWithCredentials() {
|
||||
this.properties.setUri("mongodb://127.0.0.1:1234/mydb");
|
||||
this.properties.setUsername("user");
|
||||
this.properties.setPassword("secret".toCharArray());
|
||||
assertThatIllegalStateException().isThrownBy(this::createMongoClient).withMessageContaining(
|
||||
"Invalid mongo configuration, either uri or host/port/credentials/replicaSet must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCannotBeSetWithReplicaSetName() {
|
||||
this.properties.setUri("mongodb://127.0.0.1:1234/mydb");
|
||||
this.properties.setReplicaSetName("test");
|
||||
assertThatIllegalStateException().isThrownBy(this::createMongoClient).withMessageContaining(
|
||||
"Invalid mongo configuration, either uri or host/port/credentials/replicaSet must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCannotBeSetWithHostPort() {
|
||||
this.properties.setUri("mongodb://127.0.0.1:1234/mydb");
|
||||
this.properties.setHost("localhost");
|
||||
this.properties.setPort(4567);
|
||||
assertThatIllegalStateException().isThrownBy(this::createMongoClient).withMessageContaining(
|
||||
"Invalid mongo configuration, either uri or host/port/credentials/replicaSet must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
void customizerIsInvoked() {
|
||||
MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class);
|
||||
|
|
@ -228,49 +100,6 @@ abstract class MongoClientFactorySupportTests<T> {
|
|||
verify(customizer).customize(any(MongoClientSettings.Builder.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customizerIsInvokedWhenHostIsSet() {
|
||||
this.properties.setHost("localhost");
|
||||
MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class);
|
||||
createMongoClient(customizer);
|
||||
verify(customizer).customize(any(MongoClientSettings.Builder.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customizerIsInvokedForEmbeddedMongo() {
|
||||
this.environment.setProperty("local.mongo.port", "27017");
|
||||
MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class);
|
||||
createMongoClient(customizer);
|
||||
verify(customizer).customize(any(MongoClientSettings.Builder.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void onlyHostAndPortSetShouldUseThat() {
|
||||
this.properties.setHost("localhost");
|
||||
this.properties.setPort(27017);
|
||||
T client = createMongoClient();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 27017);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onlyUriSetShouldUseThat() {
|
||||
this.properties.setUri("mongodb://mongo1.example.com:12345");
|
||||
T client = createMongoClient();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
|
||||
}
|
||||
|
||||
@Test
|
||||
void noCustomAddressAndNoUriUsesDefaultUri() {
|
||||
T client = createMongoClient();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 27017);
|
||||
}
|
||||
|
||||
@Test
|
||||
void canBindAutoIndexCreation() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
|
@ -281,40 +110,24 @@ abstract class MongoClientFactorySupportTests<T> {
|
|||
assertThat(properties.isAutoIndexCreation()).isTrue();
|
||||
}
|
||||
|
||||
private List<ServerAddress> getAllAddresses(T client) {
|
||||
return getClientSettings(client).getClusterSettings().getHosts();
|
||||
}
|
||||
|
||||
protected T createMongoClient() {
|
||||
return createMongoClient(this.properties, this.environment, null, null);
|
||||
return createMongoClient(null, MongoClientSettings.builder().build());
|
||||
}
|
||||
|
||||
protected T createMongoClient(MongoClientSettings settings) {
|
||||
return createMongoClient(this.properties, this.environment, null, settings);
|
||||
return createMongoClient(null, settings);
|
||||
}
|
||||
|
||||
protected void createMongoClient(MongoClientSettingsBuilderCustomizer... customizers) {
|
||||
createMongoClient(this.properties, this.environment, (customizers != null) ? Arrays.asList(customizers) : null,
|
||||
null);
|
||||
createMongoClient((customizers != null) ? Arrays.asList(customizers) : null,
|
||||
MongoClientSettings.builder().build());
|
||||
}
|
||||
|
||||
protected abstract T createMongoClient(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> customizers, MongoClientSettings settings);
|
||||
protected abstract T createMongoClient(List<MongoClientSettingsBuilderCustomizer> customizers,
|
||||
MongoClientSettings settings);
|
||||
|
||||
protected abstract MongoClientSettings getClientSettings(T client);
|
||||
|
||||
protected void assertServerAddress(ServerAddress serverAddress, String expectedHost, int expectedPort) {
|
||||
assertThat(serverAddress.getHost()).isEqualTo(expectedHost);
|
||||
assertThat(serverAddress.getPort()).isEqualTo(expectedPort);
|
||||
}
|
||||
|
||||
protected void assertMongoCredential(MongoCredential credentials, String expectedUsername, String expectedPassword,
|
||||
String expectedSource) {
|
||||
assertThat(credentials.getUserName()).isEqualTo(expectedUsername);
|
||||
assertThat(credentials.getPassword()).isEqualTo(expectedPassword.toCharArray());
|
||||
assertThat(credentials.getSource()).isEqualTo(expectedSource);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(MongoProperties.class)
|
||||
static class Config {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import java.util.List;
|
|||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.client.MongoClient;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
/**
|
||||
|
|
@ -36,9 +35,9 @@ import org.springframework.test.util.ReflectionTestUtils;
|
|||
class MongoClientFactoryTests extends MongoClientFactorySupportTests<MongoClient> {
|
||||
|
||||
@Override
|
||||
protected MongoClient createMongoClient(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> customizers, MongoClientSettings settings) {
|
||||
return new MongoClientFactory(properties, environment, customizers).createMongoClient(settings);
|
||||
protected MongoClient createMongoClient(List<MongoClientSettingsBuilderCustomizer> customizers,
|
||||
MongoClientSettings settings) {
|
||||
return new MongoClientFactory(customizers).createMongoClient(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* 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.mongo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
import org.bson.UuidRepresentation;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
/**
|
||||
* Tests for {@link MongoPropertiesClientSettingsBuilderCustomizer}.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class MongoPropertiesClientSettingsBuilderCustomizerTest {
|
||||
|
||||
private final MongoProperties properties = new MongoProperties();
|
||||
|
||||
private final MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
@Test
|
||||
void portCanBeCustomized() {
|
||||
this.properties.setPort(12345);
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(settings);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 12345);
|
||||
}
|
||||
|
||||
@Test
|
||||
void hostCanBeCustomized() {
|
||||
this.properties.setHost("mongo.example.com");
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(settings);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "mongo.example.com", 27017);
|
||||
}
|
||||
|
||||
@Test
|
||||
void credentialsCanBeCustomized() {
|
||||
this.properties.setUsername("user");
|
||||
this.properties.setPassword("secret".toCharArray());
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
assertMongoCredential(settings.getCredential(), "user", "secret", "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void replicaSetCanBeCustomized() {
|
||||
this.properties.setReplicaSetName("test");
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
assertThat(settings.getClusterSettings().getRequiredReplicaSetName()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void databaseCanBeCustomized() {
|
||||
this.properties.setDatabase("foo");
|
||||
this.properties.setUsername("user");
|
||||
this.properties.setPassword("secret".toCharArray());
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
assertMongoCredential(settings.getCredential(), "user", "secret", "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uuidRepresentationDefaultToJavaLegacy() {
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
assertThat(settings.getUuidRepresentation()).isEqualTo(UuidRepresentation.JAVA_LEGACY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uuidRepresentationCanBeCustomized() {
|
||||
this.properties.setUuidRepresentation(UuidRepresentation.STANDARD);
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
assertThat(settings.getUuidRepresentation()).isEqualTo(UuidRepresentation.STANDARD);
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticationDatabaseCanBeCustomized() {
|
||||
this.properties.setAuthenticationDatabase("foo");
|
||||
this.properties.setUsername("user");
|
||||
this.properties.setPassword("secret".toCharArray());
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
assertMongoCredential(settings.getCredential(), "user", "secret", "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void onlyHostAndPortSetShouldUseThat() {
|
||||
this.properties.setHost("localhost");
|
||||
this.properties.setPort(27017);
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(settings);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 27017);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onlyUriSetShouldUseThat() {
|
||||
this.properties.setUri("mongodb://mongo1.example.com:12345");
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(settings);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
|
||||
}
|
||||
|
||||
@Test
|
||||
void noCustomAddressAndNoUriUsesDefaultUri() {
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(settings);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 27017);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCanBeCustomized() {
|
||||
this.properties.setUri("mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test");
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(settings);
|
||||
assertThat(allAddresses).hasSize(2);
|
||||
assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
|
||||
assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456);
|
||||
assertMongoCredential(settings.getCredential(), "user", "secret", "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriIsIgnoredInEmbeddedMode() {
|
||||
this.properties.setUri("mongodb://mongo.example.com:1234/mydb");
|
||||
this.environment.setProperty("local.mongo.port", "4000");
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
List<ServerAddress> allAddresses = getAllAddresses(settings);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 4000);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCannotBeSetWithCredentials() {
|
||||
this.properties.setUri("mongodb://127.0.0.1:1234/mydb");
|
||||
this.properties.setUsername("user");
|
||||
this.properties.setPassword("secret".toCharArray());
|
||||
assertThatIllegalStateException().isThrownBy(this::customizeSettings).withMessageContaining(
|
||||
"Invalid mongo configuration, either uri or host/port/credentials/replicaSet must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCannotBeSetWithReplicaSetName() {
|
||||
this.properties.setUri("mongodb://127.0.0.1:1234/mydb");
|
||||
this.properties.setReplicaSetName("test");
|
||||
assertThatIllegalStateException().isThrownBy(this::customizeSettings).withMessageContaining(
|
||||
"Invalid mongo configuration, either uri or host/port/credentials/replicaSet must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCannotBeSetWithHostPort() {
|
||||
this.properties.setUri("mongodb://127.0.0.1:1234/mydb");
|
||||
this.properties.setHost("localhost");
|
||||
this.properties.setPort(4567);
|
||||
assertThatIllegalStateException().isThrownBy(this::customizeSettings).withMessageContaining(
|
||||
"Invalid mongo configuration, either uri or host/port/credentials/replicaSet must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
void retryWritesIsPropagatedFromUri() {
|
||||
this.properties.setUri("mongodb://localhost/test?retryWrites=false");
|
||||
MongoClientSettings settings = customizeSettings();
|
||||
assertThat(settings.getRetryWrites()).isFalse();
|
||||
}
|
||||
|
||||
private MongoClientSettings customizeSettings() {
|
||||
MongoClientSettings.Builder settings = MongoClientSettings.builder();
|
||||
new MongoPropertiesClientSettingsBuilderCustomizer(this.properties, this.environment).customize(settings);
|
||||
return settings.build();
|
||||
}
|
||||
|
||||
private List<ServerAddress> getAllAddresses(MongoClientSettings settings) {
|
||||
return settings.getClusterSettings().getHosts();
|
||||
}
|
||||
|
||||
protected void assertServerAddress(ServerAddress serverAddress, String expectedHost, int expectedPort) {
|
||||
assertThat(serverAddress.getHost()).isEqualTo(expectedHost);
|
||||
assertThat(serverAddress.getPort()).isEqualTo(expectedPort);
|
||||
}
|
||||
|
||||
protected void assertMongoCredential(MongoCredential credentials, String expectedUsername, String expectedPassword,
|
||||
String expectedSource) {
|
||||
assertThat(credentials.getUserName()).isEqualTo(expectedUsername);
|
||||
assertThat(credentials.getPassword()).isEqualTo(expectedPassword.toCharArray());
|
||||
assertThat(credentials.getSource()).isEqualTo(expectedSource);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -22,7 +22,6 @@ import com.mongodb.MongoClientSettings;
|
|||
import com.mongodb.internal.async.client.AsyncMongoClient;
|
||||
import com.mongodb.reactivestreams.client.MongoClient;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
/**
|
||||
|
|
@ -35,9 +34,9 @@ import org.springframework.test.util.ReflectionTestUtils;
|
|||
class ReactiveMongoClientFactoryTests extends MongoClientFactorySupportTests<MongoClient> {
|
||||
|
||||
@Override
|
||||
protected MongoClient createMongoClient(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> customizers, MongoClientSettings settings) {
|
||||
return new ReactiveMongoClientFactory(properties, environment, customizers).createMongoClient(settings);
|
||||
protected MongoClient createMongoClient(List<MongoClientSettingsBuilderCustomizer> customizers,
|
||||
MongoClientSettings settings) {
|
||||
return new ReactiveMongoClientFactory(customizers).createMongoClient(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -4365,6 +4365,14 @@ The following example shows how to connect to a MongoDB database:
|
|||
}
|
||||
----
|
||||
|
||||
If you have defined your own `MongoClient`, it will be used to auto-configure a suitable `MongoDatabaseFactory`.
|
||||
|
||||
The auto-configured `MongoClient` is created using a `MongoClientSettings` bean.
|
||||
If you have defined your own `MongoClientSettings`, it will be used without modification and the `spring.data.mongodb` properties will be ignored.
|
||||
Otherwise a `MongoClientSettings` will be auto-configured and will have the `spring.data.mongodb` properties applied to it.
|
||||
In either case, you can declare one or more `MongoClientSettingsBuilderCustomizer` beans to fine-tune the `MongoClientSettings` configuration.
|
||||
Each will be called in order with the `MongoClientSettings.Builder` that is used to build the `MongoClientSettings`.
|
||||
|
||||
You can set the configprop:spring.data.mongodb.uri[] property to change the URL and configure additional settings such as the _replica set_, as shown in the following example:
|
||||
|
||||
[source,properties,indent=0,configprops]
|
||||
|
|
@ -4384,12 +4392,6 @@ For example, you might declare the following settings in your `application.prope
|
|||
spring.data.mongodb.password=secret
|
||||
----
|
||||
|
||||
If you have defined your own `MongoClient`, it will be used to auto-configure a suitable `MongoDatabaseFactory`.
|
||||
|
||||
The auto-configured `MongoClient` is created using `MongoClientSettings`.
|
||||
To fine-tune its configuration, declare one or more `MongoClientSettingsBuilderCustomizer` beans.
|
||||
Each will be called in order with the `MongoClientSettings.Builder` that is used to build the `MongoClientSettings`.
|
||||
|
||||
TIP: If `spring.data.mongodb.port` is not specified, the default of `27017` is used.
|
||||
You could delete this line from the example shown earlier.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue