Remove unnecessary intermediate String deserialization of document bodies#2122
Remove unnecessary intermediate String deserialization of document bodies#2122emilienbev wants to merge 6 commits intomainfrom
Conversation
… favour of the raw bytes Signed-off-by: Emilien Bevierre <emilien.bevierre@couchbase.com>
…immediately after subscribe(), before the document has potentially been saved. Signed-off-by: Emilien Bevierre <emilien.bevierre@couchbase.com>
There was a problem hiding this comment.
Pull request overview
This PR addresses issue #2121 by eliminating an unnecessary intermediate String conversion when decoding KV document bodies, enabling decoding directly from raw response bytes (notably for reactive KV operations) while keeping string-based decoding available.
Changes:
- Add
byte[]decode paths across template support APIs and internal decode flow (TemplateSupport/ReactiveTemplateSupport→AbstractTemplateSupport→TranslationService). - Update reactive KV operations (e.g., find-by-id, range scan, replicas) to pass
contentAsBytes()instead of converting toString. - Extend Jackson translation to decode directly from
byte[]and add tests validating byte-based decoding (including non-ASCII content).
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/test/java/org/springframework/data/couchbase/repository/query/ReactiveCouchbaseRepositoryQueryCollectionIntegrationTests.java | Adjusts reactive test flow to block for completion (avoids async subscribe). |
| src/test/java/org/springframework/data/couchbase/core/convert/translation/JacksonTranslationServiceTests.java | Adds coverage for decoding from UTF-8 bytes (ASCII + non-ASCII). |
| src/main/java/org/springframework/data/couchbase/core/convert/translation/TranslationService.java | Adds decode(byte[], ...) default overload to support byte-based decoding. |
| src/main/java/org/springframework/data/couchbase/core/convert/translation/JacksonTranslationService.java | Implements direct byte[] parsing via Jackson JsonParser. |
| src/main/java/org/springframework/data/couchbase/core/TemplateSupport.java | Adds byte[] overload for entity decoding (sync template support). |
| src/main/java/org/springframework/data/couchbase/core/ReactiveTemplateSupport.java | Adds byte[] overload for entity decoding (reactive template support). |
| src/main/java/org/springframework/data/couchbase/core/ReactiveRangeScanOperationSupport.java | Uses contentAsBytes() to avoid intermediate String creation. |
| src/main/java/org/springframework/data/couchbase/core/ReactiveFindFromReplicasByIdOperationSupport.java | Uses contentAsBytes() for replica reads. |
| src/main/java/org/springframework/data/couchbase/core/ReactiveFindByIdOperationSupport.java | Uses contentAsBytes() across get variants (touch/lock/get/tx path). |
| src/main/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateSupport.java | Implements reactive byte[] decodeEntity overload. |
| src/main/java/org/springframework/data/couchbase/core/NonReactiveSupportWrapper.java | Bridges reactive byte[] decode to non-reactive support. |
| src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplateSupport.java | Implements sync byte[] decodeEntity overload. |
| src/main/java/org/springframework/data/couchbase/core/AbstractTemplateSupport.java | Adds byte[] decodeEntityBase path and refactors shared decode/finalize steps. |
| .gitignore | Ignores src/test/resources/integration.local.properties. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/main/java/org/springframework/data/couchbase/core/TemplateSupport.java
Outdated
Show resolved
Hide resolved
src/main/java/org/springframework/data/couchbase/core/ReactiveTemplateSupport.java
Outdated
Show resolved
Hide resolved
...ain/java/org/springframework/data/couchbase/core/convert/translation/TranslationService.java
Show resolved
Hide resolved
...a/org/springframework/data/couchbase/core/convert/translation/JacksonTranslationService.java
Show resolved
Hide resolved
src/main/java/org/springframework/data/couchbase/core/TemplateSupport.java
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Emilien Bevierre <44171454+emilienbev@users.noreply.github.com>
…te[] ...) (back to String). Ensure that if both parsing and close throw, the close exception is suppressed rather than masking the original error. Signed-off-by: Emilien Bevierre <emilien.bevierre@couchbase.com>
| * @return a properly populated document to work with. | ||
| */ | ||
| default CouchbaseStorable decode(byte[] source, CouchbaseStorable target) { | ||
| return decode(new String(source, StandardCharsets.UTF_8), target); |
There was a problem hiding this comment.
Seeing new String(…, StandardCharsets.UTF_8) in various places hints for having a utility method somewhere. ByteUtils.toString(…) could be a good startingpoint.
| * @return the decoded structure. | ||
| */ | ||
| @Override | ||
| public final CouchbaseStorable decode(final byte[] source, final CouchbaseStorable target) { |
There was a problem hiding this comment.
final arguments and in variable declarations (further down below in the pull request) is rather noise and distracts from reading code. This is more of an observation.
onobc
left a comment
There was a problem hiding this comment.
👋🏻 @emilienbev
Great work! Thank you for the excellent detail in the issue and the PR description.
I have one request that spans multiple files... do you mind moving your @ author... tags to the end of the list as we typically add in history order (i.e. the original author of the source is the first entry).
src/main/java/org/springframework/data/couchbase/core/AbstractTemplateSupport.java
Outdated
Show resolved
Hide resolved
...a/couchbase/repository/query/ReactiveCouchbaseRepositoryQueryCollectionIntegrationTests.java
Show resolved
Hide resolved
Re-order author tags correctly Remove excessive final modifiers Signed-off-by: Emilien Bevierre <emilien.bevierre@couchbase.com>
Adjust comments Signed-off-by: Emilien Bevierre <emilien.bevierre@couchbase.com>
onobc
left a comment
There was a problem hiding this comment.
Nice work @emilienbev - looks good to me. I have a comment around logging and using String#formatted but you can do what you want w/ that one.
The only other comment I have was mentioned by Mark - we typically don't add final to anything other immutable fields that are set in the constructor.
| throw new CouchbaseException(TemplateUtils.SELECT_ID + " was null. Either use #{#n1ql.selectEntity} or project " | ||
| + TemplateUtils.SELECT_ID); | ||
| throw new CouchbaseException( | ||
| TemplateUtils.SELECT_ID + " was null. Either use #{#n1ql.selectEntity} or project " |
There was a problem hiding this comment.
I have found String#formatted to help w/ the readability of logging statements like this.
Fixes #2121