Harmonize MongoDB client factories
This commit brings MongoClientFactory and ReactiveMongoClientFactory into functional alignment and reduces duplication in the classes and their tests. There are no behavior changes to ReactiveMongoClientFactory. MongoClientFactory now throws an exception when a URI is configured along with a host, port, or credentials, where it previousy ignored host, port, and credentials silently. MongClientFactory now also supports MongoClientSettingsBuilderCustomizers. Fixes gh-20019
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.mongo;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.client.MongoClient;
|
||||
|
||||
@@ -36,6 +38,7 @@ import org.springframework.core.env.Environment;
|
||||
* @author Phillip Webb
|
||||
* @author Mark Paluch
|
||||
* @author Stephane Nicoll
|
||||
* @author Scott Frederick
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@@ -46,9 +49,12 @@ public class MongoAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MongoClient.class)
|
||||
public MongoClient mongo(MongoProperties properties, ObjectProvider<MongoClientSettings> settings,
|
||||
Environment environment) {
|
||||
return new MongoClientFactory(properties, environment).createMongoClient(settings.getIfAvailable());
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,21 +16,15 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.mongo;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.MongoClientSettings.Builder;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoClients;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* A factory for a blocking {@link MongoClient} that applies {@link MongoProperties}.
|
||||
* A factory for a blocking {@link MongoClient}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
@@ -40,90 +34,32 @@ import org.springframework.core.env.Environment;
|
||||
* @author Stephane Nicoll
|
||||
* @author Nasko Vasilev
|
||||
* @author Mark Paluch
|
||||
* @author Scott Frederick
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class MongoClientFactory {
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
private final Environment environment;
|
||||
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
|
||||
public MongoClientFactory(MongoProperties properties, Environment environment) {
|
||||
this.properties = properties;
|
||||
this.environment = environment;
|
||||
this(properties, environment, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MongoClient} using the given {@link MongoClientSettings settings}.
|
||||
* If the environment contains a {@code local.mongo.port} property, it is used to
|
||||
* configure a client to an embedded MongoDB instance.
|
||||
* @param settings the settings
|
||||
* @return the Mongo client
|
||||
* Construct a factory for creating a blocking {@link MongoClient}.
|
||||
* @param properties configuration properties
|
||||
* @param environment a Spring {@link Environment} containing configuration properties
|
||||
* @param builderCustomizers a list of configuration settings customizers
|
||||
*/
|
||||
public MongoClient createMongoClient(MongoClientSettings settings) {
|
||||
Builder settingsBuilder = (settings != null) ? MongoClientSettings.builder(settings)
|
||||
: MongoClientSettings.builder();
|
||||
settingsBuilder.uuidRepresentation(this.properties.getUuidRepresentation());
|
||||
Integer embeddedPort = getEmbeddedPort();
|
||||
if (embeddedPort != null) {
|
||||
return createEmbeddedMongoClient(settingsBuilder, embeddedPort);
|
||||
}
|
||||
return createNetworkMongoClient(settingsBuilder);
|
||||
}
|
||||
|
||||
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 MongoClient createEmbeddedMongoClient(Builder settings, int port) {
|
||||
String host = (this.properties.getHost() != null) ? this.properties.getHost() : "localhost";
|
||||
settings.applyToClusterSettings(
|
||||
(cluster) -> cluster.hosts(Collections.singletonList(new ServerAddress(host, port))));
|
||||
return MongoClients.create(settings.build());
|
||||
}
|
||||
|
||||
private MongoClient createNetworkMongoClient(Builder settings) {
|
||||
MongoProperties properties = this.properties;
|
||||
if (properties.getUri() != null) {
|
||||
return createMongoClient(properties.getUri(), settings);
|
||||
}
|
||||
if (hasCustomAddress() || hasCustomCredentials()) {
|
||||
if (hasCustomCredentials()) {
|
||||
String database = (this.properties.getAuthenticationDatabase() != null)
|
||||
? this.properties.getAuthenticationDatabase() : this.properties.getMongoClientDatabase();
|
||||
settings.credential((MongoCredential.createCredential(this.properties.getUsername(), database,
|
||||
this.properties.getPassword())));
|
||||
}
|
||||
String host = getValue(properties.getHost(), "localhost");
|
||||
int port = getValue(properties.getPort(), MongoProperties.DEFAULT_PORT);
|
||||
List<ServerAddress> seeds = Collections.singletonList(new ServerAddress(host, port));
|
||||
settings.applyToClusterSettings((cluster) -> cluster.hosts(seeds));
|
||||
return MongoClients.create(settings.build());
|
||||
}
|
||||
return createMongoClient(MongoProperties.DEFAULT_URI, settings);
|
||||
}
|
||||
|
||||
private MongoClient createMongoClient(String uri, Builder settings) {
|
||||
settings.applyConnectionString(new ConnectionString(uri));
|
||||
return MongoClients.create(settings.build());
|
||||
}
|
||||
|
||||
private <T> T getValue(T value, T fallback) {
|
||||
return (value != null) ? value : fallback;
|
||||
}
|
||||
|
||||
private boolean hasCustomAddress() {
|
||||
return this.properties.getHost() != null || this.properties.getPort() != null;
|
||||
}
|
||||
|
||||
private boolean hasCustomCredentials() {
|
||||
return this.properties.getUsername() != null && this.properties.getPassword() != null;
|
||||
public MongoClientFactory(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> builderCustomizers) {
|
||||
super(properties, environment, builderCustomizers, MongoClients::create);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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 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.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Scott Frederick
|
||||
* @since 2.3.0
|
||||
*/
|
||||
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;
|
||||
|
||||
protected MongoClientFactorySupport(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> builderCustomizers,
|
||||
BiFunction<MongoClientSettings, MongoDriverInformation, T> clientCreator) {
|
||||
this.properties = properties;
|
||||
this.environment = environment;
|
||||
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());
|
||||
}
|
||||
|
||||
private MongoClientSettings computeClientSettings(MongoClientSettings settings) {
|
||||
Builder settingsBuilder = (settings != null) ? MongoClientSettings.builder(settings)
|
||||
: MongoClientSettings.builder();
|
||||
validateConfiguration();
|
||||
applyUuidRepresentation(settingsBuilder);
|
||||
applyHostAndPort(settingsBuilder);
|
||||
applyCredentials(settingsBuilder);
|
||||
customize(settingsBuilder);
|
||||
return settingsBuilder.build();
|
||||
}
|
||||
|
||||
private void validateConfiguration() {
|
||||
if (hasCustomAddress() || hasCustomCredentials()) {
|
||||
Assert.state(this.properties.getUri() == null,
|
||||
"Invalid mongo configuration, either uri or host/port/credentials 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 customize(MongoClientSettings.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 hasCustomAddress() {
|
||||
return this.properties.getHost() != null || this.properties.getPort() != null;
|
||||
}
|
||||
|
||||
private MongoDriverInformation driverInformation() {
|
||||
return MongoDriverInformation.builder(MongoDriverInformation.builder().build()).driverName("spring-boot")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,137 +16,26 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.mongo;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.MongoClientSettings.Builder;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.reactivestreams.client.MongoClient;
|
||||
import com.mongodb.reactivestreams.client.MongoClients;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A factory for a reactive {@link MongoClient} that applies {@link MongoProperties}.
|
||||
* A factory for a reactive {@link MongoClient}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Stephane Nicoll
|
||||
* @author Scott Frederick
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class ReactiveMongoClientFactory {
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private final List<MongoClientSettingsBuilderCustomizer> builderCustomizers;
|
||||
public class ReactiveMongoClientFactory extends MongoClientFactorySupport<MongoClient> {
|
||||
|
||||
public ReactiveMongoClientFactory(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> builderCustomizers) {
|
||||
this.properties = properties;
|
||||
this.environment = environment;
|
||||
this.builderCustomizers = (builderCustomizers != null) ? builderCustomizers : Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MongoClient} using the given {@code settings}. If the environment
|
||||
* contains a {@code local.mongo.port} property, it is used to configure a client to
|
||||
* an embedded MongoDB instance.
|
||||
* @param settings the settings
|
||||
* @return the Mongo client
|
||||
*/
|
||||
public MongoClient createMongoClient(MongoClientSettings settings) {
|
||||
Integer embeddedPort = getEmbeddedPort();
|
||||
if (embeddedPort != null) {
|
||||
return createEmbeddedMongoClient(settings, embeddedPort);
|
||||
}
|
||||
return createNetworkMongoClient(settings);
|
||||
}
|
||||
|
||||
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 MongoClient createEmbeddedMongoClient(MongoClientSettings settings, int port) {
|
||||
Builder builder = builder(settings);
|
||||
String host = (this.properties.getHost() != null) ? this.properties.getHost() : "localhost";
|
||||
builder.applyToClusterSettings(
|
||||
(cluster) -> cluster.hosts(Collections.singletonList(new ServerAddress(host, port))));
|
||||
return createMongoClient(builder);
|
||||
}
|
||||
|
||||
private MongoClient createNetworkMongoClient(MongoClientSettings settings) {
|
||||
if (hasCustomAddress() || hasCustomCredentials()) {
|
||||
return createCredentialNetworkMongoClient(settings);
|
||||
}
|
||||
ConnectionString connectionString = new ConnectionString(this.properties.determineUri());
|
||||
return createMongoClient(createBuilder(settings, connectionString));
|
||||
}
|
||||
|
||||
private MongoClient createCredentialNetworkMongoClient(MongoClientSettings settings) {
|
||||
Assert.state(this.properties.getUri() == null,
|
||||
"Invalid mongo configuration, either uri or host/port/credentials must be specified");
|
||||
Builder builder = builder(settings);
|
||||
if (hasCustomCredentials()) {
|
||||
applyCredentials(builder);
|
||||
}
|
||||
String host = getOrDefault(this.properties.getHost(), "localhost");
|
||||
int port = getOrDefault(this.properties.getPort(), MongoProperties.DEFAULT_PORT);
|
||||
ServerAddress serverAddress = new ServerAddress(host, port);
|
||||
builder.applyToClusterSettings((cluster) -> cluster.hosts(Collections.singletonList(serverAddress)));
|
||||
return createMongoClient(builder);
|
||||
}
|
||||
|
||||
private void applyCredentials(Builder builder) {
|
||||
String database = (this.properties.getAuthenticationDatabase() != null)
|
||||
? this.properties.getAuthenticationDatabase() : this.properties.getMongoClientDatabase();
|
||||
builder.credential((MongoCredential.createCredential(this.properties.getUsername(), database,
|
||||
this.properties.getPassword())));
|
||||
}
|
||||
|
||||
private <T> T getOrDefault(T value, T defaultValue) {
|
||||
return (value != null) ? value : defaultValue;
|
||||
}
|
||||
|
||||
private MongoClient createMongoClient(Builder builder) {
|
||||
builder.uuidRepresentation(this.properties.getUuidRepresentation());
|
||||
customize(builder);
|
||||
return MongoClients.create(builder.build());
|
||||
}
|
||||
|
||||
private Builder createBuilder(MongoClientSettings settings, ConnectionString connection) {
|
||||
return builder(settings).applyConnectionString(connection);
|
||||
}
|
||||
|
||||
private void customize(MongoClientSettings.Builder builder) {
|
||||
for (MongoClientSettingsBuilderCustomizer customizer : this.builderCustomizers) {
|
||||
customizer.customize(builder);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasCustomAddress() {
|
||||
return this.properties.getHost() != null || this.properties.getPort() != null;
|
||||
}
|
||||
|
||||
private boolean hasCustomCredentials() {
|
||||
return this.properties.getUsername() != null && this.properties.getPassword() != null;
|
||||
}
|
||||
|
||||
private Builder builder(MongoClientSettings settings) {
|
||||
if (settings == null) {
|
||||
return MongoClientSettings.builder();
|
||||
}
|
||||
return MongoClientSettings.builder(settings);
|
||||
super(properties, environment, builderCustomizers, MongoClients::create);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.mongodb.client.MongoClients;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -36,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class MongoAutoConfigurationTests {
|
||||
|
||||
@@ -50,24 +52,23 @@ class MongoAutoConfigurationTests {
|
||||
@Test
|
||||
void settingsAdded() {
|
||||
this.contextRunner.withUserConfiguration(SettingsConfig.class)
|
||||
.run((context) -> assertThat(extractClientSettings(context.getBean(MongoClient.class))
|
||||
.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)).isEqualTo(300));
|
||||
.run((context) -> assertThat(
|
||||
getSettings(context).getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(300));
|
||||
}
|
||||
|
||||
@Test
|
||||
void settingsAddedButNoHost() {
|
||||
this.contextRunner.withUserConfiguration(SettingsConfig.class)
|
||||
.run((context) -> assertThat(extractClientSettings(context.getBean(MongoClient.class))
|
||||
.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)).isEqualTo(300));
|
||||
.run((context) -> assertThat(
|
||||
getSettings(context).getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(300));
|
||||
}
|
||||
|
||||
@Test
|
||||
void settingsSslConfig() {
|
||||
this.contextRunner.withUserConfiguration(SslSettingsConfig.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(MongoClient.class);
|
||||
MongoClientSettings settings = extractClientSettings(context.getBean(MongoClient.class));
|
||||
assertThat(settings.getSslSettings().isEnabled()).isTrue();
|
||||
});
|
||||
this.contextRunner.withUserConfiguration(SslSettingsConfig.class)
|
||||
.run((context) -> assertThat(getSettings(context).getSslSettings().isEnabled()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -76,7 +77,16 @@ class MongoAutoConfigurationTests {
|
||||
.run((context) -> assertThat(context).hasSingleBean(MongoClient.class));
|
||||
}
|
||||
|
||||
private static MongoClientSettings extractClientSettings(MongoClient client) {
|
||||
@Test
|
||||
void customizerOverridesAutoConfig() {
|
||||
this.contextRunner.withPropertyValues("spring.data.mongodb.uri:mongodb://localhost/test?appname=auto-config")
|
||||
.withUserConfiguration(SimpleCustomizerConfig.class)
|
||||
.run((context) -> assertThat(getSettings(context).getApplicationName()).isEqualTo("overridden-name"));
|
||||
}
|
||||
|
||||
private MongoClientSettings getSettings(AssertableApplicationContext context) {
|
||||
assertThat(context).hasSingleBean(MongoClient.class);
|
||||
MongoClient client = context.getBean(MongoClient.class);
|
||||
return (MongoClientSettings) ReflectionTestUtils.getField(client, "settings");
|
||||
}
|
||||
|
||||
@@ -111,4 +121,14 @@ class MongoAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class SimpleCustomizerConfig {
|
||||
|
||||
@Bean
|
||||
MongoClientSettingsBuilderCustomizer customizer() {
|
||||
return (clientSettingsBuilder) -> clientSettingsBuilder.applicationName("overridden-name");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* 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.Arrays;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Tests for {@link MongoClientFactorySupport}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Stephane Nicoll
|
||||
* @author Mark Paluch
|
||||
* @author Artsiom Yudovin
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
abstract class MongoClientFactorySupportTests<T> {
|
||||
|
||||
private MongoProperties properties = new MongoProperties();
|
||||
|
||||
private MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
@Test
|
||||
void canBindCharArrayPassword() {
|
||||
// gh-1572
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
TestPropertyValues.of("spring.data.mongodb.password:word").applyTo(context);
|
||||
context.register(Config.class);
|
||||
context.refresh();
|
||||
MongoProperties properties = context.getBean(MongoProperties.class);
|
||||
assertThat(properties.getPassword()).isEqualTo("word".toCharArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
void allMongoClientSettingsCanBeSet() {
|
||||
MongoClientSettings.Builder builder = MongoClientSettings.builder();
|
||||
builder.applyToSocketSettings((settings) -> {
|
||||
settings.connectTimeout(1000, TimeUnit.MILLISECONDS);
|
||||
settings.readTimeout(1000, TimeUnit.MILLISECONDS);
|
||||
}).applyToServerSettings((settings) -> {
|
||||
settings.heartbeatFrequency(10001, TimeUnit.MILLISECONDS);
|
||||
settings.minHeartbeatFrequency(501, TimeUnit.MILLISECONDS);
|
||||
}).applyToConnectionPoolSettings((settings) -> {
|
||||
settings.maxWaitTime(120001, TimeUnit.MILLISECONDS);
|
||||
settings.maxConnectionLifeTime(60000, TimeUnit.MILLISECONDS);
|
||||
settings.maxConnectionIdleTime(60000, TimeUnit.MILLISECONDS);
|
||||
}).applyToSslSettings((settings) -> settings.enabled(true)).applicationName("test");
|
||||
|
||||
MongoClientSettings settings = builder.build();
|
||||
T client = createMongoClient(settings);
|
||||
MongoClientSettings wrapped = getClientSettings(client);
|
||||
assertThat(wrapped.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getSocketSettings().getReadTimeout(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getSocketSettings().getReadTimeout(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getServerSettings().getHeartbeatFrequency(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getServerSettings().getHeartbeatFrequency(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getServerSettings().getMinHeartbeatFrequency(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getServerSettings().getMinHeartbeatFrequency(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getApplicationName()).isEqualTo(settings.getApplicationName());
|
||||
assertThat(wrapped.getConnectionPoolSettings().getMaxWaitTime(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getConnectionPoolSettings().getMaxWaitTime(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getConnectionPoolSettings().getMaxConnectionLifeTime(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getConnectionPoolSettings().getMaxConnectionLifeTime(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getConnectionPoolSettings().getMaxConnectionIdleTime(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getConnectionPoolSettings().getMaxConnectionIdleTime(TimeUnit.MILLISECONDS));
|
||||
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 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 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 must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
void customizerIsInvoked() {
|
||||
MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class);
|
||||
createMongoClient(customizer);
|
||||
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();
|
||||
TestPropertyValues.of("spring.data.mongodb.autoIndexCreation:true").applyTo(context);
|
||||
context.register(Config.class);
|
||||
context.refresh();
|
||||
MongoProperties properties = context.getBean(MongoProperties.class);
|
||||
assertThat(properties.isAutoIndexCreation()).isTrue();
|
||||
}
|
||||
|
||||
protected T createMongoClient() {
|
||||
return createMongoClient(this.properties, this.environment, null, null);
|
||||
}
|
||||
|
||||
protected T createMongoClient(MongoClientSettings settings) {
|
||||
return createMongoClient(this.properties, this.environment, null, settings);
|
||||
}
|
||||
|
||||
protected void createMongoClient(MongoClientSettingsBuilderCustomizer... customizers) {
|
||||
createMongoClient(this.properties, this.environment, (customizers != null) ? Arrays.asList(customizers) : null,
|
||||
null);
|
||||
}
|
||||
|
||||
protected abstract T createMongoClient(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> customizers, MongoClientSettings settings);
|
||||
|
||||
protected abstract MongoClientSettings getClientSettings(T client);
|
||||
|
||||
protected abstract List<ServerAddress> getAllAddresses(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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,18 +19,12 @@ package org.springframework.boot.autoconfigure.mongo;
|
||||
import java.util.List;
|
||||
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import org.bson.UuidRepresentation;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link MongoClientFactory}.
|
||||
*
|
||||
@@ -38,124 +32,24 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Andy Wilkinson
|
||||
* @author Stephane Nicoll
|
||||
* @author Mark Paluch
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class MongoClientFactoryTests {
|
||||
class MongoClientFactoryTests extends MongoClientFactorySupportTests<MongoClient> {
|
||||
|
||||
private MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
@Test
|
||||
void portCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setPort(12345);
|
||||
MongoClient client = createMongoClient(properties);
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 12345);
|
||||
@Override
|
||||
protected MongoClient createMongoClient(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> customizers, MongoClientSettings settings) {
|
||||
return new MongoClientFactory(properties, environment, customizers).createMongoClient(settings);
|
||||
}
|
||||
|
||||
@Test
|
||||
void hostCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setHost("mongo.example.com");
|
||||
MongoClient client = createMongoClient(properties);
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "mongo.example.com", 27017);
|
||||
}
|
||||
|
||||
@Test
|
||||
void credentialsCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUsername("user");
|
||||
properties.setPassword("secret".toCharArray());
|
||||
MongoClient client = createMongoClient(properties);
|
||||
assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void databaseCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setDatabase("foo");
|
||||
properties.setUsername("user");
|
||||
properties.setPassword("secret".toCharArray());
|
||||
MongoClient client = createMongoClient(properties);
|
||||
assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uuidRepresentationDefaultToJavaLegacy() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
MongoClient client = createMongoClient(properties);
|
||||
assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.JAVA_LEGACY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uuidRepresentationCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUuidRepresentation(UuidRepresentation.STANDARD);
|
||||
MongoClient client = createMongoClient(properties);
|
||||
assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.STANDARD);
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticationDatabaseCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setAuthenticationDatabase("foo");
|
||||
properties.setUsername("user");
|
||||
properties.setPassword("secret".toCharArray());
|
||||
MongoClient client = createMongoClient(properties);
|
||||
assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUri("mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test");
|
||||
MongoClient client = createMongoClient(properties);
|
||||
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() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUri("mongodb://mongo.example.com:1234/mydb");
|
||||
this.environment.setProperty("local.mongo.port", "4000");
|
||||
MongoClient client = createMongoClient(properties, this.environment);
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 4000);
|
||||
}
|
||||
|
||||
private MongoClient createMongoClient(MongoProperties properties) {
|
||||
return createMongoClient(properties, null);
|
||||
}
|
||||
|
||||
private MongoClient createMongoClient(MongoProperties properties, Environment environment) {
|
||||
return new MongoClientFactory(properties, environment).createMongoClient(null);
|
||||
}
|
||||
|
||||
private List<ServerAddress> getAllAddresses(MongoClient client) {
|
||||
@Override
|
||||
protected List<ServerAddress> getAllAddresses(MongoClient client) {
|
||||
return client.getClusterDescription().getClusterSettings().getHosts();
|
||||
}
|
||||
|
||||
private MongoClientSettings getClientSettings(MongoClient client) {
|
||||
@Override
|
||||
protected MongoClientSettings getClientSettings(MongoClient client) {
|
||||
return (MongoClientSettings) ReflectionTestUtils.getField(client, "settings");
|
||||
}
|
||||
|
||||
private void assertServerAddress(ServerAddress serverAddress, String expectedHost, int expectedPort) {
|
||||
assertThat(serverAddress.getHost()).isEqualTo(expectedHost);
|
||||
assertThat(serverAddress.getPort()).isEqualTo(expectedPort);
|
||||
}
|
||||
|
||||
private 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* 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 java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.client.MongoClient;
|
||||
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.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link MongoProperties}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Stephane Nicoll
|
||||
* @author Mark Paluch
|
||||
* @author Artsiom Yudovin
|
||||
*/
|
||||
class MongoPropertiesTests {
|
||||
|
||||
@Test
|
||||
void canBindCharArrayPassword() {
|
||||
// gh-1572
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
TestPropertyValues.of("spring.data.mongodb.password:word").applyTo(context);
|
||||
context.register(Config.class);
|
||||
context.refresh();
|
||||
MongoProperties properties = context.getBean(MongoProperties.class);
|
||||
assertThat(properties.getPassword()).isEqualTo("word".toCharArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
void allMongoClientSettingsCanBeSet() {
|
||||
MongoClientSettings.Builder builder = MongoClientSettings.builder();
|
||||
builder.applyToSocketSettings((settings) -> {
|
||||
settings.connectTimeout(1000, TimeUnit.MILLISECONDS);
|
||||
settings.readTimeout(1000, TimeUnit.MILLISECONDS);
|
||||
}).applyToServerSettings((settings) -> {
|
||||
settings.heartbeatFrequency(10001, TimeUnit.MILLISECONDS);
|
||||
settings.minHeartbeatFrequency(501, TimeUnit.MILLISECONDS);
|
||||
}).applyToConnectionPoolSettings((settings) -> {
|
||||
settings.maxWaitTime(120001, TimeUnit.MILLISECONDS);
|
||||
settings.maxConnectionLifeTime(60000, TimeUnit.MILLISECONDS);
|
||||
settings.maxConnectionIdleTime(60000, TimeUnit.MILLISECONDS);
|
||||
}).applyToSslSettings((settings) -> settings.enabled(true)).applicationName("test");
|
||||
|
||||
MongoClientSettings settings = builder.build();
|
||||
MongoProperties properties = new MongoProperties();
|
||||
MongoClient client = createMongoClient(properties, settings);
|
||||
MongoClientSettings wrapped = (MongoClientSettings) ReflectionTestUtils.getField(client, "settings");
|
||||
assertThat(wrapped.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getSocketSettings().getReadTimeout(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getSocketSettings().getReadTimeout(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getServerSettings().getHeartbeatFrequency(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getServerSettings().getHeartbeatFrequency(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getServerSettings().getMinHeartbeatFrequency(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getServerSettings().getMinHeartbeatFrequency(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getApplicationName()).isEqualTo(settings.getApplicationName());
|
||||
assertThat(wrapped.getConnectionPoolSettings().getMaxWaitTime(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getConnectionPoolSettings().getMaxWaitTime(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getConnectionPoolSettings().getMaxConnectionLifeTime(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getConnectionPoolSettings().getMaxConnectionLifeTime(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getConnectionPoolSettings().getMaxConnectionIdleTime(TimeUnit.MILLISECONDS))
|
||||
.isEqualTo(settings.getConnectionPoolSettings().getMaxConnectionIdleTime(TimeUnit.MILLISECONDS));
|
||||
assertThat(wrapped.getSslSettings().isEnabled()).isEqualTo(settings.getSslSettings().isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriOverridesHostAndPort() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setHost("localhost");
|
||||
properties.setPort(27017);
|
||||
properties.setUri("mongodb://mongo1.example.com:12345");
|
||||
MongoClient client = createMongoClient(properties);
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onlyHostAndPortSetShouldUseThat() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setHost("localhost");
|
||||
properties.setPort(27017);
|
||||
MongoClient client = createMongoClient(properties);
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 27017);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onlyUriSetShouldUseThat() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUri("mongodb://mongo1.example.com:12345");
|
||||
MongoClient client = createMongoClient(properties);
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
|
||||
}
|
||||
|
||||
@Test
|
||||
void noCustomAddressAndNoUriUsesDefaultUri() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
MongoClient client = createMongoClient(properties);
|
||||
List<ServerAddress> allAddresses = getAllAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 27017);
|
||||
}
|
||||
|
||||
private MongoClient createMongoClient(MongoProperties properties, MongoClientSettings settings) {
|
||||
return new MongoClientFactory(properties, null).createMongoClient(settings);
|
||||
}
|
||||
|
||||
private MongoClient createMongoClient(MongoProperties properties) {
|
||||
return createMongoClient(properties, null);
|
||||
}
|
||||
|
||||
private List<ServerAddress> getAllAddresses(MongoClient client) {
|
||||
return client.getClusterDescription().getClusterSettings().getHosts();
|
||||
}
|
||||
|
||||
@Test
|
||||
void canBindAutoIndexCreation() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
TestPropertyValues.of("spring.data.mongodb.autoIndexCreation:true").applyTo(context);
|
||||
context.register(Config.class);
|
||||
context.refresh();
|
||||
MongoProperties properties = context.getBean(MongoProperties.class);
|
||||
assertThat(properties.isAutoIndexCreation()).isTrue();
|
||||
}
|
||||
|
||||
private void assertServerAddress(ServerAddress serverAddress, String expectedHost, int expectedPort) {
|
||||
assertThat(serverAddress.getHost()).isEqualTo(expectedHost);
|
||||
assertThat(serverAddress.getPort()).isEqualTo(expectedPort);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(MongoProperties.class)
|
||||
static class Config {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,210 +16,43 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.mongo;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.connection.ClusterSettings;
|
||||
import com.mongodb.internal.async.client.AsyncMongoClient;
|
||||
import com.mongodb.reactivestreams.client.MongoClient;
|
||||
import org.bson.UuidRepresentation;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Tests for {@link ReactiveMongoClientFactory}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Stephane Nicoll
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class ReactiveMongoClientFactoryTests {
|
||||
class ReactiveMongoClientFactoryTests extends MongoClientFactorySupportTests<MongoClient> {
|
||||
|
||||
private MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
@Test
|
||||
void portCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setPort(12345);
|
||||
MongoClient client = createMongoClient(properties);
|
||||
List<ServerAddress> allAddresses = extractServerAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 12345);
|
||||
@Override
|
||||
protected MongoClient createMongoClient(MongoProperties properties, Environment environment,
|
||||
List<MongoClientSettingsBuilderCustomizer> customizers, MongoClientSettings settings) {
|
||||
return new ReactiveMongoClientFactory(properties, environment, customizers).createMongoClient(settings);
|
||||
}
|
||||
|
||||
@Test
|
||||
void hostCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setHost("mongo.example.com");
|
||||
MongoClient client = createMongoClient(properties);
|
||||
List<ServerAddress> allAddresses = extractServerAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "mongo.example.com", 27017);
|
||||
}
|
||||
|
||||
@Test
|
||||
void credentialsCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUsername("user");
|
||||
properties.setPassword("secret".toCharArray());
|
||||
MongoClient client = createMongoClient(properties);
|
||||
assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void databaseCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setDatabase("foo");
|
||||
properties.setUsername("user");
|
||||
properties.setPassword("secret".toCharArray());
|
||||
MongoClient client = createMongoClient(properties);
|
||||
assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uuidRepresentationDefaultToJavaLegacy() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
MongoClient client = createMongoClient(properties);
|
||||
assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.JAVA_LEGACY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uuidRepresentationCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUuidRepresentation(UuidRepresentation.STANDARD);
|
||||
MongoClient client = createMongoClient(properties);
|
||||
assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.STANDARD);
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticationDatabaseCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setAuthenticationDatabase("foo");
|
||||
properties.setUsername("user");
|
||||
properties.setPassword("secret".toCharArray());
|
||||
MongoClient client = createMongoClient(properties);
|
||||
assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCanBeCustomized() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUri("mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test");
|
||||
MongoClient client = createMongoClient(properties);
|
||||
List<ServerAddress> allAddresses = extractServerAddresses(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 retryWritesIsPropagatedFromUri() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUri("mongodb://localhost/test?retryWrites=true");
|
||||
MongoClient client = createMongoClient(properties);
|
||||
assertThat(getClientSettings(client).getRetryWrites()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCannotBeSetWithCredentials() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUri("mongodb://127.0.0.1:1234/mydb");
|
||||
properties.setUsername("user");
|
||||
properties.setPassword("secret".toCharArray());
|
||||
assertThatIllegalStateException().isThrownBy(() -> createMongoClient(properties)).withMessageContaining(
|
||||
"Invalid mongo configuration, either uri or host/port/credentials must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriCannotBeSetWithHostPort() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUri("mongodb://127.0.0.1:1234/mydb");
|
||||
properties.setHost("localhost");
|
||||
properties.setPort(4567);
|
||||
assertThatIllegalStateException().isThrownBy(() -> createMongoClient(properties)).withMessageContaining(
|
||||
"Invalid mongo configuration, either uri or host/port/credentials must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriIsIgnoredInEmbeddedMode() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setUri("mongodb://mongo.example.com:1234/mydb");
|
||||
this.environment.setProperty("local.mongo.port", "4000");
|
||||
MongoClient client = createMongoClient(properties, this.environment);
|
||||
List<ServerAddress> allAddresses = extractServerAddresses(client);
|
||||
assertThat(allAddresses).hasSize(1);
|
||||
assertServerAddress(allAddresses.get(0), "localhost", 4000);
|
||||
}
|
||||
|
||||
@Test
|
||||
void customizerIsInvoked() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class);
|
||||
createMongoClient(properties, this.environment, customizer);
|
||||
verify(customizer).customize(any(MongoClientSettings.Builder.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customizerIsInvokedWhenHostIsSet() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
properties.setHost("localhost");
|
||||
MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class);
|
||||
createMongoClient(properties, this.environment, customizer);
|
||||
verify(customizer).customize(any(MongoClientSettings.Builder.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customizerIsInvokedForEmbeddedMongo() {
|
||||
MongoProperties properties = new MongoProperties();
|
||||
this.environment.setProperty("local.mongo.port", "27017");
|
||||
MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class);
|
||||
createMongoClient(properties, this.environment, customizer);
|
||||
verify(customizer).customize(any(MongoClientSettings.Builder.class));
|
||||
}
|
||||
|
||||
private MongoClient createMongoClient(MongoProperties properties) {
|
||||
return createMongoClient(properties, this.environment);
|
||||
}
|
||||
|
||||
private MongoClient createMongoClient(MongoProperties properties, Environment environment,
|
||||
MongoClientSettingsBuilderCustomizer... customizers) {
|
||||
return new ReactiveMongoClientFactory(properties, environment, Arrays.asList(customizers))
|
||||
.createMongoClient(null);
|
||||
}
|
||||
|
||||
private List<ServerAddress> extractServerAddresses(MongoClient client) {
|
||||
@Override
|
||||
protected List<ServerAddress> getAllAddresses(MongoClient client) {
|
||||
MongoClientSettings settings = getClientSettings(client);
|
||||
ClusterSettings clusterSettings = settings.getClusterSettings();
|
||||
return clusterSettings.getHosts();
|
||||
}
|
||||
|
||||
private MongoClientSettings getClientSettings(MongoClient client) {
|
||||
@Override
|
||||
protected MongoClientSettings getClientSettings(MongoClient client) {
|
||||
AsyncMongoClient wrapped = (AsyncMongoClient) ReflectionTestUtils.getField(client, "wrapped");
|
||||
return (MongoClientSettings) ReflectionTestUtils.getField(wrapped, "settings");
|
||||
}
|
||||
|
||||
private void assertServerAddress(ServerAddress serverAddress, String expectedHost, int expectedPort) {
|
||||
assertThat(serverAddress.getHost()).isEqualTo(expectedHost);
|
||||
assertThat(serverAddress.getPort()).isEqualTo(expectedPort);
|
||||
}
|
||||
|
||||
private 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user