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 9ff49965b9..cfbe4b1b7a 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 @@ -22,21 +22,27 @@ import com.mongodb.MongoClient; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoDatabase; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration.AnyMongoClientAvailable; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.MongoDbFactorySupport; 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.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; @@ -63,11 +69,13 @@ import org.springframework.util.StringUtils; * @author Phillip Webb * @author EddĂș MelĂ©ndez * @author Stephane Nicoll + * @author Christoph Strobl * @since 1.1.0 */ @Configuration -@ConditionalOnClass({ MongoClient.class, MongoTemplate.class }) -@ConditionalOnBean(MongoClient.class) +@ConditionalOnClass({ MongoClient.class, com.mongodb.client.MongoClient.class, + MongoTemplate.class }) +@Conditional(AnyMongoClientAvailable.class) @EnableConfigurationProperties(MongoProperties.class) @Import(MongoDataConfiguration.class) @AutoConfigureAfter(MongoAutoConfiguration.class) @@ -81,9 +89,19 @@ public class MongoDataAutoConfiguration { @Bean @ConditionalOnMissingBean(MongoDbFactory.class) - public SimpleMongoDbFactory mongoDbFactory(MongoClient mongo) { - String database = this.properties.getMongoClientDatabase(); - return new SimpleMongoDbFactory(mongo, database); + public MongoDbFactorySupport mongoDbFactory(ObjectProvider mongo, + ObjectProvider mongoClient) { + MongoClient preferredClient = mongo.getIfAvailable(); + if (preferredClient != null) { + return new SimpleMongoDbFactory(preferredClient, + this.properties.getMongoClientDatabase()); + } + com.mongodb.client.MongoClient fallbackClient = mongoClient.getIfAvailable(); + if (fallbackClient != null) { + return new SimpleMongoClientDbFactory(fallbackClient, + this.properties.getMongoClientDatabase()); + } + throw new IllegalStateException("Expected to find at least one MongoDB client."); } @Bean @@ -166,4 +184,26 @@ public class MongoDataAutoConfiguration { } + /** + * Check if either a {@link com.mongodb.MongoClient} or + * {@link com.mongodb.client.MongoClient} bean is available. + */ + static class AnyMongoClientAvailable extends AnyNestedCondition { + + AnyMongoClientAvailable() { + super(ConfigurationPhase.REGISTER_BEAN); + } + + @ConditionalOnBean(MongoClient.class) + static class PreferredClientAvailable { + + } + + @ConditionalOnBean(com.mongodb.client.MongoClient.class) + static class FallbackClientAvailable { + + } + + } + } 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 659f709aa4..f93a7edb36 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 @@ -65,7 +65,8 @@ public class MongoAutoConfiguration { } @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingBean(type = { "com.mongodb.MongoClient", + "com.mongodb.client.MongoClient" }) public MongoClient mongo() { this.mongo = this.factory.createMongoClient(this.options); return this.mongo; 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 74ba12f9f9..432f99c3db 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 @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.Set; import com.mongodb.MongoClient; +import com.mongodb.client.MongoClients; import org.junit.Test; import org.springframework.beans.factory.BeanCreationException; @@ -39,7 +40,10 @@ 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.core.MongoTemplate; +import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoDbFactory; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -173,6 +177,23 @@ public class MongoDataAutoConfigurationTests { .doesNotHaveBean(MongoDataAutoConfiguration.class)); } + @Test + public void createsMongoDbFactoryForPreferredMongoClient() { + this.contextRunner.run((context) -> { + MongoDbFactory dbFactory = context.getBean(MongoDbFactory.class); + assertThat(dbFactory).isInstanceOf(SimpleMongoDbFactory.class); + }); + } + + @Test + public void createsMongoDbFactoryForFallbackMongoClient() { + this.contextRunner.withUserConfiguration(FallbackMongoClientConfiguration.class) + .run((context) -> { + MongoDbFactory dbFactory = context.getBean(MongoDbFactory.class); + assertThat(dbFactory).isInstanceOf(SimpleMongoClientDbFactory.class); + }); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) private static void assertDomainTypesDiscovered(MongoMappingContext mappingContext, Class... types) { @@ -197,6 +218,16 @@ public class MongoDataAutoConfigurationTests { } + @Configuration + static class FallbackMongoClientConfiguration { + + @Bean + com.mongodb.client.MongoClient fallbackMongoClient() { + return MongoClients.create(); + } + + } + private static class MyConverter implements Converter { @Override 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 884ccd8331..b86757f853 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 @@ -20,6 +20,7 @@ import javax.net.SocketFactory; import com.mongodb.MongoClient; import com.mongodb.MongoClientOptions; +import com.mongodb.client.MongoClients; import org.junit.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -78,6 +79,17 @@ public class MongoAutoConfigurationTests { }); } + @Test + public void doesNotCreateMongoClientWhenAlreadyDefined() { + this.contextRunner + .withPropertyValues("spring.data.mongodb.uri:mongodb://localhost/test") + .withUserConfiguration(FallbackMongoClientConfig.class).run((context) -> { + assertThat(context).doesNotHaveBean(MongoClient.class); + assertThat(context) + .hasSingleBean(com.mongodb.client.MongoClient.class); + }); + } + @Configuration static class OptionsConfig { @@ -104,4 +116,13 @@ public class MongoAutoConfigurationTests { } + static class FallbackMongoClientConfig { + + @Bean + com.mongodb.client.MongoClient fallbackMongoClient() { + return MongoClients.create(); + } + + } + } diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 9b2cd91524..38bbfe6e58 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -4029,6 +4029,10 @@ example, you might declare the following settings in your `application.propertie spring.data.mongodb.port=27017 ---- +If you have defined your own `MongoClient`, it will be used to auto-configure a suitable +`MongoDbFactory`. Both `com.mongodb.MongoClient` and `com.mongodb.client.MongoClient` +are supported. + NOTE: If you use the Mongo 3.0 Java driver, `spring.data.mongodb.host` and `spring.data.mongodb.port` are not supported. In such cases, `spring.data.mongodb.uri` should be used to provide all of the configuration.