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 8d597d81d..b6cbd824d 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 @@ -595,7 +595,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App } ConversionContext propertyContext = context.forProperty(prop); - MongoDbPropertyValueProvider valueProviderToUse = valueProvider.withContext(propertyContext); if (prop.isAssociation()) { @@ -623,7 +622,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App continue; } - accessor.setProperty(prop, valueProviderToUse.getPropertyValue(prop)); + accessor.setProperty(prop, valueProvider.getPropertyValue(prop)); } } @@ -2436,6 +2435,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App this.returnedTypeDescriptor = projection; } + + @Override public ConversionContext forProperty(String name) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 7bdf99ee2..a1543aba8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -2554,6 +2554,30 @@ public class MongoTemplateTests { assertThat(projection.getName()).isEqualTo("Walter"); } + @Test // GH-4609 + public void shouldReadNestedProjection() { + + MyPerson walter = new MyPerson("Walter"); + walter.address = new Address("spring", "data"); + template.save(walter); + + PersonPWA result = template.query(MyPerson.class) + .as(PersonPWA.class) + .matching(where("id").is(walter.id)) + .firstValue(); + + assertThat(result.getAddress().getCity()).isEqualTo("data"); + } + + interface PersonPWA { + String getName(); + AdressProjection getAddress(); + } + + interface AdressProjection { + String getCity(); + } + @Test // GH-4300 public void findAndReplaceShouldAllowNativeDomainTypesAndReturnAProjection() { 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 857ded9cf..8a73aa2e9 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 @@ -2851,6 +2851,44 @@ class MappingMongoConverterUnitTests { assertThat(person.getAddresses()).extracting(AddressProjection::getStreet).hasSize(1).containsOnly("hwy"); } + @Test // GH-4609 + void projectShouldReadNestedInterfaceProjection() { + + org.bson.Document source = new org.bson.Document("foo", "spring").append("address", + new org.bson.Document("s", "data").append("city", "mongodb")); + + EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(converter.getProjectionFactory(), + EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy() + .and((target, underlyingType) -> !converter.conversions.isSimpleType(target)), + mappingContext); + + EntityProjection projection = introspector.introspect(WithNestedInterfaceProjection.class, + Person.class); + WithNestedInterfaceProjection person = converter.project(projection, source); + + assertThat(person.getFirstname()).isEqualTo("spring"); + assertThat(person.getAddress().getStreet()).isEqualTo("data"); + } + + @Test // GH-4609 + void projectShouldReadNestedDtoProjection() { + + org.bson.Document source = new org.bson.Document("foo", "spring").append("address", + new org.bson.Document("s", "data").append("city", "mongodb")); + + EntityProjectionIntrospector introspector = EntityProjectionIntrospector.create(converter.getProjectionFactory(), + EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy() + .and((target, underlyingType) -> !converter.conversions.isSimpleType(target)), + mappingContext); + + EntityProjection projection = introspector.introspect(WithNestedDtoProjection.class, + Person.class); + WithNestedDtoProjection person = converter.project(projection, source); + + assertThat(person.getFirstname()).isEqualTo("spring"); + assertThat(person.getAddress().getStreet()).isEqualTo("data"); + } + @Test // GH-2860 void projectShouldReadProjectionWithNestedEntity() { @@ -3206,6 +3244,7 @@ class MappingMongoConverterUnitTests { String lastname; Set
addresses; + Address address; Person() { @@ -3248,6 +3287,16 @@ class MappingMongoConverterUnitTests { Set getAddresses(); } + interface WithNestedInterfaceProjection { + String getFirstname(); + AddressProjection getAddress(); + } + + interface WithNestedDtoProjection { + String getFirstname(); + AddressDto getAddress(); + } + interface ProjectionWithNestedEntity { Set
getAddresses(); @@ -3258,6 +3307,19 @@ class MappingMongoConverterUnitTests { String getStreet(); } + class AddressDto { + + String street; + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + } + static class PersonDto { LocalDate birthDate;