Replace linkable associations when merging existing array elements for merge patch - #2597
ogawa-takeshi wants to merge 1 commit into
Conversation
…r merge patch. Since spring-projects#2358, an object nested in an array is applied to the existing element at the same index via readPut(…) to obtain PUT semantics as defined by RFC 7386. mergeForPut(…) however skips linkable associations, which is intended for top-level PUT requests where associations are managed through association resources. Nested elements are not exposed as association resources, so the request body is the only place to express them. As a result, non-association properties of an existing element were updated while its associations kept their previous values, whereas appended elements and elements written into an empty collection resolved them properly. We now merge existing array elements through a dedicated path that forwards linkable associations to the merging property handler, which replaces the reference with the one contained in the payload instead of merging the source state into the referenced instance. Closes spring-projects#2596. Signed-off-by: OGAWA, Takeshi <29126253+ogawa-takeshi@users.noreply.github.com>
| * @param source must not be {@literal null}. | ||
| * @param target must not be {@literal null}. | ||
| * @param mapper must not be {@literal null}. | ||
| * @throws Exception |
There was a problem hiding this comment.
This @throws Exception could be more descriptive (e.g., @throws Exception if deserialization of the source node fails).
| } | ||
|
|
||
| // GH-2596 | ||
|
|
There was a problem hiding this comment.
The comment // GH-2596 above the new test classes in the test file is a bit loose — it's not attached to a specific annotation. The @Test method already has // GH-2596 in its annotation comment, so the standalone comment above the model classes is slightly redundant.
| } | ||
|
|
||
| @JsonAutoDetect(fieldVisibility = Visibility.ANY) | ||
| static class Track { |
There was a problem hiding this comment.
Add @Id on Track test class for realism.
| * @author Takeshi Ogawa | ||
| */ | ||
| @ExtendWith(MockitoExtension.class) | ||
| class DomainObjectReaderUnitTests { |
There was a problem hiding this comment.
Add edge-case tests for null association and appended elements:
- For example, There's no test verifying that sending
nullfor a linkable association in a nested array element correctly nulls out the reference. This edge case is worth covering. - Also, there's no test for the case where the array grows (new element with a linkable association).
- The PR description mentions "appended elements and elements written into an empty collection resolved them properly" — implying those paths already worked. It would be good to have a regression test confirming that appending a new element with a linkable association still works correctly after this change (since the append path goes through
rawValues.apply(current)/mapper.treeToValue, notmergeArrayElement).
| * Reads the given {@link ObjectNode} into a new instance of the given existing array element's type and merges it | ||
| * into the existing element applying {@literal PUT} semantics. In contrast to {@link #readPut(ObjectNode, Object, | ||
| * ObjectMapper)}, linkable associations are replaced by the ones contained in the payload as nested elements are not | ||
| * exposed as association resources and the payload is the only place to express them. |
There was a problem hiding this comment.
Javadoc for mergeArrayElement could be more precise about what it omits vs. readPut.
Closes #2596.
Since #2358, an object nested in an array is applied to the existing element at the same index via
readPut(…)to obtain PUT semantics (RFC 7386).mergeForPut(…)skips linkable associations, which is intended for top-levelPUTrequests where associations are managed through association resources. Nested elements have no association resource, so the request body is the only place to express them. As a result, non-association properties of an existing element were updated while its associations kept their previous values, whereas appended elements and elements written into an empty collection resolved them properly.This change
merges existing array elements through a dedicated path (
mergeArrayElement) that forwards linkable associations toMergingPropertyHandler,makes
MergingPropertyHandlerreplace a linkable association with the reference contained in the payload instead of merging the source state into the referenced instance,leaves the top-level
PUTpath (readPut/mergeForPut) unchanged,adds
patchReplacesReferenceOfEntityNestedInArraytoDomainObjectReaderUnitTests(fails onmain, passes with this change;handlesEntityNestedInAnArrayLikePutForPatchRequestfrom Nested arrays of entities need to get PUT semantics applied for merge patch #2358 keeps passing).You have read the Spring Data contribution guidelines.
You use the code formatters provided here and have them applied to your changes. Don't submit any formatting related changes.
You submit test cases (unit or integration tests) that back your changes.
You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).