Skip to content

Replace linkable associations when merging existing array elements for merge patch - #2597

Open
ogawa-takeshi wants to merge 1 commit into
spring-projects:mainfrom
ogawa-takeshi:issue/2596
Open

ogawa-takeshi wants to merge 1 commit into
spring-projects:mainfrom
ogawa-takeshi:issue/2596

Conversation

@ogawa-takeshi

Copy link
Copy Markdown

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-level PUT requests 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 to MergingPropertyHandler,

  • makes MergingPropertyHandler replace a linkable association with the reference contained in the payload instead of merging the source state into the referenced instance,

  • leaves the top-level PUT path (readPut / mergeForPut) unchanged,

  • adds patchReplacesReferenceOfEntityNestedInArray to DomainObjectReaderUnitTests (fails on main, passes with this change; handlesEntityNestedInAnArrayLikePutForPatchRequest from 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).

…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>
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Sep 9, 2026
* @param source must not be {@literal null}.
* @param target must not be {@literal null}.
* @param mapper must not be {@literal null}.
* @throws Exception

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This @throws Exception could be more descriptive (e.g., @throws Exception if deserialization of the source node fails).

}

// GH-2596

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add @Id on Track test class for realism.

* @author Takeshi Ogawa
*/
@ExtendWith(MockitoExtension.class)
class DomainObjectReaderUnitTests {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add edge-case tests for null association and appended elements:

  • For example, There's no test verifying that sending null for 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, not mergeArrayElement).

* 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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Javadoc for mergeArrayElement could be more precise about what it omits vs. readPut.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: waiting-for-triage An issue we've not yet triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Merge patch drops linkable associations of existing array elements since 4.3

3 participants