diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle index 85bda5f0e58..9df64f579c3 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle @@ -83,7 +83,7 @@ dependencies { optional("org.influxdb:influxdb-java") optional("org.jolokia:jolokia-core") optional("org.liquibase:liquibase-core") - optional("org.mongodb:mongodb-driver-async") + optional("org.mongodb:mongodb-driver-sync") optional("org.mongodb:mongodb-driver-reactivestreams") optional("org.springframework:spring-jdbc") optional("org.springframework:spring-jms") diff --git a/spring-boot-project/spring-boot-actuator/build.gradle b/spring-boot-project/spring-boot-actuator/build.gradle index 3dc994b9b83..914b4a827fd 100644 --- a/spring-boot-project/spring-boot-actuator/build.gradle +++ b/spring-boot-project/spring-boot-actuator/build.gradle @@ -43,7 +43,7 @@ dependencies { optional("org.hibernate.validator:hibernate-validator") optional("org.influxdb:influxdb-java") optional("org.liquibase:liquibase-core") - optional("org.mongodb:mongodb-driver-async") + optional("org.mongodb:mongodb-driver-sync") optional("org.mongodb:mongodb-driver-reactivestreams") optional("org.springframework:spring-jdbc") optional("org.springframework:spring-messaging") diff --git a/spring-boot-project/spring-boot-autoconfigure/build.gradle b/spring-boot-project/spring-boot-autoconfigure/build.gradle index 712a7e0aa4b..500050ace67 100644 --- a/spring-boot-project/spring-boot-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-autoconfigure/build.gradle @@ -95,7 +95,7 @@ dependencies { optional("org.jooq:jooq") optional("org.liquibase:liquibase-core") optional("org.messaginghub:pooled-jms") - optional("org.mongodb:mongodb-driver-async") + optional("org.mongodb:mongodb-driver-sync") optional("org.mongodb:mongodb-driver-reactivestreams") optional("org.quartz-scheduler:quartz") optional("org.springframework:spring-jdbc") diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoClientDependsOnBeanFactoryPostProcessor.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoClientDependsOnBeanFactoryPostProcessor.java index 5b0288ff8c0..f73bcaaa72b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoClientDependsOnBeanFactoryPostProcessor.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoClientDependsOnBeanFactoryPostProcessor.java @@ -16,7 +16,7 @@ package org.springframework.boot.autoconfigure.data.mongo; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataAutoConfiguration.java index 358a3f33e25..9836e36ae54 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataAutoConfiguration.java @@ -16,8 +16,6 @@ package org.springframework.boot.autoconfigure.data.mongo; -import com.mongodb.MongoClient; - import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -48,7 +46,7 @@ import org.springframework.data.mongodb.gridfs.GridFsTemplate; * @since 1.1.0 */ @Configuration(proxyBeanMethods = false) -@ConditionalOnClass({ MongoClient.class, com.mongodb.client.MongoClient.class, MongoTemplate.class }) +@ConditionalOnClass({ com.mongodb.client.MongoClient.class, MongoTemplate.class }) @EnableConfigurationProperties(MongoProperties.class) @Import({ MongoDataConfiguration.class, MongoDbFactoryConfiguration.class, MongoDbFactoryDependentConfiguration.class }) @AutoConfigureAfter(MongoAutoConfiguration.class) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryConfiguration.java index e8bc2dded11..5486bf9c9bd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryConfiguration.java @@ -16,7 +16,7 @@ package org.springframework.boot.autoconfigure.data.mongo; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; @@ -27,31 +27,26 @@ import org.springframework.boot.autoconfigure.mongo.MongoProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; -import org.springframework.data.mongodb.MongoDbFactory; -import org.springframework.data.mongodb.core.MongoDbFactorySupport; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.MongoDatabaseFactorySupport; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; /** - * Configuration for a {@link MongoDbFactory}. + * Configuration for a {@link MongoDatabaseFactory}. * * @author Andy Wilkinson */ @Configuration(proxyBeanMethods = false) -@ConditionalOnMissingBean(MongoDbFactory.class) +@ConditionalOnMissingBean(MongoDatabaseFactory.class) @Conditional(AnyMongoClientAvailable.class) class MongoDbFactoryConfiguration { @Bean - MongoDbFactorySupport mongoDbFactory(ObjectProvider mongo, - ObjectProvider mongoClient, MongoProperties properties) { - MongoClient preferredClient = mongo.getIfAvailable(); - if (preferredClient != null) { - return new SimpleMongoDbFactory(preferredClient, properties.getMongoClientDatabase()); - } + MongoDatabaseFactorySupport mongoDbFactory(ObjectProvider mongoClient, MongoProperties properties) { + com.mongodb.client.MongoClient fallbackClient = mongoClient.getIfAvailable(); if (fallbackClient != null) { - return new SimpleMongoClientDbFactory(fallbackClient, properties.getMongoClientDatabase()); + return new SimpleMongoClientDatabaseFactory(fallbackClient, properties.getMongoClientDatabase()); } throw new IllegalStateException("Expected to find at least one MongoDB client."); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryDependentConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryDependentConfiguration.java index 9c8e7d886a9..c647cc9e99b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryDependentConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDbFactoryDependentConfiguration.java @@ -17,7 +17,6 @@ package org.springframework.boot.autoconfigure.data.mongo; import com.mongodb.ClientSessionOptions; -import com.mongodb.DB; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoDatabase; @@ -28,7 +27,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.convert.DbRefResolver; @@ -43,12 +42,12 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * Configuration for Mongo-related beans that depend on a {@link MongoDbFactory}. + * Configuration for Mongo-related beans that depend on a {@link MongoDatabaseFactory}. * * @author Andy Wilkinson */ @Configuration(proxyBeanMethods = false) -@ConditionalOnBean(MongoDbFactory.class) +@ConditionalOnBean(MongoDatabaseFactory.class) class MongoDbFactoryDependentConfiguration { private final MongoProperties properties; @@ -59,13 +58,13 @@ class MongoDbFactoryDependentConfiguration { @Bean @ConditionalOnMissingBean(MongoOperations.class) - MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter converter) { + MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDbFactory, MongoConverter converter) { return new MongoTemplate(mongoDbFactory, converter); } @Bean @ConditionalOnMissingBean(MongoConverter.class) - MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context, + MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory factory, MongoMappingContext context, MongoCustomConversions conversions) { DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context); @@ -75,22 +74,22 @@ class MongoDbFactoryDependentConfiguration { @Bean @ConditionalOnMissingBean(GridFsOperations.class) - GridFsTemplate gridFsTemplate(MongoDbFactory mongoDbFactory, MongoTemplate mongoTemplate) { + GridFsTemplate gridFsTemplate(MongoDatabaseFactory mongoDbFactory, MongoTemplate mongoTemplate) { return new GridFsTemplate(new GridFsMongoDbFactory(mongoDbFactory, this.properties), mongoTemplate.getConverter()); } /** - * {@link MongoDbFactory} decorator to respect + * {@link MongoDatabaseFactory} decorator to respect * {@link MongoProperties#getGridFsDatabase()} if set. */ - static class GridFsMongoDbFactory implements MongoDbFactory { + static class GridFsMongoDbFactory implements MongoDatabaseFactory { - private final MongoDbFactory mongoDbFactory; + private final MongoDatabaseFactory mongoDbFactory; private final MongoProperties properties; - GridFsMongoDbFactory(MongoDbFactory mongoDbFactory, MongoProperties properties) { + GridFsMongoDbFactory(MongoDatabaseFactory mongoDbFactory, MongoProperties properties) { Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null"); Assert.notNull(properties, "Properties must not be null"); this.mongoDbFactory = mongoDbFactory; @@ -98,17 +97,17 @@ class MongoDbFactoryDependentConfiguration { } @Override - public MongoDatabase getDb() throws DataAccessException { + public MongoDatabase getMongoDatabase() throws DataAccessException { String gridFsDatabase = this.properties.getGridFsDatabase(); if (StringUtils.hasText(gridFsDatabase)) { - return this.mongoDbFactory.getDb(gridFsDatabase); + return this.mongoDbFactory.getMongoDatabase(gridFsDatabase); } - return this.mongoDbFactory.getDb(); + return this.mongoDbFactory.getMongoDatabase(); } @Override - public MongoDatabase getDb(String dbName) throws DataAccessException { - return this.mongoDbFactory.getDb(dbName); + public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException { + return this.mongoDbFactory.getMongoDatabase(dbName); } @Override @@ -116,19 +115,13 @@ class MongoDbFactoryDependentConfiguration { return this.mongoDbFactory.getExceptionTranslator(); } - @Override - @Deprecated - public DB getLegacyDb() { - return this.mongoDbFactory.getLegacyDb(); - } - @Override public ClientSession getSession(ClientSessionOptions options) { return this.mongoDbFactory.getSession(options); } @Override - public MongoDbFactory withSession(ClientSession session) { + public MongoDatabaseFactory withSession(ClientSession session) { return this.mongoDbFactory.withSession(session); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfiguration.java index 527042576c8..3eb21d562f2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfiguration.java @@ -16,7 +16,7 @@ package org.springframework.boot.autoconfigure.data.mongo; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java index 7e4d882df45..406a3dc2e69 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java @@ -16,8 +16,10 @@ package org.springframework.boot.autoconfigure.mongo; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; +import java.util.stream.Collectors; + +import com.mongodb.MongoClientSettings; +import com.mongodb.client.MongoClient; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -45,10 +47,13 @@ import org.springframework.core.env.Environment; public class MongoAutoConfiguration { @Bean - @ConditionalOnMissingBean(type = { "com.mongodb.MongoClient", "com.mongodb.client.MongoClient" }) - public MongoClient mongo(MongoProperties properties, ObjectProvider options, - Environment environment) { - return new MongoClientFactory(properties, environment).createMongoClient(options.getIfAvailable()); + @ConditionalOnMissingBean(type = { "com.mongodb.client.MongoClient" }) + public MongoClient mongo(MongoProperties properties, Environment environment, + ObjectProvider builderCustomizers, + ObjectProvider settings) { + return new MongoClientFactory(properties, environment, + builderCustomizers.orderedStream().collect(Collectors.toList())) + .createMongoClient(settings.getIfAvailable()); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactory.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactory.java index 0717a51d849..583f44a4c6b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactory.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactory.java @@ -16,15 +16,11 @@ package org.springframework.boot.autoconfigure.mongo; -import java.util.Collections; import java.util.List; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; -import com.mongodb.MongoClientOptions.Builder; -import com.mongodb.MongoClientURI; -import com.mongodb.MongoCredential; -import com.mongodb.ServerAddress; +import com.mongodb.MongoClientSettings; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; import org.springframework.core.env.Environment; @@ -39,102 +35,23 @@ import org.springframework.core.env.Environment; * @author Stephane Nicoll * @author Nasko Vasilev * @author Mark Paluch + * @author Christoph Strobl * @since 2.0.0 */ -public class MongoClientFactory { +public class MongoClientFactory extends MongoClientFactorySupport { - private final MongoProperties properties; - - private final Environment environment; - - public MongoClientFactory(MongoProperties properties, Environment environment) { - this.properties = properties; - this.environment = environment; + public MongoClientFactory(MongoProperties properties, Environment environment, + List builderCustomizers) { + super(properties, environment, builderCustomizers); } - /** - * Creates a {@link MongoClient} using the given {@code options}. If the environment - * contains a {@code local.mongo.port} property, it is used to configure a client to - * an embedded MongoDB instance. - * @param options the options - * @return the Mongo client - */ - public MongoClient createMongoClient(MongoClientOptions options) { - Integer embeddedPort = getEmbeddedPort(); - if (embeddedPort != null) { - return createEmbeddedMongoClient(options, embeddedPort); - } - return createNetworkMongoClient(options); + protected MongoClient createNetworkMongoClient(MongoClientSettings settings) { + return MongoClients.create(settings, driverInformation()); } - 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(MongoClientOptions options, int port) { - if (options == null) { - options = MongoClientOptions.builder().build(); - } - String host = (this.properties.getHost() != null) ? this.properties.getHost() : "localhost"; - return new MongoClient(Collections.singletonList(new ServerAddress(host, port)), options); - } - - private MongoClient createNetworkMongoClient(MongoClientOptions options) { - MongoProperties properties = this.properties; - if (properties.getUri() != null) { - return createMongoClient(properties.getUri(), options); - } - if (hasCustomAddress() || hasCustomCredentials()) { - if (options == null) { - options = MongoClientOptions.builder().build(); - } - MongoCredential credentials = getCredentials(properties); - String host = getValue(properties.getHost(), "localhost"); - int port = getValue(properties.getPort(), MongoProperties.DEFAULT_PORT); - List seeds = Collections.singletonList(new ServerAddress(host, port)); - return (credentials != null) ? new MongoClient(seeds, credentials, options) - : new MongoClient(seeds, options); - } - return createMongoClient(MongoProperties.DEFAULT_URI, options); - } - - private MongoClient createMongoClient(String uri, MongoClientOptions options) { - return new MongoClient(new MongoClientURI(uri, builder(options))); - } - - private T getValue(T value, T fallback) { - return (value != null) ? value : fallback; - } - - private boolean hasCustomAddress() { - return this.properties.getHost() != null || this.properties.getPort() != null; - } - - private MongoCredential getCredentials(MongoProperties properties) { - if (!hasCustomCredentials()) { - return null; - } - String username = properties.getUsername(); - String database = getValue(properties.getAuthenticationDatabase(), properties.getMongoClientDatabase()); - char[] password = properties.getPassword(); - return MongoCredential.createCredential(username, database, password); - } - - private boolean hasCustomCredentials() { - return this.properties.getUsername() != null && this.properties.getPassword() != null; - } - - private Builder builder(MongoClientOptions options) { - if (options != null) { - return MongoClientOptions.builder(options); - } - return MongoClientOptions.builder(); + @Override + protected MongoClient createEmbeddedMongoClient(MongoClientSettings settings) { + return MongoClients.create(settings, driverInformation()); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactorySupport.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactorySupport.java new file mode 100644 index 00000000000..0e9c1e02642 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactorySupport.java @@ -0,0 +1,144 @@ +/* + * Copyright 2019 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 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 common setup bits (aka {@link MongoClientSettings}) required for + * instantiating a MongoClient. + * + * @author Christoph Strobl + * @since 2.3.0 + */ +public abstract class MongoClientFactorySupport { + + private final MongoProperties properties; + + private final Environment environment; + + private final List builderCustomizers; + + public MongoClientFactorySupport(MongoProperties properties, Environment environment, + List builderCustomizers) { + this.properties = properties; + this.environment = environment; + this.builderCustomizers = (builderCustomizers != null) ? builderCustomizers : Collections.emptyList(); + } + + public T createMongoClient(MongoClientSettings settings) { + MongoClientSettings targetSettings = computeClientSettings(settings); + return (getEmbeddedPort() != null) ? createEmbeddedMongoClient(targetSettings) + : createNetworkMongoClient(targetSettings); + } + + private MongoClientSettings computeClientSettings(MongoClientSettings settings) { + + Builder settingsBuilder = (settings != null) ? MongoClientSettings.builder(settings) + : MongoClientSettings.builder(); + applyHostAndPort(settingsBuilder); + applyCredentials(settingsBuilder); + + customize(settingsBuilder); + return settingsBuilder.build(); + } + + private void applyHostAndPort(MongoClientSettings.Builder settings) { + + if (isEmbedded()) { + settings.applyConnectionString(new ConnectionString("mongodb://localhost:" + getEmbeddedPort())); + return; + } + if (!this.properties.determineUri().equals(MongoProperties.DEFAULT_URI)) { + if (hasCustomAddress()) { + Assert.state(this.properties.getUri() == null, + "Invalid mongo configuration, either uri or host/port/credentials must be specified"); + } + settings.applyConnectionString(new ConnectionString(this.properties.determineUri())); + } + else 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))); + } + } + + 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 T getOrDefault(T value, T defaultValue) { + return (value != null) ? value : defaultValue; + } + + protected abstract T createNetworkMongoClient(MongoClientSettings settings); + + protected abstract T createEmbeddedMongoClient(MongoClientSettings 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 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; + } + + protected static MongoDriverInformation driverInformation() { + return MongoDriverInformation.builder(MongoDriverInformation.builder().build()).driverName("spring-boot") + .build(); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java index a19b605927e..8f6edc50982 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java @@ -16,7 +16,7 @@ package org.springframework.boot.autoconfigure.mongo; -import com.mongodb.MongoClientURI; +import com.mongodb.ConnectionString; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -178,7 +178,7 @@ public class MongoProperties { if (this.database != null) { return this.database; } - return new MongoClientURI(determineUri()).getDatabase(); + return new ConnectionString(determineUri()).getDatabase(); } public Boolean isAutoIndexCreation() { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java index 24aa30f9424..c706a3aa15c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java @@ -16,136 +16,36 @@ 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}. * * @author Mark Paluch * @author Stephane Nicoll + * @author Christoph Strobl * @since 2.0.0 */ -public class ReactiveMongoClientFactory { - - private final MongoProperties properties; - - private final Environment environment; - - private final List builderCustomizers; +public class ReactiveMongoClientFactory extends MongoClientFactorySupport { public ReactiveMongoClientFactory(MongoProperties properties, Environment environment, List builderCustomizers) { - this.properties = properties; - this.environment = environment; - this.builderCustomizers = (builderCustomizers != null) ? builderCustomizers : Collections.emptyList(); + super(properties, environment, builderCustomizers); } - /** - * 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); + protected MongoClient createNetworkMongoClient(MongoClientSettings settings) { + return MongoClients.create(settings, driverInformation()); } - 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 getOrDefault(T value, T defaultValue) { - return (value != null) ? value : defaultValue; - } - - private MongoClient createMongoClient(Builder builder) { - 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); + @Override + protected MongoClient createEmbeddedMongoClient(MongoClientSettings settings) { + return MongoClients.create(settings, driverInformation()); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfiguration.java index b0fb3f57f26..c887e9d264d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfiguration.java @@ -23,7 +23,7 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; import de.flapdoodle.embed.mongo.Command; import de.flapdoodle.embed.mongo.MongodExecutable; import de.flapdoodle.embed.mongo.MongodStarter; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataAutoConfigurationTests.java index 2e0a80d115b..a9903c6597a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataAutoConfigurationTests.java @@ -20,7 +20,7 @@ import java.time.LocalDateTime; import java.util.Arrays; import java.util.Set; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import org.junit.jupiter.api.Test; @@ -40,10 +40,9 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy; import org.springframework.data.mapping.model.FieldNamingStrategy; import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -171,16 +170,16 @@ class MongoDataAutoConfigurationTests { @Test void createsMongoDbFactoryForPreferredMongoClient() { this.contextRunner.run((context) -> { - MongoDbFactory dbFactory = context.getBean(MongoDbFactory.class); - assertThat(dbFactory).isInstanceOf(SimpleMongoDbFactory.class); + MongoDatabaseFactory dbFactory = context.getBean(MongoDatabaseFactory.class); + assertThat(dbFactory).isInstanceOf(SimpleMongoClientDatabaseFactory.class); }); } @Test void createsMongoDbFactoryForFallbackMongoClient() { this.contextRunner.withUserConfiguration(FallbackMongoClientConfiguration.class).run((context) -> { - MongoDbFactory dbFactory = context.getBean(MongoDbFactory.class); - assertThat(dbFactory).isInstanceOf(SimpleMongoClientDbFactory.class); + MongoDatabaseFactory dbFactory = context.getBean(MongoDatabaseFactory.class); + assertThat(dbFactory).isInstanceOf(SimpleMongoClientDatabaseFactory.class); }); } @@ -226,8 +225,8 @@ class MongoDataAutoConfigurationTests { static class MongoDbFactoryConfiguration { @Bean - MongoDbFactory mongoDbFactory() { - return new SimpleMongoClientDbFactory(MongoClients.create(), "test"); + MongoDatabaseFactory mongoDbFactory() { + return new SimpleMongoClientDatabaseFactory(MongoClients.create(), "test"); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfigurationTests.java index a2efc5b9cb6..469bbc4937f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfigurationTests.java @@ -18,7 +18,7 @@ package org.springframework.boot.autoconfigure.data.mongo; import java.util.Set; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java index 4d64ff2a50f..d431257e4cc 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java @@ -16,10 +16,12 @@ package org.springframework.boot.autoconfigure.mongo; +import java.util.concurrent.TimeUnit; + import javax.net.SocketFactory; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; +import com.mongodb.MongoClientSettings; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import org.junit.jupiter.api.Test; @@ -27,6 +29,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -49,43 +52,44 @@ class MongoAutoConfigurationTests { @Test void optionsAdded() { - this.contextRunner.withUserConfiguration(OptionsConfig.class).run( - (context) -> assertThat(context.getBean(MongoClient.class).getMongoClientOptions().getSocketTimeout()) - .isEqualTo(300)); + this.contextRunner.withUserConfiguration(OptionsConfig.class) + .run((context) -> assertThat(extractClientSettings(context.getBean(MongoClient.class)) + .getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)).isEqualTo(300)); } @Test void optionsAddedButNoHost() { - this.contextRunner.withUserConfiguration(OptionsConfig.class).run( - (context) -> assertThat(context.getBean(MongoClient.class).getMongoClientOptions().getSocketTimeout()) - .isEqualTo(300)); + this.contextRunner.withUserConfiguration(OptionsConfig.class) + .run((context) -> assertThat(extractClientSettings(context.getBean(MongoClient.class)) + .getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)).isEqualTo(300)); } @Test void optionsSslConfig() { this.contextRunner.withUserConfiguration(SslOptionsConfig.class).run((context) -> { assertThat(context).hasSingleBean(MongoClient.class); - MongoClient mongo = context.getBean(MongoClient.class); - MongoClientOptions options = mongo.getMongoClientOptions(); - assertThat(options.isSslEnabled()).isTrue(); - assertThat(options.getSocketFactory()).isSameAs(context.getBean("mySocketFactory")); + MongoClientSettings options = extractClientSettings(context.getBean(MongoClient.class)); + assertThat(options.getSslSettings().isEnabled()).isTrue(); }); } @Test - void doesNotCreateMongoClientWhenAlreadyDefined() { - this.contextRunner.withUserConfiguration(FallbackMongoClientConfig.class).run((context) -> { - assertThat(context).doesNotHaveBean(MongoClient.class); - assertThat(context).hasSingleBean(com.mongodb.client.MongoClient.class); - }); + void configuresSingleClient() { + this.contextRunner.withUserConfiguration(FallbackMongoClientConfig.class) + .run((context) -> assertThat(context).hasSingleBean(MongoClient.class)); + } + + private static MongoClientSettings extractClientSettings(MongoClient client) { + return (MongoClientSettings) ReflectionTestUtils.getField(client, "settings"); } @Configuration(proxyBeanMethods = false) static class OptionsConfig { @Bean - MongoClientOptions mongoOptions() { - return MongoClientOptions.builder().socketTimeout(300).build(); + MongoClientSettings mongoOptions() { + return MongoClientSettings.builder() + .applyToSocketSettings((it) -> it.connectTimeout(300, TimeUnit.MILLISECONDS)).build(); } } @@ -94,8 +98,8 @@ class MongoAutoConfigurationTests { static class SslOptionsConfig { @Bean - MongoClientOptions mongoClientOptions(SocketFactory socketFactory) { - return MongoClientOptions.builder().sslEnabled(true).socketFactory(socketFactory).build(); + MongoClientSettings mongoClientOptions(SocketFactory socketFactory) { + return MongoClientSettings.builder().applyToSslSettings((it) -> it.enabled(true)).build(); } @Bean diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactoryTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactoryTests.java index b5a858d2e75..d15deb60fa1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactoryTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactoryTests.java @@ -16,17 +16,20 @@ package org.springframework.boot.autoconfigure.mongo; +import java.util.Collections; import java.util.List; -import com.mongodb.MongoClient; +import com.mongodb.MongoClientSettings; import com.mongodb.MongoCredential; 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.context.annotation.Configuration; 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; @@ -121,21 +124,22 @@ class MongoClientFactoryTests { } private MongoClient createMongoClient(MongoProperties properties, Environment environment) { - return new MongoClientFactory(properties, environment).createMongoClient(null); + return new MongoClientFactory(properties, environment, Collections.emptyList()).createMongoClient(null); } @SuppressWarnings("deprecation") private List getAllAddresses(MongoClient client) { // At some point we'll probably need to use reflection to find the address but for // now, we can use the deprecated getAllAddress method. - return client.getAllAddress(); + return client.getClusterDescription().getClusterSettings().getHosts(); } @SuppressWarnings("deprecation") private List getCredentials(MongoClient client) { // At some point we'll probably need to use reflection to find the credentials but // for now, we can use the deprecated getCredentialsList method. - return client.getCredentialsList(); + return Collections.singletonList( + ((MongoClientSettings) ReflectionTestUtils.getField(client, "settings")).getCredential()); } private void assertServerAddress(ServerAddress serverAddress, String expectedHost, int expectedPort) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoPropertiesTests.java index a3717838699..5c82b30f4c2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoPropertiesTests.java @@ -16,17 +16,20 @@ package org.springframework.boot.autoconfigure.mongo; +import java.util.Collections; import java.util.List; +import java.util.concurrent.TimeUnit; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; +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; @@ -55,48 +58,43 @@ class MongoPropertiesTests { @Test @SuppressWarnings("deprecation") void allMongoClientOptionsCanBeSet() { - MongoClientOptions.Builder builder = MongoClientOptions.builder(); - builder.alwaysUseMBeans(true); - builder.connectionsPerHost(101); - builder.connectTimeout(10001); - builder.cursorFinalizerEnabled(false); - builder.description("test"); - builder.maxWaitTime(120001); - builder.socketKeepAlive(false); - builder.socketTimeout(1000); - builder.threadsAllowedToBlockForConnectionMultiplier(6); - builder.minConnectionsPerHost(0); - builder.maxConnectionIdleTime(60000); - builder.maxConnectionLifeTime(60000); - builder.heartbeatFrequency(10001); - builder.minHeartbeatFrequency(501); - builder.heartbeatConnectTimeout(20001); - builder.heartbeatSocketTimeout(20001); - builder.localThreshold(20); - builder.requiredReplicaSetName("testReplicaSetName"); - MongoClientOptions options = builder.build(); + 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); + }).applyToClusterSettings((settings) -> settings.requiredReplicaSetName("testReplicaSetName")) + .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 = new MongoClientFactory(properties, null).createMongoClient(options); - MongoClientOptions wrapped = client.getMongoClientOptions(); - assertThat(wrapped.isAlwaysUseMBeans()).isEqualTo(options.isAlwaysUseMBeans()); - assertThat(wrapped.getConnectionsPerHost()).isEqualTo(options.getConnectionsPerHost()); - assertThat(wrapped.getConnectTimeout()).isEqualTo(options.getConnectTimeout()); - assertThat(wrapped.isCursorFinalizerEnabled()).isEqualTo(options.isCursorFinalizerEnabled()); - assertThat(wrapped.getDescription()).isEqualTo(options.getDescription()); - assertThat(wrapped.getMaxWaitTime()).isEqualTo(options.getMaxWaitTime()); - assertThat(wrapped.getSocketTimeout()).isEqualTo(options.getSocketTimeout()); - assertThat(wrapped.isSocketKeepAlive()).isEqualTo(options.isSocketKeepAlive()); - assertThat(wrapped.getThreadsAllowedToBlockForConnectionMultiplier()) - .isEqualTo(options.getThreadsAllowedToBlockForConnectionMultiplier()); - assertThat(wrapped.getMinConnectionsPerHost()).isEqualTo(options.getMinConnectionsPerHost()); - assertThat(wrapped.getMaxConnectionIdleTime()).isEqualTo(options.getMaxConnectionIdleTime()); - assertThat(wrapped.getMaxConnectionLifeTime()).isEqualTo(options.getMaxConnectionLifeTime()); - assertThat(wrapped.getHeartbeatFrequency()).isEqualTo(options.getHeartbeatFrequency()); - assertThat(wrapped.getMinHeartbeatFrequency()).isEqualTo(options.getMinHeartbeatFrequency()); - assertThat(wrapped.getHeartbeatConnectTimeout()).isEqualTo(options.getHeartbeatConnectTimeout()); - assertThat(wrapped.getHeartbeatSocketTimeout()).isEqualTo(options.getHeartbeatSocketTimeout()); - assertThat(wrapped.getLocalThreshold()).isEqualTo(options.getLocalThreshold()); - assertThat(wrapped.getRequiredReplicaSetName()).isEqualTo(options.getRequiredReplicaSetName()); + MongoClient client = new MongoClientFactory(properties, null, Collections.emptyList()) + .createMongoClient(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.getClusterSettings().getRequiredReplicaSetName()) + .isEqualTo(settings.getClusterSettings().getRequiredReplicaSetName()); + 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 @@ -105,7 +103,7 @@ class MongoPropertiesTests { properties.setHost("localhost"); properties.setPort(27017); properties.setUri("mongodb://mongo1.example.com:12345"); - MongoClient client = new MongoClientFactory(properties, null).createMongoClient(null); + MongoClient client = new MongoClientFactory(properties, null, Collections.emptyList()).createMongoClient(null); List allAddresses = getAllAddresses(client); assertThat(allAddresses).hasSize(1); assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345); @@ -116,7 +114,7 @@ class MongoPropertiesTests { MongoProperties properties = new MongoProperties(); properties.setHost("localhost"); properties.setPort(27017); - MongoClient client = new MongoClientFactory(properties, null).createMongoClient(null); + MongoClient client = new MongoClientFactory(properties, null, Collections.emptyList()).createMongoClient(null); List allAddresses = getAllAddresses(client); assertThat(allAddresses).hasSize(1); assertServerAddress(allAddresses.get(0), "localhost", 27017); @@ -126,7 +124,7 @@ class MongoPropertiesTests { void onlyUriSetShouldUseThat() { MongoProperties properties = new MongoProperties(); properties.setUri("mongodb://mongo1.example.com:12345"); - MongoClient client = new MongoClientFactory(properties, null).createMongoClient(null); + MongoClient client = new MongoClientFactory(properties, null, Collections.emptyList()).createMongoClient(null); List allAddresses = getAllAddresses(client); assertThat(allAddresses).hasSize(1); assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345); @@ -135,17 +133,17 @@ class MongoPropertiesTests { @Test void noCustomAddressAndNoUriUsesDefaultUri() { MongoProperties properties = new MongoProperties(); - MongoClient client = new MongoClientFactory(properties, null).createMongoClient(null); + MongoClient client = new MongoClientFactory(properties, null, Collections.emptyList()).createMongoClient(null); List allAddresses = getAllAddresses(client); assertThat(allAddresses).hasSize(1); - assertServerAddress(allAddresses.get(0), "localhost", 27017); + assertServerAddress(allAddresses.get(0), "127.0.0.1", 27017); } @SuppressWarnings("deprecation") private List getAllAddresses(MongoClient client) { // At some point we'll probably need to use reflection to find the address but for // now, we can use the deprecated getAllAddress method. - return client.getAllAddress(); + return client.getClusterDescription().getClusterSettings().getHosts(); } @Test diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java index ee7fd0c2f43..666650d9ff8 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java @@ -25,6 +25,7 @@ import com.mongodb.connection.AsynchronousSocketChannelStreamFactoryFactory; import com.mongodb.connection.StreamFactory; import com.mongodb.connection.StreamFactoryFactory; import com.mongodb.connection.netty.NettyStreamFactoryFactory; +import com.mongodb.internal.async.client.AsyncMongoClient; import com.mongodb.reactivestreams.client.MongoClient; import io.netty.channel.EventLoopGroup; import org.junit.jupiter.api.Test; @@ -113,7 +114,8 @@ class MongoReactiveAutoConfigurationTests { @SuppressWarnings("deprecation") private MongoClientSettings getSettings(ApplicationContext context) { MongoClient client = context.getBean(MongoClient.class); - return (MongoClientSettings) ReflectionTestUtils.getField(client.getSettings(), "wrapped"); + AsyncMongoClient wrappedClient = (AsyncMongoClient) ReflectionTestUtils.getField(client, "wrapped"); + return (MongoClientSettings) ReflectionTestUtils.getField(wrappedClient, "settings"); } @Configuration(proxyBeanMethods = false) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java index aa1d9801fd8..eab5448b9e7 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java @@ -23,6 +23,7 @@ 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.junit.jupiter.api.Test; @@ -117,13 +118,13 @@ class ReactiveMongoClientFactoryTests { } @Test - void uriCannotBeSetWithCredentials() { + void uriCanBeSetWithCredentials() { 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"); + MongoCredential credential = extractMongoCredentials(createMongoClient(properties)); + assertMongoCredential(credential, "user", "secret", "mydb"); } @Test @@ -195,7 +196,8 @@ class ReactiveMongoClientFactoryTests { @SuppressWarnings("deprecation") private MongoClientSettings getSettings(MongoClient client) { - return (MongoClientSettings) ReflectionTestUtils.getField(client.getSettings(), "wrapped"); + AsyncMongoClient wrapped = (AsyncMongoClient) ReflectionTestUtils.getField(client, "wrapped"); + return (MongoClientSettings) ReflectionTestUtils.getField(wrapped, "settings"); } private void assertServerAddress(ServerAddress serverAddress, String expectedHost, int expectedPort) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfigurationTests.java index 7f3cde68c6b..75f897975af 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfigurationTests.java @@ -23,7 +23,8 @@ import java.util.EnumSet; import java.util.Map; import java.util.stream.Collectors; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; import de.flapdoodle.embed.mongo.MongodExecutable; import de.flapdoodle.embed.mongo.MongodStarter; import de.flapdoodle.embed.mongo.config.IMongodConfig; @@ -240,7 +241,7 @@ class EmbeddedMongoAutoConfigurationTests { private int getPort(MongoClient client) { // At some point we'll probably need to use reflection to find the address but for // now, we can use the deprecated getAddress method. - return client.getAddress().getPort(); + return client.getClusterDescription().getClusterSettings().getHosts().iterator().next().getPort(); } @Configuration(proxyBeanMethods = false) @@ -248,7 +249,7 @@ class EmbeddedMongoAutoConfigurationTests { @Bean MongoClient mongoClient(@Value("${local.mongo.port}") int port) { - return new MongoClient("localhost", port); + return MongoClients.create("mongodb://localhost:" + port); } } diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 0819d480569..6127b37cbf3 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1192,21 +1192,14 @@ bom { ] } } - library("Mongo Driver ReactiveStreams", "1.13.0") { - group("org.mongodb") { - modules = [ - "mongodb-driver-reactivestreams" - ] - } - } - library("MongoDB", "3.12.1") { + library("MongoDB", "4.0.0-beta1") { group("org.mongodb") { modules = [ "bson", - "mongodb-driver", + "mongodb-driver-sync", "mongodb-driver-async", "mongodb-driver-core", - "mongo-java-driver" + "mongodb-driver-reactivestreams" ] } } @@ -1601,7 +1594,7 @@ bom { ] } } - library("Spring Data Releasetrain", "Neumann-M2") { + library("Spring Data Releasetrain", "Neumann-BUILD-SNAPSHOT") { group("org.springframework.data") { imports = [ "spring-data-releasetrain" diff --git a/spring-boot-project/spring-boot-starters/spring-boot-starter-data-mongodb-reactive/build.gradle b/spring-boot-project/spring-boot-starters/spring-boot-starter-data-mongodb-reactive/build.gradle index 0f7ab7bc9f2..a2082c11f26 100644 --- a/spring-boot-project/spring-boot-starters/spring-boot-starter-data-mongodb-reactive/build.gradle +++ b/spring-boot-project/spring-boot-starters/spring-boot-starter-data-mongodb-reactive/build.gradle @@ -8,8 +8,7 @@ dependencies { api(platform(project(":spring-boot-project:spring-boot-dependencies"))) api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter")) api("io.projectreactor:reactor-core") - api("org.mongodb:mongodb-driver") - api("org.mongodb:mongodb-driver-async") + api("org.mongodb:mongodb-driver-sync") api("org.mongodb:mongodb-driver-reactivestreams") api("org.springframework.data:spring-data-mongodb") { exclude group: "org.mongodb", module: "mongo-java-driver" diff --git a/spring-boot-project/spring-boot-starters/spring-boot-starter-data-mongodb/build.gradle b/spring-boot-project/spring-boot-starters/spring-boot-starter-data-mongodb/build.gradle index fbe75792123..674119eebf6 100644 --- a/spring-boot-project/spring-boot-starters/spring-boot-starter-data-mongodb/build.gradle +++ b/spring-boot-project/spring-boot-starters/spring-boot-starter-data-mongodb/build.gradle @@ -7,7 +7,7 @@ description = "Starter for using MongoDB document-oriented database and Spring D dependencies { api(platform(project(":spring-boot-project:spring-boot-dependencies"))) api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter")) - api("org.mongodb:mongodb-driver") + api("org.mongodb:mongodb-driver-core") api("org.springframework.data:spring-data-mongodb") { exclude group: "org.mongodb", module: "mongo-java-driver" } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/build.gradle b/spring-boot-project/spring-boot-test-autoconfigure/build.gradle index 21867ae113b..f41566789d9 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-test-autoconfigure/build.gradle @@ -45,7 +45,7 @@ dependencies { optional("org.springframework.security:spring-security-config") optional("org.springframework.security:spring-security-test") optional("org.apache.tomcat.embed:tomcat-embed-core") - optional("org.mongodb:mongodb-driver-async") + optional("org.mongodb:mongodb-driver-sync") optional("org.mongodb:mongodb-driver-reactivestreams") testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))