From b2809d691e14eccfcea230be52b75e4ea7a713a3 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 1 Sep 2023 12:01:42 +0200 Subject: [PATCH] Correctly read unwrapped properties during constructor creation. Closes: #4491 Original Pull Request: #4492 --- .../core/convert/MappingMongoConverter.java | 32 ++++++++++++++++--- .../MappingMongoConverterUnitTests.java | 30 +++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java index 6aeb08e240..3610d65532 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java @@ -17,7 +17,16 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -41,7 +50,13 @@ import org.springframework.data.annotation.Reference; import org.springframework.data.convert.CustomConversions; import org.springframework.data.convert.TypeMapper; -import org.springframework.data.mapping.*; +import org.springframework.data.mapping.Association; +import org.springframework.data.mapping.InstanceCreatorMetadata; +import org.springframework.data.mapping.MappingException; +import org.springframework.data.mapping.Parameter; +import org.springframework.data.mapping.PersistentEntity; +import org.springframework.data.mapping.PersistentProperty; +import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.callback.EntityCallbacks; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.ConvertingPropertyAccessor; @@ -1961,6 +1976,8 @@ class AssociationAwareMongoDbPropertyValueProvider extends MongoDbPropertyValueP @SuppressWarnings("unchecked") public T getPropertyValue(MongoPersistentProperty property) { + ConversionContext propertyContext = context.forProperty(property); + if (property.isDbReference() && property.getDBRef().lazy()) { Object rawRefValue = accessor.get(property); @@ -1977,9 +1994,16 @@ public T getPropertyValue(MongoPersistentProperty property) { } if (property.isDocumentReference()) { + return (T) dbRefResolver.resolveReference(property, - new DocumentReferenceSource(accessor.getDocument(), accessor.get(property)), - referenceLookupDelegate, context::convert); + new DocumentReferenceSource(accessor.getDocument(), accessor.get(property)), referenceLookupDelegate, + context::convert); + } + + if (property.isUnwrapped()) { + + return (T) readUnwrapped(propertyContext, accessor, property, + mappingContext.getRequiredPersistentEntity(property)); } return super.getPropertyValue(property); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 6bab7fc89a..748dd29a8a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -2350,6 +2350,24 @@ void readUnwrappedTypeWithComplexValue() { .isEqualTo(expected); } + @Test // GH-4491 + void readUnwrappedTypeWithComplexValueUsingConstructor() { + + org.bson.Document source = new org.bson.Document("_id", "id-1").append("stringValue", "hello").append("address", + new org.bson.Document("s", "1007 Mountain Drive").append("city", "Gotham")); + + WithUnwrappedConstructor target = converter.read(WithUnwrappedConstructor.class, source); + + Address expected = new Address(); + expected.city = "Gotham"; + expected.street = "1007 Mountain Drive"; + + assertThat(target.embeddableValue.stringValue) // + .isEqualTo("hello"); + assertThat(target.embeddableValue.address) // + .isEqualTo(expected); + } + @Test // DATAMONGO-1902 void writeUnwrappedTypeWithComplexValue() { @@ -3374,6 +3392,18 @@ static class WithNullableUnwrapped { @Unwrapped.Nullable EmbeddableType embeddableValue; } + static class WithUnwrappedConstructor { + + private final String id; + + private final @Unwrapped.Empty EmbeddableType embeddableValue; + + public WithUnwrappedConstructor(String id, EmbeddableType embeddableValue) { + this.id = id; + this.embeddableValue = embeddableValue; + } + } + static class WithPrefixedNullableUnwrapped { String id;