commit
2af815f2cf
|
|
@ -16,43 +16,18 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.data.mongo;
|
||||
|
||||
import com.mongodb.ClientSessionOptions;
|
||||
import com.mongodb.DB;
|
||||
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;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's mongo support.
|
||||
|
|
@ -74,131 +49,9 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ MongoClient.class, com.mongodb.client.MongoClient.class, MongoTemplate.class })
|
||||
@Conditional(AnyMongoClientAvailable.class)
|
||||
@EnableConfigurationProperties(MongoProperties.class)
|
||||
@Import(MongoDataConfiguration.class)
|
||||
@Import({ MongoDataConfiguration.class, MongoDbFactoryConfiguration.class, MongoDbFactoryDependentConfiguration.class })
|
||||
@AutoConfigureAfter(MongoAutoConfiguration.class)
|
||||
public class MongoDataAutoConfiguration {
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
public MongoDataAutoConfiguration(MongoProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MongoDbFactory.class)
|
||||
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
|
||||
@ConditionalOnMissingBean
|
||||
public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter converter) {
|
||||
return new MongoTemplate(mongoDbFactory, converter);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MongoConverter.class)
|
||||
public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context,
|
||||
MongoCustomConversions conversions) {
|
||||
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
|
||||
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
|
||||
mappingConverter.setCustomConversions(conversions);
|
||||
return mappingConverter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public GridFsTemplate gridFsTemplate(MongoDbFactory mongoDbFactory, MongoTemplate mongoTemplate) {
|
||||
return new GridFsTemplate(new GridFsMongoDbFactory(mongoDbFactory, this.properties),
|
||||
mongoTemplate.getConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MongoDbFactory} decorator to respect
|
||||
* {@link MongoProperties#getGridFsDatabase()} if set.
|
||||
*/
|
||||
private static class GridFsMongoDbFactory implements MongoDbFactory {
|
||||
|
||||
private final MongoDbFactory mongoDbFactory;
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
GridFsMongoDbFactory(MongoDbFactory mongoDbFactory, MongoProperties properties) {
|
||||
Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null");
|
||||
Assert.notNull(properties, "Properties must not be null");
|
||||
this.mongoDbFactory = mongoDbFactory;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoDatabase getDb() throws DataAccessException {
|
||||
String gridFsDatabase = this.properties.getGridFsDatabase();
|
||||
if (StringUtils.hasText(gridFsDatabase)) {
|
||||
return this.mongoDbFactory.getDb(gridFsDatabase);
|
||||
}
|
||||
return this.mongoDbFactory.getDb();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoDatabase getDb(String dbName) throws DataAccessException {
|
||||
return this.mongoDbFactory.getDb(dbName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceExceptionTranslator getExceptionTranslator() {
|
||||
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) {
|
||||
return this.mongoDbFactory.withSession(session);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if either a {@link MongoClient com.mongodb.MongoClient} or
|
||||
* {@link com.mongodb.client.MongoClient 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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2012-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.data.mongo;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.data.mongo.MongoDbFactoryConfiguration.AnyMongoClientAvailable;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Configuration for a {@link MongoDbFactory}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingBean(MongoDbFactory.class)
|
||||
@Conditional(AnyMongoClientAvailable.class)
|
||||
class MongoDbFactoryConfiguration {
|
||||
|
||||
@Bean
|
||||
MongoDbFactorySupport<?> mongoDbFactory(ObjectProvider<MongoClient> mongo,
|
||||
ObjectProvider<com.mongodb.client.MongoClient> mongoClient, MongoProperties properties) {
|
||||
MongoClient preferredClient = mongo.getIfAvailable();
|
||||
if (preferredClient != null) {
|
||||
return new SimpleMongoDbFactory(preferredClient, properties.getMongoClientDatabase());
|
||||
}
|
||||
com.mongodb.client.MongoClient fallbackClient = mongoClient.getIfAvailable();
|
||||
if (fallbackClient != null) {
|
||||
return new SimpleMongoClientDbFactory(fallbackClient, properties.getMongoClientDatabase());
|
||||
}
|
||||
throw new IllegalStateException("Expected to find at least one MongoDB client.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if either a {@link MongoClient com.mongodb.MongoClient} or
|
||||
* {@link com.mongodb.client.MongoClient 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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright 2012-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.data.mongo;
|
||||
|
||||
import com.mongodb.ClientSessionOptions;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.client.ClientSession;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
|
||||
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.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.convert.DbRefResolver;
|
||||
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Configuration for Mongo-related beans that depend on a {@link MongoDbFactory}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnBean(MongoDbFactory.class)
|
||||
class MongoDbFactoryDependentConfiguration {
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
MongoDbFactoryDependentConfiguration(MongoProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter converter) {
|
||||
return new MongoTemplate(mongoDbFactory, converter);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MongoConverter.class)
|
||||
MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context,
|
||||
MongoCustomConversions conversions) {
|
||||
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
|
||||
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
|
||||
mappingConverter.setCustomConversions(conversions);
|
||||
return mappingConverter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
GridFsTemplate gridFsTemplate(MongoDbFactory mongoDbFactory, MongoTemplate mongoTemplate) {
|
||||
return new GridFsTemplate(new GridFsMongoDbFactory(mongoDbFactory, this.properties),
|
||||
mongoTemplate.getConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MongoDbFactory} decorator to respect
|
||||
* {@link MongoProperties#getGridFsDatabase()} if set.
|
||||
*/
|
||||
static class GridFsMongoDbFactory implements MongoDbFactory {
|
||||
|
||||
private final MongoDbFactory mongoDbFactory;
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
GridFsMongoDbFactory(MongoDbFactory mongoDbFactory, MongoProperties properties) {
|
||||
Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null");
|
||||
Assert.notNull(properties, "Properties must not be null");
|
||||
this.mongoDbFactory = mongoDbFactory;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoDatabase getDb() throws DataAccessException {
|
||||
String gridFsDatabase = this.properties.getGridFsDatabase();
|
||||
if (StringUtils.hasText(gridFsDatabase)) {
|
||||
return this.mongoDbFactory.getDb(gridFsDatabase);
|
||||
}
|
||||
return this.mongoDbFactory.getDb();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoDatabase getDb(String dbName) throws DataAccessException {
|
||||
return this.mongoDbFactory.getDb(dbName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceExceptionTranslator getExceptionTranslator() {
|
||||
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) {
|
||||
return this.mongoDbFactory.withSession(session);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -31,7 +31,9 @@ import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoCon
|
|||
import org.springframework.boot.autoconfigure.data.mongo.city.City;
|
||||
import org.springframework.boot.autoconfigure.data.mongo.country.Country;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
|
@ -63,7 +65,8 @@ class MongoDataAutoConfigurationTests {
|
|||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class,
|
||||
MongoAutoConfiguration.class, MongoDataAutoConfiguration.class));
|
||||
MongoAutoConfiguration.class, MongoDataAutoConfiguration.class))
|
||||
.withInitializer(new ConditionEvaluationReportLoggingListener(LogLevel.INFO));
|
||||
|
||||
@Test
|
||||
void templateExists() {
|
||||
|
|
@ -165,7 +168,7 @@ class MongoDataAutoConfigurationTests {
|
|||
void backsOffIfMongoClientBeanIsNotPresent() {
|
||||
ApplicationContextRunner runner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(MongoDataAutoConfiguration.class));
|
||||
runner.run((context) -> assertThat(context).doesNotHaveBean(MongoDataAutoConfiguration.class));
|
||||
runner.run((context) -> assertThat(context).doesNotHaveBean(MongoTemplate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -184,6 +187,12 @@ class MongoDataAutoConfigurationTests {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfiguresIfUserProvidesMongoDbFactoryButNoClient() {
|
||||
this.contextRunner.withUserConfiguration(MongoDbFactoryConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(MongoTemplate.class));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private static void assertDomainTypesDiscovered(MongoMappingContext mappingContext, Class<?>... types) {
|
||||
Set<Class> initialEntitySet = (Set<Class>) ReflectionTestUtils.getField(mappingContext, "initialEntitySet");
|
||||
|
|
@ -216,6 +225,16 @@ class MongoDataAutoConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class MongoDbFactoryConfiguration {
|
||||
|
||||
@Bean
|
||||
MongoDbFactory mongoDbFactory() {
|
||||
return new SimpleMongoClientDbFactory(MongoClients.create(), "test");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class MyConverter implements Converter<MongoClient, Boolean> {
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in New Issue