Skip to content

Conversation

@sacOO7
Copy link
Collaborator

@sacOO7 sacOO7 commented Jun 22, 2025

Fixed #1098

  1. Added LiveObjectsHelper for initializing LiveObjects plugin and related serializer
  2. Updated ProtocolMessage to handle msgpack serialization/deserialization

Decided to have separate serialization over just single gson serialization because =>

  1. In case of msgpack, needs two layers of serialization, first is always json and second is to msgpack.
  2. Even then conversation from json to msgpack for binary type( byte array ) is not compatible ( need to add hack for the same by checking binary field )
  3. Doesn't conform to the spec as per Add spec for ObjectMessage encoding and decoding specification#335 (comment)

Summary by CodeRabbit

  • New Features

    • Added support for serializing and deserializing live object arrays in both JSON and MessagePack formats.
    • Introduced a new field for object state in protocol messages, enabling richer data synchronization.
    • Enhanced JSON and binary serialization for complex object types, including custom handling for enums, binary data, and polymorphic values.
  • Improvements

    • Improved type safety and JSON mapping for object message properties.
    • Deprecated and removed unused or redundant fields to streamline data models.
  • Tests

    • Added comprehensive tests for object message serialization and deserialization in both JSON and MessagePack formats.
    • Introduced new test fixtures to support robust serialization testing.
  • Chores

    • Updated dependencies and internal helpers to support new serialization features.

sacOO7 added 5 commits June 18, 2025 19:26
1. Added LiveObjectsHelper for initializing LiveObjects plugin and LiveObjectsSerializer impl.
2. Updated ProtocolMessage to handle msgpack serialization/deserialization for state field
3. Implemented LiveObjectsJsonSerializer for json serialization/deserialization of state field
…sage

1. Added jackson-dataformat-msgpack 0.8.11 dependency for automatic msgpack handling
2. Implemented JSON serialization via ObjectMessage.toJsonObject() and JsonObject.toObjectMessage() extensions
3. Implemented MessagePack serialization via ObjectMessage.writeTo() and MessageUnpacker.readObjectMessage() extensions
4. Added @SerializedName("object") annotation for proper field naming consistency
1. Added JSON serializer/deserializer using ObjectDataJsonSerializer
2, Added msgpack serializer/deserializer using ObjectDataMsgpackSerializer and ObjectDataMsgpackDeserializer
…ialization

1. Created ObjectMessageFixtures to represent dummy data in various formats
2. Added jackson-param dependency to fix jackson deserialization issue
3. Marked javaParameters as true on compilerOptions
1. Updated test for testOmitNullsInObjectMessageSerialization
2. Added test HandleNullsInObjectMessageDeserialization
@coderabbitai
Copy link

coderabbitai bot commented Jun 22, 2025

Walkthrough

This change introduces comprehensive serialization and deserialization support for LiveObjects in both JSON and MessagePack formats. It adds interfaces, default implementations, helper classes, and custom serializers for handling arrays of live objects, and integrates these into protocol messages. Extensive unit tests and fixtures are included to verify correct serialization behavior.

Changes

File(s) Change Summary
lib/src/main/java/io/ably/lib/objects/LiveObjectSerializer.java Added interface for serializing/deserializing arrays of live objects in JSON/MsgPack.
lib/src/main/java/io/ably/lib/objects/LiveObjectsHelper.java Added helper class for initializing LiveObjects plugin and serializer via reflection.
lib/src/main/java/io/ably/lib/objects/LiveObjectsJsonSerializer.java Added custom JSON serializer/deserializer for live object arrays using LiveObjectSerializer.
lib/src/main/java/io/ably/lib/realtime/AblyRealtime.java Delegated LiveObjects plugin initialization to helper; removed private method and related imports.
lib/src/main/java/io/ably/lib/types/ProtocolMessage.java Added nullable state field (array of objects) with custom serialization logic (JSON/MsgPack).
lib/src/main/java/io/ably/lib/types/ProtocolSerializer.java Updated writeMsgpack to throw AblyException instead of returning null on error.
live-objects/build.gradle.kts Added dependency on common library bundle.
live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt Made Binary.data non-nullable; removed null checks.
live-objects/src/main/kotlin/io/ably/lib/objects/ObjectMessage.kt Added/updated JSON serialization annotations; changed types and deprecated a field.
live-objects/src/main/kotlin/io/ably/lib/objects/Serialization.kt Deleted singleton Gson serializer definition.
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/JsonSerialization.kt Added JSON (de)serialization logic, custom enum adapters, and serializers for object data.
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/MsgpackSerialization.kt Added MessagePack (de)serialization logic for all relevant object types.
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/DefaultSerialization.kt Added default implementation of LiveObjectSerializer for arrays of ObjectMessage.
live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSerializationTest.kt Added unit tests for JSON and MsgPack serialization/deserialization of ObjectMessage.
live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt Updated test data for ObjectMessage size calculation to match new types/fields.
live-objects/src/test/kotlin/io/ably/lib/objects/unit/fixtures/ObjectMessageFixtures.kt Added test fixtures for various ObjectMessage and related data types.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AblyRealtime
    participant LiveObjectsHelper
    participant LiveObjectSerializer
    participant ProtocolMessage

    Client->>AblyRealtime: Send/receive ProtocolMessage with state
    AblyRealtime->>LiveObjectsHelper: getLiveObjectSerializer()
    LiveObjectsHelper->>LiveObjectSerializer: (via reflection) instantiate if needed
    AblyRealtime->>ProtocolMessage: Serialize/deserialize state field
    ProtocolMessage->>LiveObjectSerializer: Serialize/deserialize ObjectMessage[] (JSON/MsgPack)
    LiveObjectSerializer-->>ProtocolMessage: Return serialized/deserialized data
    ProtocolMessage-->>AblyRealtime: Complete (de)serialization
    AblyRealtime-->>Client: Return processed ProtocolMessage
Loading

Assessment against linked issues

Objective Addressed Explanation
Implement LiveObject serialization/deserialization in JSON and MessagePack formats (#1098, ECO-5386)
Integrate custom serialization logic with ProtocolMessage and ensure plugin support (#1098, ECO-5386)
Provide unit tests and fixtures for serialization correctness (#1098, ECO-5386)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation

Possibly related PRs

  • Setup : LiveObject plugin #1085: Sets up the LiveObjects plugin infrastructure, which is closely related as the current PR adds serialization support used by the plugin.

Poem

In fields of bytes where objects play,
The rabbits hop with JSON and MsgPack today.
Serialization magic, arrays in a row,
Through helpers and tests, the live objects flow.
With fixtures and helpers, the code is now bright—
🐇 Serialization dreams take flight!

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Post Copyable Unit Tests in Comment
  • Commit Unit Tests in branch chore/liveojects-serialization-without-msgpack-deps

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@sacOO7 sacOO7 changed the title Chore/liveojects serialization without msgpack deps [ECO-5386] Liveobjects serialization without msgpack deps Jun 22, 2025
@github-actions github-actions bot temporarily deployed to staging/pull/1106/features June 22, 2025 16:19 Inactive
@sacOO7 sacOO7 force-pushed the chore/liveojects-serialization-without-msgpack-deps branch from f97b3e7 to 4c07a19 Compare June 22, 2025 16:20
@github-actions github-actions bot temporarily deployed to staging/pull/1106/features June 22, 2025 16:21 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1106/javadoc June 22, 2025 16:23 Inactive
@sacOO7 sacOO7 force-pushed the chore/liveojects-serialization-without-msgpack-deps branch from 4c07a19 to 1d85b5c Compare June 22, 2025 17:27
@github-actions github-actions bot temporarily deployed to staging/pull/1106/features June 22, 2025 17:28 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1106/javadoc June 22, 2025 17:29 Inactive
1. Implemented manual msgpack serialization
2. Updated tests
@sacOO7 sacOO7 force-pushed the chore/liveojects-serialization-without-msgpack-deps branch from 1d85b5c to 8d23a1f Compare June 22, 2025 17:31
@github-actions github-actions bot temporarily deployed to staging/pull/1106/features June 22, 2025 17:32 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1106/javadoc June 22, 2025 17:33 Inactive
@sacOO7 sacOO7 marked this pull request as ready for review June 22, 2025 18:26
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (4)
live-objects/build.gradle.kts (1)

14-14: Verify that the common bundle doesn’t reintroduce MessagePack dependencies
This PR’s goal is to remove MsgPack from the module; please double-check that libs.bundles.common in your version catalog only contains the intended helper and JSON serialization libraries and does not transitively pull in any org.msgpack artifacts. If it does, explicitly exclude them:

implementation(libs.bundles.common) {
  exclude(group = "org.msgpack", module = "msgpack-core")
}
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt (1)

1-18: Consider narrowing the suppression scope.

Suppressing UNCHECKED_CAST at the file level is too broad. Consider suppressing only at specific unsafe cast locations after adding appropriate type checks.

Apply this pattern to add type safety:

-@file:Suppress("UNCHECKED_CAST")
-
 package io.ably.lib.objects.serialization

 // ... imports ...

 @Suppress("unused") // Used via reflection in LiveObjectsHelper
 internal class DefaultLiveObjectSerializer : LiveObjectSerializer {
live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSerializationTest.kt (1)

49-66: Fix incorrect comment.

The comment mentions MsgPack but the code performs JSON serialization.

-    // Serialize the ProtocolMessage containing ObjectMessages to MsgPack format
+    // Serialize the ProtocolMessage containing ObjectMessages to JSON format
     val serializedProtoMsg = ProtocolSerializer.writeJSON(protocolMessage).toString(Charsets.UTF_8)
live-objects/src/test/kotlin/io/ably/lib/objects/unit/fixtures/ObjectMessageFixture.kt (1)

5-10: Remove redundant imports

The individual class imports on lines 6-10 are redundant since line 5 already imports all classes from io.ably.lib.objects.*.

 import io.ably.lib.objects.*
-import io.ably.lib.objects.Binary
-import io.ably.lib.objects.ObjectData
-import io.ably.lib.objects.ObjectMessage
-import io.ably.lib.objects.ObjectState
-import io.ably.lib.objects.ObjectValue
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 80a655e and 8d23a1f.

📒 Files selected for processing (16)
  • lib/src/main/java/io/ably/lib/objects/LiveObjectSerializer.java (1 hunks)
  • lib/src/main/java/io/ably/lib/objects/LiveObjectsHelper.java (1 hunks)
  • lib/src/main/java/io/ably/lib/objects/LiveObjectsJsonSerializer.java (1 hunks)
  • lib/src/main/java/io/ably/lib/realtime/AblyRealtime.java (2 hunks)
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java (5 hunks)
  • lib/src/main/java/io/ably/lib/types/ProtocolSerializer.java (2 hunks)
  • live-objects/build.gradle.kts (1 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt (1 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/ObjectMessage.kt (5 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/Serialization.kt (0 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/JsonSerialization.kt (1 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/MsgpackSerialization.kt (1 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt (1 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSerializationTest.kt (1 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt (4 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/fixtures/ObjectMessageFixture.kt (1 hunks)
💤 Files with no reviewable changes (1)
  • live-objects/src/main/kotlin/io/ably/lib/objects/Serialization.kt
🔇 Additional comments (18)
lib/src/main/java/io/ably/lib/objects/LiveObjectSerializer.java (1)

10-51: Excellent interface design for LiveObjects serialization.

The interface is well-structured with:

  • Clear separation between MessagePack and JSON serialization methods
  • Proper nullability annotations ensuring type safety
  • Appropriate exception declarations (IOException for MessagePack operations)
  • Comprehensive Javadoc documentation
  • Consistent method naming conventions

The design provides a clean abstraction for converting LiveObject arrays between different serialization formats.

live-objects/src/main/kotlin/io/ably/lib/objects/Helpers.kt (1)

42-56: Verify the impact of making Binary.data non-nullable.

The change from ByteArray? to ByteArray removes null safety, which could be a breaking change. Ensure that:

  1. All existing code that creates Binary instances provides non-null data
  2. No existing code relies on the nullable behavior
  3. The serialization/deserialization logic handles this correctly

Run the following script to verify Binary usage across the codebase:

#!/bin/bash
# Description: Check for Binary class usage and potential null handling

# Search for Binary class instantiation
echo "=== Binary class instantiation ==="
rg -A 3 "Binary\(" --type kotlin --type java

# Search for null checks on Binary.data
echo "=== Null checks on Binary.data ==="
rg "\.data\s*[!=]=\s*null" --type kotlin --type java

# Search for Binary.data usage
echo "=== Binary.data property usage ==="
rg "\.data\b" --type kotlin --type java -A 2 -B 2
lib/src/main/java/io/ably/lib/types/ProtocolSerializer.java (1)

31-41: I need to see how exceptions are propagated in the rest of send(...), so I’ll pull more lines around the method:

#!/bin/bash
# Show send() including its catch blocks
rg -n "public void send" -A 60 lib/src/main/java/io/ably/lib/transport/WebSocketTransport.java
live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt (1)

3-3: Test updates align well with the new serialization framework.

The changes correctly update test data to match the new serialization approach:

  • Using JsonObject instead of Map for extras field aligns with the new JSON serialization
  • Simplified Binary data creation using string conversion
  • Import additions for required types

The test logic and size calculations remain consistent, ensuring backward compatibility verification.

Also applies to: 21-21, 37-40, 84-84

lib/src/main/java/io/ably/lib/realtime/AblyRealtime.java (1)

8-8: Excellent refactoring to centralize LiveObjects plugin initialization.

This change improves code organization by:

  • Moving reflection-based plugin loading to a dedicated LiveObjectsHelper class
  • Reducing complexity in the AblyRealtime constructor
  • Centralizing LiveObjects-related initialization logic
  • Maintaining the same functionality while improving separation of concerns

The refactoring enhances maintainability and makes the code more modular.

Also applies to: 75-75

lib/src/main/java/io/ably/lib/types/ProtocolMessage.java (3)

7-11: Imports look good.

The new imports are appropriate for the LiveObjects serialization functionality.


131-138: State field declaration is well-designed.

The nullable state field with custom JSON serialization adapter is properly documented and implemented.


274-283: MsgPack deserialization logic is correct.

The implementation properly handles the case where LiveObjectSerializer is unavailable by logging and skipping the value.

live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt (1)

31-36: JSON array deserialization is well-implemented.

Proper validation of JSON elements with appropriate error handling.

lib/src/main/java/io/ably/lib/objects/LiveObjectsJsonSerializer.java (1)

14-38: JSON serializer implementation is well-designed.

The implementation properly handles cases where LiveObjectSerializer is unavailable, with appropriate logging and fallback behavior.

lib/src/main/java/io/ably/lib/objects/LiveObjectsHelper.java (1)

13-25: Plugin initialization via reflection is well-implemented.

Good error handling with appropriate logging for when the plugin is not available.

live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSerializationTest.kt (2)

19-47: MsgPack serialization test is well-implemented.

Good test coverage with proper assertions for round-trip serialization.


68-180: Excellent test coverage for edge cases.

The tests for null handling and enum serialization are comprehensive and well-structured.

live-objects/src/test/kotlin/io/ably/lib/objects/unit/fixtures/ObjectMessageFixture.kt (1)

12-174: Well-structured test fixtures

The test fixture data is comprehensive and well-organized, providing good coverage for different data types (string, binary, number, boolean, JSON object, and JSON array). The factory functions follow a consistent pattern that makes the test data easy to understand and maintain.

live-objects/src/main/kotlin/io/ably/lib/objects/ObjectMessage.kt (2)

6-11: Excellent serialization enhancements

The addition of Gson annotations and custom serializers improves the robustness of the serialization framework:

  • Custom serializers for ObjectData and Binary provide proper type-specific handling
  • Restricting extras to JsonObject? improves type safety
  • The @SerializedName("object") annotation ensures correct JSON field mapping

Also applies to: 37-37, 221-222, 318-318, 334-334


227-228: Proper deprecation handling

Good practice marking initialValueEncoding as deprecated with a clear migration message. This helps maintain backward compatibility while signaling future removal.

live-objects/src/main/kotlin/io/ably/lib/objects/serialization/JsonSerialization.kt (1)

1-100: Well-implemented JSON serialization framework

The JSON serialization implementation is comprehensive and follows best practices:

  • Custom enum serialization by code values ensures consistent behavior
  • Polymorphic ObjectData serialization correctly handles all value types
  • Special JSON encoding handling (lines 54-58, 71-81) properly implements the specifications
  • Base64 encoding for binary data is implemented correctly
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/MsgpackSerialization.kt (1)

1-206: High-quality MessagePack serialization implementation

The MessagePack serialization is well-implemented with several notable strengths:

  • Consistent null-safe field counting approach
  • Memory-efficient string interning (e.g., line 107)
  • Proper enum validation with descriptive error messages (lines 230-231, 489-490)
  • Correct handling of JSON-encoded strings (lines 694-705)
  • Comprehensive coverage of all object types

Also applies to: 232-709

@sacOO7 sacOO7 changed the title [ECO-5386] Liveobjects serialization without msgpack deps [ECO-5386] Liveobjects serialization without msgpack (jackson) deps Jun 23, 2025
@sacOO7 sacOO7 requested a review from ttypic June 23, 2025 12:48
@github-actions github-actions bot temporarily deployed to staging/pull/1106/features June 23, 2025 14:23 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1106/javadoc June 23, 2025 14:26 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/MsgpackSerialization.kt (1)

112-112: Consider removing unnecessary string interning.

The intern() calls on field names may add unnecessary overhead. Since these are typically short strings used for field matching in when statements, the benefits of interning are minimal.

-    val fieldName = unpacker.unpackString().intern()
+    val fieldName = unpacker.unpackString()

Also applies to: 226-226, 327-327, 393-393, 437-437, 489-489, 542-542, 598-598, 678-678

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d23a1f and 7755418.

📒 Files selected for processing (4)
  • lib/src/main/java/io/ably/lib/objects/LiveObjectsHelper.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java (5 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/MsgpackSerialization.kt (1 hunks)
  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java
  • lib/src/main/java/io/ably/lib/objects/LiveObjectsHelper.java
  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:25-29
Timestamp: 2025-06-23T14:18:25.298Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class methods like writeMsgpackArray will have their type signatures updated to be non-nullable since the calling sites ensure objects are never null when passed to these methods.
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: check (29)
  • GitHub Check: check (24)
  • GitHub Check: check (19)
  • GitHub Check: check (21)
  • GitHub Check: check
  • GitHub Check: check-liveobjects
  • GitHub Check: build
  • GitHub Check: check-rest-okhttp
  • GitHub Check: check-realtime-okhttp
  • GitHub Check: check-realtime
  • GitHub Check: check-rest
🔇 Additional comments (3)
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/MsgpackSerialization.kt (3)

26-88: Clean implementation of ObjectMessage serialization.

The write/read functions properly handle optional fields and maintain symmetry between serialization and deserialization.

Also applies to: 90-145


209-269: Excellent handling of required fields.

The implementation correctly validates that the required action field is present, throwing a clear exception if it's missing. This ensures data integrity without masking potential protocol errors.


657-662: Well-designed JSON value handling.

The approach of serializing JSON objects/arrays as strings with an encoding field is elegant and avoids nested complexity while maintaining type safety during deserialization.

Also applies to: 703-714

@sacOO7 sacOO7 force-pushed the chore/liveojects-serialization-without-msgpack-deps branch from 7755418 to 6f55903 Compare June 23, 2025 14:52
@github-actions github-actions bot temporarily deployed to staging/pull/1106/features June 23, 2025 14:53 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1106/javadoc June 23, 2025 14:55 Inactive
1. Made LiveObjectSerializer variable thread safe inside LiveObjectsHelper
2. Added null check for MessageUnpacker inside readObjectMessage
@sacOO7 sacOO7 force-pushed the chore/liveojects-serialization-without-msgpack-deps branch from 6f55903 to 36f9844 Compare June 23, 2025 14:58
@github-actions github-actions bot temporarily deployed to staging/pull/1106/features June 23, 2025 14:58 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1106/javadoc June 23, 2025 15:00 Inactive
@sacOO7 sacOO7 changed the title [ECO-5386] Liveobjects serialization without msgpack (jackson) deps [ECO-5386] Liveobjects serialization without jackson deps Jun 24, 2025
@github-actions github-actions bot temporarily deployed to staging/pull/1106/features June 24, 2025 09:59 Inactive
@sacOO7 sacOO7 force-pushed the chore/liveojects-serialization-without-msgpack-deps branch from de8a957 to 284837a Compare June 24, 2025 10:00
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/DefaultSerialization.kt (1)

12-15: Fix inconsistent documentation reference.

The documentation mentions "Jackson and Gson" but the implementation only uses Gson for JSON operations. MessagePack operations use the msgpack-java library directly.

- * of ObjectMessage arrays for both JSON and MessagePack formats using Jackson and Gson.
+ * of ObjectMessage arrays for both JSON and MessagePack formats using Gson and msgpack-java.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36f9844 and 6fa439d.

📒 Files selected for processing (3)
  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/DefaultSerialization.kt (1 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt (4 hunks)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/fixtures/ObjectMessageFixtures.kt (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/fixtures/ObjectMessageFixtures.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • live-objects/src/test/kotlin/io/ably/lib/objects/unit/ObjectMessageSizeTest.kt
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:25-29
Timestamp: 2025-06-23T14:18:25.315Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class methods like writeMsgpackArray will have their type signatures updated to be non-nullable since the calling sites ensure objects are never null when passed to these methods.
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/DefaultSerialization.kt (2)
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:25-29
Timestamp: 2025-06-23T14:18:25.315Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class methods like writeMsgpackArray will have their type signatures updated to be non-nullable since the calling sites ensure objects are never null when passed to these methods.
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:38-46
Timestamp: 2025-06-23T14:14:17.847Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class uses intentional unsafe casting (`objects as Array<ObjectMessage>`) without type validation in both writeMsgpackArray and asJsonArray methods. This is a deliberate design decision to keep the dynamically-loaded class simple and let ClassCastException occur naturally for type mismatches.
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: check-liveobjects
  • GitHub Check: check-realtime-okhttp
  • GitHub Check: check-rest-okhttp
  • GitHub Check: check-rest
  • GitHub Check: check-realtime
  • GitHub Check: check
  • GitHub Check: check (29)
  • GitHub Check: check (24)
  • GitHub Check: check (19)
  • GitHub Check: check (21)
  • GitHub Check: build
🔇 Additional comments (5)
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/DefaultSerialization.kt (5)

1-1: LGTM: Appropriate suppression for intentional unsafe casting.

The file-level suppression is correctly applied given the intentional unsafe casting used in the implementation methods, as confirmed by the retrieved learnings.


20-23: LGTM: Clean MessagePack array deserialization.

The method correctly unpacks the array header and creates an array of ObjectMessage instances using the appropriate helper method.


25-29: LGTM: Intentional unsafe casting as per design decision.

The unsafe casting on line 26 is intentional according to the retrieved learnings, allowing ClassCastException to occur naturally for type mismatches while keeping the dynamically-loaded class simple.


31-36: LGTM: Robust JSON array deserialization with proper error handling.

The method correctly handles JSON array parsing with appropriate error checking for non-JsonObject elements, providing clear error messages for debugging.


38-46: LGTM: Consistent JSON array serialization approach.

The method follows the same intentional unsafe casting pattern as writeMsgpackArray and correctly converts ObjectMessage instances to JsonObjects.

Copy link
Contributor

@ttypic ttypic left a comment

Choose a reason for hiding this comment

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

LGTM

return out.toByteArray();
} catch(IOException e) { return null; }
} catch (IOException ioe) {
throw AblyException.fromThrowable(ioe);
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you double-check that we won't introduce regression here

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Actually, there's no point in returning null when writeMsgpack fails.
Catching error silently means although our send/publish operation failed, we are not returning any error for the operation. This is not expected ( even from customer use-case point of view ) and relevant error should be thrown to understand and fix the failed operation.
PS. I faced similar issue when writeMsgpack failed for publish op. and was not able to trace the error thrown for the same.

Copy link
Collaborator Author

@sacOO7 sacOO7 Jun 30, 2025

Choose a reason for hiding this comment

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

Also, we already throw error for similar readMsgpack method =>

public static ProtocolMessage readMsgpack(byte[] packed) throws AblyException {
try {
MessageUnpacker unpacker = Serialisation.msgpackUnpackerConfig.newUnpacker(packed);
return ProtocolMessage.fromMsgpack(unpacker);
} catch (IOException ioe) {
throw AblyException.fromThrowable(ioe);
}
}

Seems, the relevant code for the writeMsgpack method wasn't updated.

@sacOO7
Copy link
Collaborator Author

sacOO7 commented Jun 30, 2025

Closing in favor of #1109

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.

LiveObject: Setup object serialization

3 participants