Fix regression in PUT handling for empty nested documents.

The fix for #2174 introduced a bug for our PUT handling of nested documents in case the target object's field value is null as it would only apply the nested value if all Optionals were present. This is, of course not the case.

Fixes #2264.
This commit is contained in:
Oliver Drotbohm
2023-06-12 11:38:28 +02:00
parent 601a793213
commit 47724b3cba
2 changed files with 24 additions and 2 deletions

View File

@@ -40,7 +40,6 @@ import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.data.rest.webmvc.mapping.Associations;
import org.springframework.data.rest.webmvc.util.InputStreamHttpInputMessage;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.TypeInformation;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.lang.Nullable;
@@ -685,7 +684,10 @@ public class DomainObjectReader {
} else if (property.isCollectionLike()) {
result = mergeCollections(property, sourceValue, targetValue, mapper);
} else if (property.isEntity()) {
result = Optionals.mapIfAllPresent(sourceValue, targetValue, (l, r) -> mergeForPut(l, r, mapper));
result = targetValue.isEmpty()
? sourceValue
: targetValue.flatMap(t -> sourceValue.map(s -> mergeForPut(s, t, mapper)));
} else {
result = sourceValue;
}

View File

@@ -662,6 +662,26 @@ class DomainObjectReaderUnitTests {
assertThat(result.longs).isEqualTo(Arrays.asList(1L, 2L));
}
@Test // GH-2264
void nestedEntitiesAreCreatedWhenMissingForPut() throws Exception {
Outer outer = new Outer();
outer.name = "outer name";
outer.prop = "something";
JsonNode node = new ObjectMapper().readTree(
"{ \"inner\" : { \"name\" : \"new inner name\", \"readOnly\" : \"readonly value\", \"hidden\" : \"hidden value\" } }");
Outer result = reader.readPut((ObjectNode) node, outer, new ObjectMapper());
assertThat(result).isSameAs(outer);
assertThat(result.inner).isNotNull();
assertThat(result.inner.prop).isNull();
assertThat(result.inner.name).isEqualTo("new inner name");
assertThat(result.inner.readOnly).isNull();
assertThat(result.inner.hidden).isNull();
}
@SuppressWarnings("unchecked")
private static <T> T as(Object source, Class<T> type) {