Skip to content

[AIT-1009] Implement Json and MsgPack serializers for path-based LiveObjects#1218

Open
sacOO7 wants to merge 5 commits into
chore/liveobjects-add-basic-implementationfrom
chore/path-based-liveobjects-serialization
Open

[AIT-1009] Implement Json and MsgPack serializers for path-based LiveObjects#1218
sacOO7 wants to merge 5 commits into
chore/liveobjects-add-basic-implementationfrom
chore/path-based-liveobjects-serialization

Conversation

@sacOO7

@sacOO7 sacOO7 commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds the serialization layer for the path-based LiveObjects API (io.ably.lib.object), supporting both JSON and MessagePack encoding/decoding of object messages. This is the wire-format plumbing that sits underneath the path-based public API.

The design keeps the core lib free of any hard dependency on the optional LiveObjects plugin: the core declares interfaces and reflectively loads the implementation from the liveobjects module at runtime, returning null when the plugin is absent.

Core (lib)

  • ObjectSerializer — public interface declaring the four codec entry points (readMsgpackArray / writeMsgpackArray / readFromJsonArray / asJsonArray). The implementation is loaded reflectively and cached as a lazy singleton via a nested Holder (double-checked locking; retries until the plugin is present), exposed through the static ObjectSerializer.tryGet().
  • ObjectJsonSerializer — Gson JsonSerializer/JsonDeserializer for the protocol-message state field; delegates to the loaded ObjectSerializer, and no-ops gracefully (logs + JsonNull) when the plugin is unavailable.

Plugin (liveobjects)

  • DefaultObjectsSerializer — implements ObjectSerializer, (de)serializing arrays of object messages for JSON and MessagePack.
  • JsonSerialization — Gson setup: enum-by-code adapters and WireObjectDataJsonSerializer (handles the json-as-string encoding per OD4c5 and the "at least one value field" validation).
  • MsgpackSerialization — hand-rolled MessagePack pack/unpack for the full object model (operations, state, map/counter payloads, map entries, object data).

Wire model decoupling

The serializers operate on the WireObjectMessage model in io.ably.lib.object.message, so the new object package carries no dependency on the legacy io.ably.lib.objects package. WireObjectMessage carries the Gson annotations needed for wire-format fidelity — @SerializedName("object") on objectState (OM2g) and @JsonAdapter(WireObjectDataJsonSerializer) on WireObjectData.

Notes

  • Errors use the object package's objectStateError (ErrorInfo 500 / 92000).
  • No new test coverage for the path-based serializers yet — existing serialization tests still target the legacy package. Round-trip tests for the Wire* model are tracked as a follow-up.

Spec: OM*, OOP*, OD*, OMP*, OCN*, OST*, MCR*, MST*, MRM*, CCR*, CIN*, ODE*, MCL*

🤖 Generated with Claude Code

@sacOO7 sacOO7 changed the title Implemented Json and MsgPack serializers for path based liveobjects Implemente Json and MsgPack serializers for path based liveobjects Jun 18, 2026
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@sacOO7, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 54 minutes and 58 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1cf0c62d-9c55-41a5-b39e-bd6382f8f559

📥 Commits

Reviewing files that changed from the base of the PR and between c8a283d and bfa574f.

📒 Files selected for processing (7)
  • lib/src/main/java/io/ably/lib/object/LiveObjectsPlugin.java
  • lib/src/main/java/io/ably/lib/object/serialization/ObjectJsonSerializer.java
  • lib/src/main/java/io/ably/lib/object/serialization/ObjectSerializer.java
  • liveobjects/src/main/kotlin/io/ably/lib/object/message/WireObjectMessage.kt
  • liveobjects/src/main/kotlin/io/ably/lib/object/serialization/DefaultSerialization.kt
  • liveobjects/src/main/kotlin/io/ably/lib/object/serialization/JsonSerialization.kt
  • liveobjects/src/main/kotlin/io/ably/lib/object/serialization/MsgpackSerialization.kt
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/path-based-liveobjects-serialization

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot temporarily deployed to staging/pull/1218/features June 18, 2026 18:04 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1218/javadoc June 18, 2026 18:06 Inactive
- Implemented JsonSerializer annotation for better json handling
@github-actions github-actions Bot temporarily deployed to staging/pull/1218/features June 19, 2026 12:13 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1218/javadoc June 19, 2026 12:15 Inactive
Point the JSON and MsgPack serializers in io.ably.lib.object.serialization
at the new WireObjectMessage wire model instead of the legacy
io.ably.lib.objects.ObjectMessage, so the new `object` package has no
dependency on the legacy `objects` package.

- DefaultSerialization: implement the new ObjectSerializer interface and
  (de)serialize WireObjectMessage arrays (reflectively loaded via
  ObjectSerializer.Holder).
- Json/MsgpackSerialization: bind the Wire* types; replace legacy
  objectError with the object package's objectStateError (same 500/92000).
- WireObjectMessage: restore the gson annotations required for wire-format
  fidelity - @SerializedName("object") on objectState and
  @JsonAdapter(WireObjectDataJsonSerializer) on WireObjectData.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot temporarily deployed to staging/pull/1218/features June 19, 2026 12:22 Inactive
@sacOO7 sacOO7 changed the title Implemente Json and MsgPack serializers for path based liveobjects Implement Json and MsgPack serializers for path-based LiveObjects Jun 19, 2026
@sacOO7 sacOO7 changed the title Implement Json and MsgPack serializers for path-based LiveObjects [AIT-1009] Implement Json and MsgPack serializers for path-based LiveObjects Jun 19, 2026
@sacOO7 sacOO7 marked this pull request as ready for review June 19, 2026 12:23
@github-actions github-actions Bot temporarily deployed to staging/pull/1218/javadoc June 19, 2026 12:23 Inactive
Fixes checkstyle AvoidStarImport violation on com.google.gson.*.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot temporarily deployed to staging/pull/1218/features June 19, 2026 12:25 Inactive
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/path-based-liveobjects-serialization

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot temporarily deployed to staging/pull/1218/features June 19, 2026 12:27 Inactive

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds the wire-format serialization layer for the path-based LiveObjects API (io.ably.lib.object), providing JSON and MessagePack codecs for the Wire* object-message model while keeping the core lib module decoupled from the optional liveobjects plugin via reflective loading.

Changes:

  • Introduces ObjectSerializer (+ ObjectJsonSerializer) in lib, with a lazy reflectively-loaded plugin implementation.
  • Adds DefaultObjectsSerializer plus JSON/MsgPack encoding/decoding for WireObjectMessage arrays in liveobjects.
  • Updates the Wire* model with Gson annotations needed for wire-format fidelity (e.g., "object" field name and WireObjectData JSON-as-string handling).

Reviewed changes

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

Show a summary per file
File Description
liveobjects/src/main/kotlin/io/ably/lib/object/serialization/MsgpackSerialization.kt MessagePack (de)serialization for the path-based Wire* object model.
liveobjects/src/main/kotlin/io/ably/lib/object/serialization/JsonSerialization.kt Gson configuration + enum-by-code adapters + WireObjectData JSON-as-string adapter.
liveobjects/src/main/kotlin/io/ably/lib/object/serialization/DefaultSerialization.kt Plugin-side ObjectSerializer implementation for JSON/MsgPack arrays of WireObjectMessage.
liveobjects/src/main/kotlin/io/ably/lib/object/message/WireObjectMessage.kt Wire model updates: Gson annotations for "object" and WireObjectData adapter.
lib/src/main/java/io/ably/lib/object/serialization/ObjectSerializer.java Core-side serializer interface + reflective singleton loader for plugin implementation.
lib/src/main/java/io/ably/lib/object/serialization/ObjectJsonSerializer.java Gson serializer/deserializer for the protocol state field via ObjectSerializer.tryGet().
lib/src/main/java/io/ably/lib/object/LiveObjectsPlugin.java Core-side reflective plugin initializer interface for LiveObjects functionality.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +289 to +293
if (action == null) {
throw objectStateError("Missing required 'action' field in WireObjectOperation")
}

return WireObjectOperation(
Comment on lines +390 to +391

return WireObjectState(
Comment on lines +19 to +23
ObjectSerializer serializer = ObjectSerializer.tryGet();
if (serializer == null) {
Log.w(TAG, "Skipping 'state' field json deserialization because ObjectsSerializer not found.");
return null;
}
Comment on lines +32 to +36
ObjectSerializer serializer = ObjectSerializer.tryGet();
if (serializer == null) {
Log.w(TAG, "Skipping 'state' field json serialization because ObjectsSerializer not found.");
return JsonNull.INSTANCE;
}
Comment on lines +86 to +91
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException |
NoSuchMethodException |
InvocationTargetException e) {
Log.w(TAG, "Failed to init ObjectsSerializer, LiveObjects plugin not included in the classpath", e);
return null;
}
Comment on lines +14 to +18
internal class DefaultObjectsSerializer : ObjectSerializer {

override fun readMsgpackArray(unpacker: MessageUnpacker): Array<Any> {
val objectMessagesCount = unpacker.unpackArrayHeader()
return Array(objectMessagesCount) { readObjectMessage(unpacker) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants