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;