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 f07e2cadfc..353e8fe84b 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 @@ -16,7 +16,15 @@ package org.springframework.boot.autoconfigure.data.mongo; +import java.util.Optional; + +import com.mongodb.ClientSessionOptions; +import com.mongodb.reactivestreams.client.ClientSession; import com.mongodb.reactivestreams.client.MongoClient; +import com.mongodb.reactivestreams.client.MongoDatabase; +import org.bson.codecs.Codec; +import org.bson.codecs.configuration.CodecRegistry; +import reactor.core.publisher.Mono; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -31,6 +39,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DefaultDataBufferFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; @@ -42,6 +52,7 @@ import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.gridfs.ReactiveGridFsOperations; import org.springframework.data.mongodb.gridfs.ReactiveGridFsTemplate; +import org.springframework.util.StringUtils; /** * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's reactive mongo @@ -98,8 +109,77 @@ public class MongoReactiveDataAutoConfiguration { @Bean @ConditionalOnMissingBean(ReactiveGridFsOperations.class) public ReactiveGridFsTemplate reactiveGridFsTemplate(ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory, - MappingMongoConverter mappingMongoConverter, DataBufferFactory dataBufferFactory) { - return new ReactiveGridFsTemplate(dataBufferFactory, reactiveMongoDatabaseFactory, mappingMongoConverter, null); + MappingMongoConverter mappingMongoConverter, DataBufferFactory dataBufferFactory, + MongoProperties properties) { + return new ReactiveGridFsTemplate(dataBufferFactory, + new GridFsReactiveMongoDatabaseFactory(reactiveMongoDatabaseFactory, properties), mappingMongoConverter, + null); + } + + /** + * {@link ReactiveMongoDatabaseFactory} decorator to use + * {@link MongoProperties#getGridFsDatabase()} when set. + */ + static class GridFsReactiveMongoDatabaseFactory implements ReactiveMongoDatabaseFactory { + + private final ReactiveMongoDatabaseFactory delegate; + + private final MongoProperties properties; + + GridFsReactiveMongoDatabaseFactory(ReactiveMongoDatabaseFactory delegate, MongoProperties properties) { + this.delegate = delegate; + this.properties = properties; + } + + @Override + public boolean hasCodecFor(Class type) { + return this.delegate.hasCodecFor(type); + } + + @Override + public Mono getMongoDatabase() throws DataAccessException { + String gridFsDatabase = this.properties.getGridFsDatabase(); + if (StringUtils.hasText(gridFsDatabase)) { + return this.delegate.getMongoDatabase(gridFsDatabase); + } + return this.delegate.getMongoDatabase(); + } + + @Override + public Mono getMongoDatabase(String dbName) throws DataAccessException { + return this.delegate.getMongoDatabase(dbName); + } + + @Override + public Optional> getCodecFor(Class type) { + return this.delegate.getCodecFor(type); + } + + @Override + public PersistenceExceptionTranslator getExceptionTranslator() { + return this.delegate.getExceptionTranslator(); + } + + @Override + public CodecRegistry getCodecRegistry() { + return this.delegate.getCodecRegistry(); + } + + @Override + public Mono getSession(ClientSessionOptions options) { + return this.delegate.getSession(options); + } + + @Override + public ReactiveMongoDatabaseFactory withSession(ClientSession session) { + return this.delegate.withSession(session); + } + + @Override + public boolean isTransactionActive() { + return this.delegate.isTransactionActive(); + } + } } 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 2d88d81150..de2c3fe586 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -21,9 +21,12 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; +import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.gridfs.ReactiveGridFsTemplate; +import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -45,8 +48,17 @@ class MongoReactiveDataAutoConfigurationTests { } @Test - void gridFsTemplateExists() { - this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ReactiveGridFsTemplate.class)); + void whenNoGridFsDatabaseIsConfiguredTheGridFsTemplateUsesTheMainDatabase() { + this.contextRunner.run((context) -> { + assertThat(grisFsTemplateDatabaseName(context)).isEqualTo("test"); + }); + } + + @Test + void whenGridFsDatabaseIsConfiguredThenGridFsTemplateUsesIt() { + this.contextRunner.withPropertyValues("spring.data.mongodb.gridFsDatabase:grid").run((context) -> { + assertThat(grisFsTemplateDatabaseName(context)).isEqualTo("grid"); + }); } @Test @@ -56,4 +68,12 @@ class MongoReactiveDataAutoConfigurationTests { runner.run((context) -> assertThat(context).doesNotHaveBean(MongoReactiveDataAutoConfiguration.class)); } + private String grisFsTemplateDatabaseName(AssertableApplicationContext context) { + assertThat(context).hasSingleBean(ReactiveGridFsTemplate.class); + ReactiveGridFsTemplate template = context.getBean(ReactiveGridFsTemplate.class); + ReactiveMongoDatabaseFactory factory = (ReactiveMongoDatabaseFactory) ReflectionTestUtils.getField(template, + "dbFactory"); + return factory.getMongoDatabase().block().getName(); + } + }