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 63c2ad1fe9..9ff49965b9 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,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. diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataConfiguration.java new file mode 100644 index 0000000000..a10af3a1ab --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataConfiguration.java @@ -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()); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfiguration.java index de16566c56..560747eee3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfiguration.java @@ -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; + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfiguration.java index 5e03c05809..de8ff484c6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfiguration.java @@ -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 { 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 6fc852fd26..0080a6f64d 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 @@ -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 expectedType) { this.context = new AnnotationConfigApplicationContext(); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfigurationTests.java index f207ab8531..b201360e1e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/MongoReactiveDataAutoConfigurationTests.java @@ -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); + } + }