Polish "Add support for com.mongodb.client.MongoClient"

Closes gh-14176
This commit is contained in:
Stephane Nicoll
2018-08-28 15:24:31 +02:00
parent d549e6001a
commit 56329e67d7
4 changed files with 49 additions and 101 deletions

View File

@@ -16,9 +16,6 @@
package org.springframework.boot.autoconfigure.data.mongo;
import java.util.Arrays;
import java.util.List;
import com.mongodb.ClientSessionOptions;
import com.mongodb.DB;
import com.mongodb.MongoClient;
@@ -32,7 +29,7 @@ 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.AnySyncMongoClientAvailable;
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;
@@ -43,6 +40,7 @@ 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;
@@ -75,8 +73,9 @@ import org.springframework.util.StringUtils;
* @since 1.1.0
*/
@Configuration
@ConditionalOnClass({ MongoClient.class, MongoTemplate.class })
@Conditional(AnySyncMongoClientAvailable.class)
@ConditionalOnClass({ MongoClient.class, com.mongodb.client.MongoClient.class,
MongoTemplate.class })
@Conditional(AnyMongoClientAvailable.class)
@EnableConfigurationProperties(MongoProperties.class)
@Import(MongoDataConfiguration.class)
@AutoConfigureAfter(MongoAutoConfiguration.class)
@@ -84,22 +83,25 @@ public class MongoDataAutoConfiguration {
private final MongoProperties properties;
private final MongoDbFactoryFactory dbFactoryFactory;
public MongoDataAutoConfiguration(ObjectProvider<MongoClient> mongoClientProvider,
ObjectProvider<com.mongodb.client.MongoClient> mongoClientClientProvider,
MongoProperties properties) {
public MongoDataAutoConfiguration(MongoProperties properties) {
this.properties = properties;
this.dbFactoryFactory = new MongoDbFactoryFactory(mongoClientProvider,
mongoClientClientProvider);
}
@Bean
@Conditional(AnySyncMongoClientAvailable.class)
@ConditionalOnMissingBean(MongoDbFactory.class)
public MongoDbFactory mongoDbFactory() {
return this.dbFactoryFactory.getFor(this.properties.getMongoClientDatabase());
public MongoDbFactorySupport<?> mongoDbFactory(ObjectProvider<MongoClient> mongo,
ObjectProvider<com.mongodb.client.MongoClient> 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
@@ -183,89 +185,25 @@ public class MongoDataAutoConfiguration {
}
/**
* Check if either {@link com.mongodb.MongoClient} or
* {@link com.mongodb.client.MongoClient} is already defined in the
* {@link org.springframework.context.ApplicationContext}.
*
* @author Christoph Strobl
* @since 2.1
* Check if either a {@link com.mongodb.MongoClient} or
* {@link com.mongodb.client.MongoClient} bean is available.
*/
static class AnySyncMongoClientAvailable extends AnyNestedCondition {
static class AnyMongoClientAvailable extends AnyNestedCondition {
AnySyncMongoClientAvailable() {
AnyMongoClientAvailable() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnBean(com.mongodb.MongoClient.class)
static class MongoClientPreferred {
@ConditionalOnBean(MongoClient.class)
static class PreferredClientAvailable {
}
@ConditionalOnBean(com.mongodb.client.MongoClient.class)
static class MongoClientClientPreferred {
static class FallbackClientAvailable {
}
}
/**
* Encapsulation of {@link MongoDbFactory} creation depending on available beans
* {@link com.mongodb.MongoClient} or {@link com.mongodb.client.MongoClient} expressed
* via the given {@link ObjectProvider ObjectProviders}. Prefers the first available
* MongoDB client creating a suitable instance of {@link MongoDbFactory} for it.
*
* @author Christoph Strobl
* @since 2.1
*/
static class MongoDbFactoryFactory {
private final List<ObjectProvider<?>> clientProviders;
/**
* Create new instance of {@link MongoDbFactoryFactory}.
* @param clientProviders order matters here, as we choose the first available
* one.
*/
MongoDbFactoryFactory(ObjectProvider<?>... clientProviders) {
this.clientProviders = Arrays.asList(clientProviders);
}
/**
* Get the {@link MongoDbFactory} suitable for the first available MongoDB client.
* @param database the name of the default database to return on
* {@link MongoDbFactory#getDb()}.
* @return new instance of {@link MongoDbFactory} suitable for the first available
* MongoDB client.
*/
MongoDbFactory getFor(String database) {
Object client = findAvailableClientProvider();
if (client instanceof MongoClient) {
return new SimpleMongoDbFactory(MongoClient.class.cast(client), database);
}
if (client instanceof com.mongodb.client.MongoClient) {
return new SimpleMongoClientDbFactory(
com.mongodb.client.MongoClient.class.cast(client), database);
}
return null;
}
private Object findAvailableClientProvider() {
for (ObjectProvider<?> provider : this.clientProviders) {
Object client = provider.getIfAvailable();
if (client != null) {
return client;
}
}
throw new IllegalStateException(
"Expected to find at least one MongoDB client.");
}
}
}

View File

@@ -43,6 +43,7 @@ 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;
@@ -177,9 +178,16 @@ public class MongoDataAutoConfigurationTests {
}
@Test
public void createsMongoDbFactoryForMongoClientClientWhenBeanPresent() {
public void createsMongoDbFactoryForPreferredMongoClient() {
this.contextRunner.run((context) -> {
MongoDbFactory dbFactory = context.getBean(MongoDbFactory.class);
assertThat(dbFactory).isInstanceOf(SimpleMongoDbFactory.class);
});
}
this.contextRunner.withUserConfiguration(WithMongoClientClientConfiguration.class)
@Test
public void createsMongoDbFactoryForFallbackMongoClient() {
this.contextRunner.withUserConfiguration(FallbackMongoClientConfiguration.class)
.run((context) -> {
MongoDbFactory dbFactory = context.getBean(MongoDbFactory.class);
assertThat(dbFactory).isInstanceOf(SimpleMongoClientDbFactory.class);
@@ -211,10 +219,10 @@ public class MongoDataAutoConfigurationTests {
}
@Configuration
static class WithMongoClientClientConfiguration {
static class FallbackMongoClientConfiguration {
@Bean
com.mongodb.client.MongoClient mongoClient() {
com.mongodb.client.MongoClient fallbackMongoClient() {
return MongoClients.create();
}

View File

@@ -23,14 +23,12 @@ import com.mongodb.MongoClientOptions;
import com.mongodb.client.MongoClients;
import org.junit.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
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 static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.Mockito.mock;
/**
@@ -83,13 +81,13 @@ public class MongoAutoConfigurationTests {
@Test
public void doesNotCreateMongoClientWhenAlreadyDefined() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.uri:mongodb://localhost/test")
.withUserConfiguration(ConfigurationWithClientMongoClient.class)
.run((context) -> assertThatExceptionOfType(
NoSuchBeanDefinitionException.class)
.isThrownBy(() -> context.getBean(MongoClient.class)));
.withUserConfiguration(FallbackMongoClientConfig.class).run((context) -> {
assertThat(context).doesNotHaveBean(MongoClient.class);
assertThat(context)
.hasSingleBean(com.mongodb.client.MongoClient.class);
});
}
@Configuration
@@ -118,10 +116,10 @@ public class MongoAutoConfigurationTests {
}
static class ConfigurationWithClientMongoClient {
static class FallbackMongoClientConfig {
@Bean
com.mongodb.client.MongoClient mongoClient() {
com.mongodb.client.MongoClient fallbackMongoClient() {
return MongoClients.create();
}

View File

@@ -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.