From ecba61662cb15a5e78977f8ee48c6b0ee415d379 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Mon, 12 Jun 2023 11:38:28 +0200 Subject: [PATCH] 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. --- .../rest/webmvc/json/DomainObjectReader.java | 6 ++++-- .../json/DomainObjectReaderUnitTests.java | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java index 901f9ce55..593e1a50c 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java @@ -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; @@ -677,7 +676,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; } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/DomainObjectReaderUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/DomainObjectReaderUnitTests.java index 25c94f5d1..92ecc2bba 100755 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/DomainObjectReaderUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/DomainObjectReaderUnitTests.java @@ -664,6 +664,26 @@ class DomainObjectReaderUnitTests { assertThat(result.longs).isEqualTo(List.of(1L, 2L)); } + @Test // GH-2264 + void nestedEntitiesAreCreatedWhenMissingForPut() throws Exception { + + var outer = new Outer(); + outer.name = "outer name"; + outer.prop = "something"; + + var node = new ObjectMapper().readTree( + "{ \"inner\" : { \"name\" : \"new inner name\", \"readOnly\" : \"readonly value\", \"hidden\" : \"hidden value\" } }"); + + var 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 as(Object source, Class type) {