Skip to content

Cosmos: Fix replaceItem bypassing customItemSerializer#48529

Open
lloydmeta wants to merge 3 commits intoAzure:mainfrom
lloydmeta:cosmosdb/fixup-replaceItem-serialisation
Open

Cosmos: Fix replaceItem bypassing customItemSerializer#48529
lloydmeta wants to merge 3 commits intoAzure:mainfrom
lloydmeta:cosmosdb/fixup-replaceItem-serialisation

Conversation

@lloydmeta
Copy link
Contributor

@lloydmeta lloydmeta commented Mar 23, 2026

Description

CosmosAsyncContainer.replaceItem eagerly converted the POJO to a Document via
InternalObjectNode.fromObject(item), which serialises through the SDK's internal
ObjectMapper rather than the user's customItemSerializer. The resulting Document
then short-circuits Document.fromObject (already a Document, returned as-is),
so the custom serialiser is never invoked.

This means any ObjectMapper configuration on the custom serialiser (e.g.
WRITE_DATES_AS_TIMESTAMPS = false, JsonInclude.NON_NULL, custom modules) is
silently ignored for replaceItem, while createItem and upsertItem work correctly.

The fix removes the intermediate InternalObjectNode.fromObject conversion and passes
the raw POJO through the replace chain, matching how createItem and upsertItem
already work.

Fixes #48527

All SDK Contribution checklist:

  • The pull request does not introduce [breaking changes]
  • CHANGELOG is updated for new features, bug fixes or other significant changes.
  • I have read the contribution guidelines.

General Guidelines and Best Practices

  • Title of the pull request is clear and informative.
  • There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, see this page.

Testing Guidelines

  • Pull request includes test coverage for the included changes.

@github-actions github-actions bot added Community Contribution Community members are working on the issue Cosmos customer-reported Issues that are reported by GitHub users external to the Azure organization. labels Mar 23, 2026
@github-actions
Copy link
Contributor

Thank you for your contribution @lloydmeta! We will review the pull request and get back to you soon.

@lloydmeta lloydmeta force-pushed the cosmosdb/fixup-replaceItem-serialisation branch from d108d78 to bd4ea98 Compare March 23, 2026 13:40
Copy link
Member

@FabianMeiswinkel FabianMeiswinkel left a comment

Choose a reason for hiding this comment

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

Looks goo to me - Thanks!

Copy link
Member

@kushagraThapar kushagraThapar left a comment

Choose a reason for hiding this comment

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

Thanks @lloydmeta for fixing this bug on the SDK, appreciate your contributions.

Add a regression test

Signed-off-by: lloydmeta <lloydmeta@gmail.com>
@lloydmeta lloydmeta force-pushed the cosmosdb/fixup-replaceItem-serialisation branch from 0281bb7 to 1550599 Compare March 23, 2026 14:49
@kushagraThapar kushagraThapar marked this pull request as ready for review March 23, 2026 19:24
@kushagraThapar kushagraThapar requested review from a team and kirankumarkolli as code owners March 23, 2026 19:24
Copilot AI review requested due to automatic review settings March 23, 2026 19:24
@kushagraThapar kushagraThapar requested a review from a team as a code owner March 23, 2026 19:24
@kushagraThapar
Copy link
Member

@lloydmeta the newly added tests are failing on this pipeline, can you please check and fix them? https://dev.azure.com/azure-sdk/public/_build/results?buildId=6048391&view=ms.vss-test-web.build-test-results-tab&runId=60434280&paneView=debug
Let me know if you can't access them, I can help pasting the specific error logs.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes CosmosAsyncContainer.replaceItem to respect the effective (custom) item serializer by removing the eager POJO→Document conversion that bypassed user-provided customItemSerializer.

Changes:

  • Updated replaceItem flow to pass the raw item object through the replace pipeline so Document.fromObject(..., effectiveItemSerializer) can invoke the correct serializer.
  • Added an emulator test to validate replaceItem respects custom ObjectMapper settings (e.g., JsonInclude.NON_NULL).
  • Added a CHANGELOG entry describing the bug fix.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java Stops pre-serializing items via SDK-internal mapper so replace operations use the effective/custom serializer.
sdk/cosmos/azure-cosmos/CHANGELOG.md Documents the serializer-bypass bug fix under “Bugs Fixed”.
sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/CosmosItemSerializerTest.java Adds coverage ensuring replaceItem honors request-level custom serializer/ObjectMapper behavior.

Signed-off-by: lloydmeta <lloydmeta@gmail.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Signed-off-by: lloydmeta <lloydmeta@gmail.com>
@lloydmeta
Copy link
Contributor Author

@lloydmeta the newly added tests are failing on this pipeline, can you please check and fix them?

I gave it a go and pushed a commit that has a real fix, f48f962 , but currently there is a failure in a test for something that is not related at all.

c.a.c.i.b.TransactionalBulkExecutorTest.TransactionalBulkExecutorTest::executeTransactionalBulk_concurrencyControl_e2e[Direct Tcp with Eventual consistency]

is failing with

Expecting actual:
3103L
to be less than:
3035L

There is a test that actually looks quite prone to flakiness

// Parallel execution should be faster than serialized execution
assertThat(durationParallel).isLessThan(durationSerial);

it compares parallel vs serial execution and expects the former to be faster than the latter with no tolerance.... not sure what machines you're executing on and the exact set up you hav to ensure parallel is always faster but it feels like it's worthwhile to consider less ambitious like

// allow some leniency variations
assertThat(durationParallel).isCloseTo(durationSerial, Percentage.withPercentage(5)) ;

// Or do one or the other...
assertThat(durationParallel).satisfiesAnyOf(
  it -> assertThat(it).isLessThan(durationSerial),
  it -> assertThat(it).isCloseTo(durationSerial, Percentage.withPercentage(5))
);

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

Labels

Community Contribution Community members are working on the issue Cosmos customer-reported Issues that are reported by GitHub users external to the Azure organization.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] CosmosAsyncContainer.replaceItem bypasses customItemSerializer, serialises POJO with internal ObjectMapper

4 participants