Harmonize mongo auto-configuration
Provides a way to easily exclude `MongoAutoConfiguration` or `MongoReactiveAutoConfiguration` so that multiple mongo clients are not present. Fixes gh-12407
This commit is contained in:
parent
1ea91ece23
commit
6d9fabf5bc
|
@ -16,30 +16,25 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.data.mongo;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
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.BeanUtils;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
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.domain.EntityScanner;
|
||||
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.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
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.annotation.Persistent;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||
|
@ -48,7 +43,6 @@ 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.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -73,17 +67,15 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ MongoClient.class, MongoTemplate.class })
|
||||
@ConditionalOnBean(MongoClient.class)
|
||||
@EnableConfigurationProperties(MongoProperties.class)
|
||||
@Import(MongoDataConfiguration.class)
|
||||
@AutoConfigureAfter(MongoAutoConfiguration.class)
|
||||
public class MongoDataAutoConfiguration {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
public MongoDataAutoConfiguration(ApplicationContext applicationContext,
|
||||
MongoProperties properties) {
|
||||
this.applicationContext = applicationContext;
|
||||
public MongoDataAutoConfiguration(MongoProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
|
@ -112,22 +104,6 @@ public class MongoDataAutoConfiguration {
|
|||
return mappingConverter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MongoMappingContext mongoMappingContext(MongoCustomConversions conversions)
|
||||
throws ClassNotFoundException {
|
||||
MongoMappingContext context = new MongoMappingContext();
|
||||
context.setInitialEntitySet(new EntityScanner(this.applicationContext)
|
||||
.scan(Document.class, Persistent.class));
|
||||
Class<?> strategyClass = this.properties.getFieldNamingStrategy();
|
||||
if (strategyClass != null) {
|
||||
context.setFieldNamingStrategy(
|
||||
(FieldNamingStrategy) BeanUtils.instantiateClass(strategyClass));
|
||||
}
|
||||
context.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
|
||||
return context;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public GridFsTemplate gridFsTemplate(MongoDbFactory mongoDbFactory,
|
||||
|
@ -137,12 +113,6 @@ public class MongoDataAutoConfiguration {
|
|||
mongoTemplate.getConverter());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MongoCustomConversions mongoCustomConversions() {
|
||||
return new MongoCustomConversions(Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MongoDbFactory} decorator to respect
|
||||
* {@link MongoProperties#getGridFsDatabase()} if set.
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright 2012-2018 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
|
||||
*
|
||||
* http://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 java.util.Collections;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScanner;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
|
||||
/**
|
||||
* Base configuration class for Spring Data's mongo support.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
@Configuration
|
||||
class MongoDataConfiguration {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
MongoDataConfiguration(ApplicationContext applicationContext,
|
||||
MongoProperties properties) {
|
||||
this.applicationContext = applicationContext;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MongoMappingContext mongoMappingContext(MongoCustomConversions conversions)
|
||||
throws ClassNotFoundException {
|
||||
MongoMappingContext context = new MongoMappingContext();
|
||||
context.setInitialEntitySet(new EntityScanner(this.applicationContext)
|
||||
.scan(Document.class, Persistent.class));
|
||||
Class<?> strategyClass = this.properties.getFieldNamingStrategy();
|
||||
if (strategyClass != null) {
|
||||
context.setFieldNamingStrategy(
|
||||
(FieldNamingStrategy) BeanUtils.instantiateClass(strategyClass));
|
||||
}
|
||||
context.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
|
||||
return context;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MongoCustomConversions mongoCustomConversions() {
|
||||
return new MongoCustomConversions(Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
|
@ -20,6 +20,7 @@ import com.mongodb.reactivestreams.client.MongoClient;
|
|||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
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.mongo.MongoProperties;
|
||||
|
@ -27,10 +28,15 @@ import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfigurati
|
|||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
|
||||
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
|
||||
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.convert.NoOpDbRefResolver;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's reactive mongo
|
||||
|
@ -47,9 +53,10 @@ import org.springframework.data.mongodb.core.convert.MongoConverter;
|
|||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ MongoClient.class, ReactiveMongoTemplate.class })
|
||||
@ConditionalOnBean(MongoClient.class)
|
||||
@EnableConfigurationProperties(MongoProperties.class)
|
||||
@AutoConfigureAfter({ MongoReactiveAutoConfiguration.class,
|
||||
MongoDataAutoConfiguration.class })
|
||||
@Import(MongoDataConfiguration.class)
|
||||
@AutoConfigureAfter(MongoReactiveAutoConfiguration.class)
|
||||
public class MongoReactiveDataAutoConfiguration {
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
@ -74,4 +81,14 @@ public class MongoReactiveDataAutoConfiguration {
|
|||
return new ReactiveMongoTemplate(reactiveMongoDatabaseFactory, converter);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MongoConverter.class)
|
||||
public MappingMongoConverter mappingMongoConverter(MongoMappingContext context,
|
||||
MongoCustomConversions conversions) {
|
||||
MappingMongoConverter mappingConverter = new MappingMongoConverter(
|
||||
NoOpDbRefResolver.INSTANCE, context);
|
||||
mappingConverter.setCustomConversions(conversions);
|
||||
return mappingConverter;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import com.mongodb.async.client.MongoClientSettings;
|
|||
import com.mongodb.connection.netty.NettyStreamFactoryFactory;
|
||||
import com.mongodb.reactivestreams.client.MongoClient;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
|
@ -44,7 +45,7 @@ import org.springframework.core.env.Environment;
|
|||
* @since 2.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(MongoClient.class)
|
||||
@ConditionalOnClass({ MongoClient.class, Flux.class })
|
||||
@EnableConfigurationProperties(MongoProperties.class)
|
||||
public class MongoReactiveAutoConfiguration {
|
||||
|
||||
|
|
|
@ -22,9 +22,12 @@ import java.util.Set;
|
|||
|
||||
import com.mongodb.MongoClient;
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.mongo.city.City;
|
||||
|
@ -60,6 +63,9 @@ public class MongoDataAutoConfigurationTests {
|
|||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (this.context != null) {
|
||||
|
@ -162,6 +168,15 @@ public class MongoDataAutoConfigurationTests {
|
|||
assertThat(dateProperty.isEntity()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backsOffIfMongoClientBeanIsNotPresent() {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.register(MongoDataAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
this.thrown.expect(NoSuchBeanDefinitionException.class);
|
||||
assertThat(this.context.getBean(MongoDataAutoConfiguration.class)).isNull();
|
||||
}
|
||||
|
||||
public void testFieldNamingStrategy(String strategy,
|
||||
Class<? extends FieldNamingStrategy> expectedType) {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
package org.springframework.boot.autoconfigure.data.mongo;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
|
||||
|
@ -36,6 +38,9 @@ public class MongoReactiveDataAutoConfigurationTests {
|
|||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (this.context != null) {
|
||||
|
@ -46,11 +51,20 @@ public class MongoReactiveDataAutoConfigurationTests {
|
|||
@Test
|
||||
public void templateExists() {
|
||||
this.context = new AnnotationConfigApplicationContext(
|
||||
PropertyPlaceholderAutoConfiguration.class, MongoAutoConfiguration.class,
|
||||
MongoDataAutoConfiguration.class, MongoReactiveAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
MongoReactiveAutoConfiguration.class,
|
||||
MongoReactiveDataAutoConfiguration.class);
|
||||
assertThat(this.context.getBeanNamesForType(ReactiveMongoTemplate.class))
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backsOffIfMongoClientBeanIsNotPresent() {
|
||||
this.context = new AnnotationConfigApplicationContext(
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
MongoReactiveDataAutoConfiguration.class);
|
||||
this.thrown.expect(NoSuchBeanDefinitionException.class);
|
||||
this.context.getBean(MongoReactiveDataAutoConfiguration.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue