diff --git a/pom.xml b/pom.xml index 92c8f2562b..d282a42f4f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 4.2.3-SNAPSHOT + 4.2.x-4609-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index f0f146edd9..1e70a28eb0 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 4.2.3-SNAPSHOT + 4.2.x-4609-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 6876c90f9f..6c2f6ffb56 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -15,7 +15,7 @@ org.springframework.data spring-data-mongodb-parent - 4.2.3-SNAPSHOT + 4.2.x-4609-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 4e070e04d4..c43dfc392d 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -13,7 +13,7 @@ org.springframework.data spring-data-mongodb-parent - 4.2.3-SNAPSHOT + 4.2.x-4609-SNAPSHOT ../pom.xml 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 8d597d81d9..b6cbd824da 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 @@ private void readProperties(ConversionContext context, MongoPersistentEntity } ConversionContext propertyContext = context.forProperty(prop); - MongoDbPropertyValueProvider valueProviderToUse = valueProvider.withContext(propertyContext); if (prop.isAssociation()) { @@ -623,7 +622,7 @@ private void readProperties(ConversionContext context, MongoPersistentEntity continue; } - accessor.setProperty(prop, valueProviderToUse.getPropertyValue(prop)); + accessor.setProperty(prop, valueProvider.getPropertyValue(prop)); } } @@ -2436,6 +2435,8 @@ class ProjectingConversionContext extends DefaultConversionContext { 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 7bdf99ee28..a1543aba86 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 void findAndReplaceShouldProjectReturnedObjectCorrectly() { 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 857ded9cf6..8a73aa2e9c 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 @@ void projectShouldReadNestedProjection() { 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 @@ static class Person implements Contact { String lastname; Set
addresses; + Address address; Person() { @@ -3248,6 +3287,16 @@ interface WithNestedProjection { Set getAddresses(); } + interface WithNestedInterfaceProjection { + String getFirstname(); + AddressProjection getAddress(); + } + + interface WithNestedDtoProjection { + String getFirstname(); + AddressDto getAddress(); + } + interface ProjectionWithNestedEntity { Set
getAddresses(); @@ -3258,6 +3307,19 @@ interface AddressProjection { String getStreet(); } + class AddressDto { + + String street; + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + } + static class PersonDto { LocalDate birthDate;