From a8948790854796789a4087739ed7199a43a0300c Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 21 May 2024 09:14:42 +0100 Subject: [PATCH] Use DefaultDbRefResolver whenever MongoDatabaseFactory is available Fixes gh-39405 --- .../data/mongo/MongoDataConfiguration.java | 21 ++++++++++++++++++- ...DatabaseFactoryDependentConfiguration.java | 17 +-------------- .../MongoReactiveDataAutoConfiguration.java | 14 +------------ .../MongoDataAutoConfigurationTests.java | 12 ++++++++++- ...ngoReactiveDataAutoConfigurationTests.java | 12 ++++++++++- 5 files changed, 44 insertions(+), 32 deletions(-) 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 index 898b4bc7e9a..f11e0c6f20f 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.data.mongo; import java.util.Collections; import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.domain.EntityScanner; import org.springframework.boot.autoconfigure.mongo.MongoProperties; @@ -27,8 +28,14 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mapping.model.FieldNamingStrategy; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoManagedTypes; +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.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -70,4 +77,16 @@ class MongoDataConfiguration { return new MongoCustomConversions(Collections.emptyList()); } + @Bean + @ConditionalOnMissingBean(MongoConverter.class) + MappingMongoConverter mappingMongoConverter(ObjectProvider factory, + MongoMappingContext context, MongoCustomConversions conversions) { + MongoDatabaseFactory mongoDatabaseFactory = factory.getIfAvailable(); + DbRefResolver dbRefResolver = (mongoDatabaseFactory != null) ? new DefaultDbRefResolver(mongoDatabaseFactory) + : NoOpDbRefResolver.INSTANCE; + MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context); + mappingConverter.setCustomConversions(conversions); + return mappingConverter; + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDatabaseFactoryDependentConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDatabaseFactoryDependentConfiguration.java index 77ed0c6dc48..ba0f6a1a95f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDatabaseFactoryDependentConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDatabaseFactoryDependentConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -33,12 +33,7 @@ import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoOperations; 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.GridFsOperations; import org.springframework.data.mongodb.gridfs.GridFsTemplate; import org.springframework.util.Assert; @@ -61,16 +56,6 @@ class MongoDatabaseFactoryDependentConfiguration { return new MongoTemplate(factory, converter); } - @Bean - @ConditionalOnMissingBean(MongoConverter.class) - MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory factory, MongoMappingContext context, - MongoCustomConversions conversions) { - DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); - MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context); - mappingConverter.setCustomConversions(conversions); - return mappingConverter; - } - @Bean @ConditionalOnMissingBean(GridFsOperations.class) GridFsTemplate gridFsTemplate(MongoProperties properties, MongoDatabaseFactory factory, MongoTemplate mongoTemplate, 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 ecdf179b611..4b3c71f82e0 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -48,9 +48,6 @@ 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; import org.springframework.data.mongodb.gridfs.ReactiveGridFsOperations; import org.springframework.data.mongodb.gridfs.ReactiveGridFsTemplate; import org.springframework.util.StringUtils; @@ -101,15 +98,6 @@ 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; - } - @Bean @ConditionalOnMissingBean(DataBufferFactory.class) public DefaultDataBufferFactory dataBufferFactory() { 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 caff745e56f..77a4b149747 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -50,6 +50,8 @@ import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; @@ -319,6 +321,14 @@ class MongoDataAutoConfigurationTests { .doesNotHaveBean(PropertiesMongoConnectionDetails.class)); } + @Test + void mappingMongoConverterHasADefaultDbRefResolver() { + this.contextRunner.run((context) -> { + MappingMongoConverter converter = context.getBean(MappingMongoConverter.class); + assertThat(converter).extracting("dbRefResolver").isInstanceOf(DefaultDbRefResolver.class); + }); + } + private static void assertDomainTypesDiscovered(MongoMappingContext mappingContext, Class... types) { ManagedTypes managedTypes = (ManagedTypes) ReflectionTestUtils.getField(mappingContext, "managedTypes"); assertThat(managedTypes.toList()).containsOnly(types); 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 a64fe5b7031..7f72ac71823 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-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -35,6 +35,8 @@ import org.springframework.context.annotation.Configuration; 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.NoOpDbRefResolver; import org.springframework.data.mongodb.gridfs.ReactiveGridFsTemplate; import org.springframework.test.util.ReflectionTestUtils; @@ -161,6 +163,14 @@ class MongoReactiveDataAutoConfigurationTests { .run((context) -> assertThat(context).getFailure().hasMessageContaining("Database name must not be empty")); } + @Test + void mappingMongoConverterHasANoOpDbRefResolver() { + this.contextRunner.run((context) -> { + MappingMongoConverter converter = context.getBean(MappingMongoConverter.class); + assertThat(converter).extracting("dbRefResolver").isInstanceOf(NoOpDbRefResolver.class); + }); + } + @SuppressWarnings("unchecked") private String grisFsTemplateDatabaseName(AssertableApplicationContext context) { assertThat(context).hasSingleBean(ReactiveGridFsTemplate.class);