Skip to content

Conversation

@ttypic
Copy link
Contributor

@ttypic ttypic commented Jun 5, 2025

Add support for managing message annotations via Rest and Realtime APIs

Introduced new classes and functionality to enable creating, retrieving, and deleting annotations on messages, both synchronously and asynchronously. Extended protocol support to handle annotation operations and added serialization/deserialization logic for annotations and summaries.

Summary by CodeRabbit

  • New Features

    • Introduced comprehensive support for annotations on messages, including publishing, deleting, retrieving, and subscribing within realtime and REST channels.
    • Added annotation summaries to messages, enhancing metadata visibility.
    • Enhanced protocol messages to support annotation actions and their serialization.
    • Provided new APIs and utilities for annotation management and serialization in JSON and MessagePack formats.
  • Bug Fixes

    • Improved message decoding logic to avoid errors when message data is empty.
  • Tests

    • Added extensive tests covering annotation publishing, subscription, retrieval, and pagination.
    • Updated test utilities and fixtures loading to improve test data management.
  • Chores

    • Removed obsolete submodule references and related configuration files.

@ttypic ttypic requested a review from sacOO7 June 5, 2025 12:11
@coderabbitai
Copy link

coderabbitai bot commented Jun 5, 2025

Walkthrough

This change introduces support for message annotations (such as reactions) in the Ably Java library. It adds new classes and methods for creating, publishing, retrieving, serializing, and subscribing to annotations on messages via both REST and realtime APIs. Comprehensive tests and serialization logic for annotations and summaries are also included.

Changes

File(s) Change Summary
lib/src/main/java/io/ably/lib/realtime/ChannelBase.java, lib/src/main/java/io/ably/lib/rest/ChannelBase.java Added annotations field to channel classes; integrated annotation handling in protocol message flow; added method to send protocol messages.
lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotations.java, lib/src/main/java/io/ably/lib/rest/RestAnnotations.java Introduced new classes for managing annotations (publish, delete, get, subscribe) on channels via realtime and REST APIs.
lib/src/main/java/io/ably/lib/types/Annotation.java, lib/src/main/java/io/ably/lib/types/AnnotationAction.java, lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java Added new types and serializers for annotations, including enum for actions, serialization/deserialization for MessagePack and JSON, and error handling.
lib/src/main/java/io/ably/lib/types/Message.java, lib/src/main/java/io/ably/lib/types/Summary.java, lib/src/main/java/io/ably/lib/types/ProtocolMessage.java Added support for annotation summaries in messages, integrated annotations into protocol message serialization/deserialization, and updated enums and logic for annotation actions.
lib/src/main/java/io/ably/lib/util/Serialisation.java Registered new serializers for annotation-related types in Gson configuration.
lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java, lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java Added and registered new test class for annotation feature, covering publish, subscribe, and retrieval scenarios.
lib/src/test/java/io/ably/lib/test/common/Setup.java, lib/src/test/resources/local/testAppSpec.json Added support for a mutable namespace in test setup and resources.
.gitmodules, lib/src/test/resources/ably-common Removed ably-common submodule and its reference.
lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java, lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceTest.java, lib/src/test/java/io/ably/lib/test/util/AblyCommonsReader.java, lib/src/test/java/io/ably/lib/util/CryptoMessageTest.java Replaced JSON fixture loading from local submodule with HTTP-based AblyCommonsReader utility for test data access.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Channel
    participant RealtimeAnnotations
    participant RestAnnotations
    participant AblyBackend

    Client->>Channel: publish(message)
    Channel->>RealtimeAnnotations: publish(messageSerial, annotation)
    RealtimeAnnotations->>Channel: sendProtocolMessage(annotation)
    Channel->>AblyBackend: send ProtocolMessage (annotation)
    AblyBackend-->>Channel: ProtocolMessage (annotation)
    Channel->>RealtimeAnnotations: onAnnotation(protocolMessage)
    RealtimeAnnotations->>Client: notify AnnotationListener

    Client->>RestAnnotations: get(messageSerial)
    RestAnnotations->>AblyBackend: HTTP GET /annotations
    AblyBackend-->>RestAnnotations: annotation data
    RestAnnotations-->>Client: PaginatedResult<Annotation>
Loading

Assessment against linked issues

Objective Addressed Explanation
Implement message reaction (annotation) feature with support for publishing, subscribing, retrieving, and serializing annotations on messages (ECO-5065)
Add tests for annotation publish, subscribe, and retrieval (ECO-5065)
Integrate annotation support in protocol message handling and serialization (ECO-5065)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Removal of ably-common submodule reference and .gitmodules file (.gitmodules, lib/src/test/resources/ably-common) Removing a submodule is unrelated to the annotation feature and not mentioned in the objectives.
Addition of mutableMessages field in test Namespace (lib/src/test/java/io/ably/lib/test/common/Setup.java) This field is not referenced in the linked objectives and appears to be a test infrastructure change.
Addition of "mutable" namespace in testAppSpec (lib/src/test/resources/local/testAppSpec.json) This test resource update is not directly related to annotation functionality.
Replacement of JSON fixture loading from local submodule to HTTP-based AblyCommonsReader in tests (lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java, lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceTest.java, lib/src/test/java/io/ably/lib/test/util/AblyCommonsReader.java, lib/src/test/java/io/ably/lib/util/CryptoMessageTest.java) This change affects test data loading mechanism and is unrelated to the annotation feature objectives.

Poem

In the meadow of code, new features bloom bright,
Reactions and annotations now dance in the light.
With messages cheered and emojis in tow,
The tests leap and bound, all passing in flow.
🐇 Hopping with joy, this rabbit declares:
“Annotations are here—let’s celebrate in pairs!”

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.38.1)
lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceTest.java
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Commit Unit Tests in branch ECO-5065/annotation-support
  • Post Copyable Unit Tests in Comment

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.

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: 18

🔭 Outside diff range comments (1)
lib/src/main/java/io/ably/lib/types/ProtocolMessage.java (1)

137-145: ⚠️ Potential issue

Missing field count update for annotations.

The fieldCount calculation doesn't include the annotations field, which will cause incorrect MessagePack header size when annotations are present.

Add this to the field count calculation:

 int fieldCount = 1; //action
 if(channel != null) ++fieldCount;
 if(msgSerial != null) ++fieldCount;
 if(messages != null) ++fieldCount;
 if(presence != null) ++fieldCount;
 if(auth != null) ++fieldCount;
 if(flags != 0) ++fieldCount;
 if(params != null) ++fieldCount;
 if(channelSerial != null) ++fieldCount;
+if(annotations != null) ++fieldCount;
 packer.packMapHeader(fieldCount);

Also applies to: 181-184

🧹 Nitpick comments (3)
lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java (2)

33-34: Consider reducing the test timeout duration.

A 300-second timeout seems excessive for these tests. Consider reducing it to align with other test timeouts in the suite.


143-143: Use assertFalse for boolean negation.

For better readability, use assertFalse instead of assertTrue with negation.

-assertTrue(!result.hasNext());
+assertFalse(result.hasNext());
lib/src/main/java/io/ably/lib/types/Summary.java (1)

124-124: Make constructor visibility consistent

The constructor has package-private visibility while other constructors in the inner classes are public.

-SummaryTotal(int total) {
+public SummaryTotal(int total) {
     this.total = total;
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e00af51 and f07c984.

📒 Files selected for processing (15)
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (5 hunks)
  • lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/rest/ChannelBase.java (2 hunks)
  • lib/src/main/java/io/ably/lib/rest/RestAnnotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Annotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/AnnotationAction.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/ChannelMode.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Message.java (7 hunks)
  • lib/src/main/java/io/ably/lib/types/MessageAction.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java (6 hunks)
  • lib/src/main/java/io/ably/lib/types/Summary.java (1 hunks)
  • lib/src/main/java/io/ably/lib/util/Serialisation.java (2 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java (1)
lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotation.java (1)
  • RealtimeAnnotation (31-284)
🔇 Additional comments (26)
lib/src/main/java/io/ably/lib/types/MessageAction.java (1)

7-7:

Details

✅ Verification successful

Verify all references to the old constant name have been updated.

The rename from META_OCCUPANCY to META is semantically appropriate for supporting broader metadata functionality including annotations. The ordinal position is preserved, maintaining backward compatibility for serialized data.


🏁 Script executed:

#!/bin/bash
# Search for any remaining references to the old constant name
rg "META_OCCUPANCY" --type java

Length of output: 31


To ensure we catch any stray references (in Java or elsewhere), let’s broaden the search across all files:


🏁 Script executed:

#!/bin/bash
rg "META_OCCUPANCY"

Length of output: 19


All references to META_OCCUPANCY have been removed

No occurrences of the old constant name were found across the codebase after renaming to META. The change preserves the original ordinal (3), maintains backward compatibility for serialized data, and aligns with the expanded metadata use case.

Approving the change.

lib/src/main/java/io/ably/lib/util/Serialisation.java (2)

14-15: LGTM: Imports are appropriately added for new annotation types.

The imports for Annotation, AnnotationAction, and Summary are correctly placed and will be used in the serializer registration below.

Also applies to: 21-21


54-56: LGTM: Serializer registrations follow established patterns.

The custom serializers for annotation-related types are correctly registered using the same pattern as existing types. This ensures proper JSON and MessagePack serialization support for the new annotation functionality.

lib/src/main/java/io/ably/lib/types/ChannelMode.java (1)

27-35:

Details

✅ Verification successful

LGTM: New annotation channel modes are properly implemented.

The new annotation_publish and annotation_subscribe enum constants follow the established patterns with consistent documentation and proper flag mapping. This correctly extends the channel capabilities for annotation functionality.


🏁 Script executed:

#!/bin/bash
# Verify that the referenced flags exist in ProtocolMessage.Flag
ast-grep --pattern $'enum Flag {
  $$$
  annotation_publish$_,
  $$$
  annotation_subscribe$_,
  $$$
}'

Length of output: 104


🏁 Script executed:

#!/bin/bash
# Locate the Java source file containing `enum Flag` and verify the new flags
flag_file=$(rg -l "enum Flag" -t java | head -n1)
echo "Found Flag enum in: $flag_file"
if [[ -n "$flag_file" ]]; then
  echo "--- Checking for annotation_publish ---"
  rg -n "annotation_publish" "$flag_file" || echo "annotation_publish not found"
  echo "--- Checking for annotation_subscribe ---"
  rg -n "annotation_subscribe" "$flag_file" || echo "annotation_subscribe not found"
else
  echo "No `enum Flag` definition found in Java sources."
fi

Length of output: 784


✅ Annotation Channel Modes Correctly Implemented

Verified that ProtocolMessage.Flag defines both annotation_publish (line 71) and annotation_subscribe (line 72). The new enum constants in ChannelMode.java are named, documented, and mapped consistently with existing patterns.

lib/src/main/java/io/ably/lib/rest/ChannelBase.java (2)

41-46: LGTM! Clean implementation following established patterns.

The annotations field follows the same pattern as the existing presence field with proper documentation and type declaration.


325-325: Constructor initialization looks correct.

The RestAnnotation initialization with appropriate parameters (name, HTTP client, options, channel options) follows the expected pattern.

lib/src/main/java/io/ably/lib/types/Message.java (5)

92-98: Excellent documentation and field declaration.

The summary field is well-documented with clear specification references and usage guidelines.


277-277: MsgPack serialization implementation is correct.

The field count increment and serialization logic follows the established pattern for other fields in the Message class.

Also applies to: 321-324


360-361: MsgPack deserialization is properly implemented.

The summary field reading logic is consistent with other field deserialization patterns.


537-543: JSON deserialization includes proper type checking.

Good defensive programming with explicit type checking and meaningful error messages.


580-582: JSON serialization is correctly implemented.

The summary field serialization uses the appropriate method and follows the pattern of other fields.

lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (5)

16-16: Import added for dependency.

Required import for RestAnnotation usage in constructor.


95-95: Annotations field follows established pattern.

Consistent with the presence field declaration pattern.


1301-1304: Constructor initialization is well-structured.

The RealtimeAnnotation initialization properly composes with RestAnnotation, creating a clean separation between realtime and REST functionality.


1371-1373: Message handling follows established pattern.

The annotation action handling delegates appropriately to the annotations instance, consistent with how presence messages are handled.


1400-1409: Clean abstraction for protocol message sending.

The sendProtocolMessage method provides a clean interface for sending protocol messages with completion callbacks, properly delegating to the connection manager.

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

31-52: Action enum additions look good.

The new protocol actions are added with proper sequential ordinal values, maintaining backward compatibility.


69-75: Flag enum additions are properly implemented.

The new channel mode flags use unique offsets and properly document reserved values, maintaining compatibility with the protocol specification.


88-94: Correct update to acknowledgment requirements.

The addition of object and annotation actions to the acknowledgment-required list is appropriate for data-bearing protocol messages.


122-122: Field addition follows established patterns.

The annotations array field is correctly added, consistent with how messages and presence arrays are handled.


244-246: Deserialization logic correctly implemented.

The annotations deserialization follows the established pattern and properly uses AnnotationSerializer.

lib/src/main/java/io/ably/lib/types/Annotation.java (5)

20-71: Well-structured annotation class with comprehensive documentation.

The class properly extends BaseMessage and includes all necessary fields with clear specification references.


76-123: MessagePack serialization correctly implemented.

The method properly counts fields including parent class fields and serializes all annotation data correctly.


125-158: Robust MessagePack deserialization with proper error handling.

Good use of tryFindByOrdinal for enum deserialization and proper delegation to parent class.


160-234: Comprehensive JSON serialization with proper validation.

The implementation includes appropriate type checking and error handling, especially for the extras field validation.


236-247: Correct enum serialization implementation.

The ActionSerializer properly handles AnnotationAction enum serialization using ordinal values.

@sacOO7
Copy link
Collaborator

sacOO7 commented Jun 5, 2025

Seems PR has few conflicts

@ttypic ttypic force-pushed the ECO-5065/annotation-support branch from f07c984 to fd48a6d Compare June 9, 2025 16:51
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: 2

♻️ Duplicate comments (8)
lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java (8)

24-26: ⚠️ Potential issue

Exception handling issue persists from previous review

The IOException is still being wrapped in RuntimeException, which prevents callers from handling I/O errors gracefully. This was previously flagged and remains unaddressed.

-        } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
+        } catch (IOException e) {
+            throw new AblyException(e.getMessage(), e);
+        }

45-47: ⚠️ Potential issue

Silent failure on serialization error still present

The method continues execution after logging IOException, potentially returning corrupted data. This critical issue from previous review remains unresolved.

         } catch (IOException e) {
             Log.e(TAG, e.getMessage(), e);
+            throw new RuntimeException("Failed to serialize annotation", e);
         }

69-69: ⚠️ Potential issue

Charset specification still missing

Creating String from bytes without specifying charset can lead to encoding issues. This was flagged in previous review but not fixed.

-        return Serialisation.gson.fromJson(new String(packed), Annotation[].class);
+        return Serialisation.gson.fromJson(new String(packed, StandardCharsets.UTF_8), Annotation[].class);

Add the import:

+import java.nio.charset.StandardCharsets;

90-95: ⚠️ Potential issue

Partial data issue from decode errors remains unaddressed

The method logs decode errors but continues processing, potentially returning incomplete data without caller awareness. This critical issue from previous review is still present.

Consider collecting decode errors and either throwing an exception or returning a result object that includes both successful annotations and errors.


17-27: Exception handling strategy needs improvement

The current implementation wraps IOException in RuntimeException, which prevents callers from handling I/O errors gracefully.


37-49: Handle IOException properly instead of just logging

The method logs the exception but continues execution, potentially returning a corrupted or incomplete request body.


68-70: Specify charset when creating String from bytes

Creating a String from bytes without specifying the charset can lead to encoding issues.


88-95: Consider failing fast on decode errors

The current implementation logs decode errors but continues processing remaining annotations. This could lead to partial data being returned without the caller knowing some annotations failed to decode.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f07c984 and fd48a6d.

📒 Files selected for processing (16)
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (6 hunks)
  • lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/rest/ChannelBase.java (2 hunks)
  • lib/src/main/java/io/ably/lib/rest/RestAnnotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Annotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/AnnotationAction.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Message.java (7 hunks)
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java (7 hunks)
  • lib/src/main/java/io/ably/lib/types/Summary.java (1 hunks)
  • lib/src/main/java/io/ably/lib/util/Serialisation.java (2 hunks)
  • lib/src/test/java/io/ably/lib/test/common/Setup.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java (2 hunks)
  • lib/src/test/resources/ably-common (1 hunks)
  • lib/src/test/resources/local/testAppSpec.json (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • lib/src/test/resources/ably-common
  • lib/src/test/java/io/ably/lib/test/common/Setup.java
🚧 Files skipped from review as they are similar to previous changes (12)
  • lib/src/main/java/io/ably/lib/util/Serialisation.java
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java
  • lib/src/main/java/io/ably/lib/rest/ChannelBase.java
  • lib/src/main/java/io/ably/lib/types/Message.java
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java
  • lib/src/main/java/io/ably/lib/types/AnnotationAction.java
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
  • lib/src/main/java/io/ably/lib/types/Annotation.java
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java
  • lib/src/main/java/io/ably/lib/rest/RestAnnotation.java
  • lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotation.java
  • lib/src/main/java/io/ably/lib/types/Summary.java
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: check (24)
  • GitHub Check: check (29)
  • GitHub Check: check (21)
  • GitHub Check: check (19)
  • GitHub Check: check
  • GitHub Check: build
🔇 Additional comments (10)
lib/src/test/resources/local/testAppSpec.json (6)

2-19: Test configuration updates look appropriate

The addition of new capability patterns ("cansubscribe:*", "pushenabled:*", "pushenabled:admin:*") and the revocable tokens configuration properly support the new annotation functionality.


20-24: Mutable namespace addition aligns with annotation features

The new "mutable" namespace with "mutableMessages": true correctly supports the message annotation capabilities being introduced.


25-51: Channel consolidation improves test organization

Consolidating multiple presence channels into a single "persisted:presence_fixtures" channel with diverse presence data provides better test coverage for annotation scenarios.


2-19: LGTM!

The updated keys configuration properly supports the new annotation and push capabilities with well-formed capability patterns.


20-24: LGTM!

The addition of the "mutable" namespace with mutableMessages support appropriately enables testing of annotation features that require message mutability.


25-51: LGTM!

The consolidated channel configuration provides comprehensive test coverage with diverse presence data types and encoding scenarios, supporting robust testing of the annotation feature.

lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java (4)

29-35: LGTM!

The method correctly handles IOException and has a clean implementation for reading annotation arrays.


51-53: LGTM!

Simple and correct implementation for creating JSON request bodies.


55-57: LGTM!

Clean factory method implementation.


59-66: LGTM!

Proper exception handling using AblyException for I/O errors.

@github-actions github-actions bot temporarily deployed to staging/pull/1096/javadoc June 9, 2025 16:58 Inactive
@ttypic ttypic force-pushed the ECO-5065/annotation-support branch from fd48a6d to 510e69d Compare June 9, 2025 17:33
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: 2

♻️ Duplicate comments (5)
lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java (5)

17-27: Add input validation and improve exception handling


29-35: Add null safety check for unpacker parameter


88-96: Consider failing fast on decode errors


37-49: 🛠️ Refactor suggestion

Handle exception properly and add input validation

The method has two issues:

  1. Logs IOException but continues execution, potentially returning corrupted data (as noted in previous review)
  2. Missing null check for annotations parameter

Add null validation:

 public static HttpCore.RequestBody asMsgpackRequest(Annotation[] annotations) {
+    if (annotations == null) {
+        throw new IllegalArgumentException("Annotations array cannot be null");
+    }
     ByteArrayOutputStream out = new ByteArrayOutputStream();

68-70: 🛠️ Refactor suggestion

Add charset specification and null check

Two issues need to be addressed:

  1. String creation from bytes without charset specification (as noted in previous review)
  2. Missing null check for packed parameter

Add null validation:

 public static Annotation[] readMessagesFromJson(byte[] packed) throws MessageDecodeException {
+    if (packed == null) {
+        throw new IllegalArgumentException("Packed data cannot be null");
+    }
     return Serialisation.gson.fromJson(new String(packed, StandardCharsets.UTF_8), Annotation[].class);
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fd48a6d and 510e69d.

📒 Files selected for processing (16)
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (6 hunks)
  • lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/rest/ChannelBase.java (2 hunks)
  • lib/src/main/java/io/ably/lib/rest/RestAnnotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Annotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/AnnotationAction.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Message.java (7 hunks)
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java (7 hunks)
  • lib/src/main/java/io/ably/lib/types/Summary.java (1 hunks)
  • lib/src/main/java/io/ably/lib/util/Serialisation.java (2 hunks)
  • lib/src/test/java/io/ably/lib/test/common/Setup.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java (2 hunks)
  • lib/src/test/resources/ably-common (1 hunks)
  • lib/src/test/resources/local/testAppSpec.json (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • lib/src/main/java/io/ably/lib/util/Serialisation.java
  • lib/src/test/resources/local/testAppSpec.json
🚧 Files skipped from review as they are similar to previous changes (12)
  • lib/src/test/resources/ably-common
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java
  • lib/src/main/java/io/ably/lib/rest/ChannelBase.java
  • lib/src/test/java/io/ably/lib/test/common/Setup.java
  • lib/src/main/java/io/ably/lib/types/AnnotationAction.java
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java
  • lib/src/main/java/io/ably/lib/types/Message.java
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
  • lib/src/main/java/io/ably/lib/types/Annotation.java
  • lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotation.java
  • lib/src/main/java/io/ably/lib/rest/RestAnnotation.java
  • lib/src/main/java/io/ably/lib/types/Summary.java
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: check
  • GitHub Check: check (29)
  • GitHub Check: check (21)
  • GitHub Check: check (24)
  • GitHub Check: build
  • GitHub Check: check (19)
🔇 Additional comments (4)
lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java (2)

55-57: LGTM - Clean factory method

Simple and clear factory method implementation.


59-66: LGTM - Proper exception handling

Good exception handling that converts IOException to AblyException appropriately.

lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java (2)

33-90: LGTM - Improved synchronization

Excellent improvement! The test now uses proper synchronization with CompletionWaiter and MessageWaiter instead of Thread.sleep, making it more reliable and faster. The test logic comprehensively covers annotation publishing and subscription for both realtime and REST channels.


160-186: LGTM - Well-designed test helper

Excellent test helper class that properly sets up channels with annotation modes and ensures proper cleanup. The channel configuration with annotation publish/subscribe modes is appropriate for testing annotation functionality.

@github-actions github-actions bot temporarily deployed to staging/pull/1096/javadoc June 9, 2025 17:40 Inactive
@ttypic ttypic force-pushed the ECO-5065/annotation-support branch from 510e69d to 3c5ed0e Compare June 9, 2025 17:40
@github-actions github-actions bot temporarily deployed to staging/pull/1096/features June 9, 2025 17:41 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: 6

♻️ Duplicate comments (4)
lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java (4)

17-27: Add null validation for parameters

The method should validate that both the annotations array and packer parameters are not null to prevent NullPointerExceptions and provide clearer error messages.


24-26: Reconsider exception handling strategy

Wrapping IOException in RuntimeException removes the ability for callers to handle I/O errors gracefully. Consider letting the IOException propagate or using AblyException.


29-35: Add null safety check

The method doesn't validate the unpacker parameter and could fail with unclear error messages if null is passed.


51-53: Add input validation for null annotations

The method should validate that the annotations parameter is not null to provide clearer error messages.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 510e69d and 3c5ed0e.

📒 Files selected for processing (17)
  • .gitmodules (0 hunks)
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (6 hunks)
  • lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/rest/ChannelBase.java (2 hunks)
  • lib/src/main/java/io/ably/lib/rest/RestAnnotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Annotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/AnnotationAction.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Message.java (7 hunks)
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java (7 hunks)
  • lib/src/main/java/io/ably/lib/types/Summary.java (1 hunks)
  • lib/src/main/java/io/ably/lib/util/Serialisation.java (2 hunks)
  • lib/src/test/java/io/ably/lib/test/common/Setup.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java (2 hunks)
  • lib/src/test/resources/ably-common (0 hunks)
  • lib/src/test/resources/local/testAppSpec.json (1 hunks)
💤 Files with no reviewable changes (2)
  • lib/src/test/resources/ably-common
  • .gitmodules
🚧 Files skipped from review as they are similar to previous changes (14)
  • lib/src/test/resources/local/testAppSpec.json
  • lib/src/main/java/io/ably/lib/util/Serialisation.java
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java
  • lib/src/test/java/io/ably/lib/test/common/Setup.java
  • lib/src/main/java/io/ably/lib/rest/ChannelBase.java
  • lib/src/main/java/io/ably/lib/types/Message.java
  • lib/src/main/java/io/ably/lib/types/AnnotationAction.java
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java
  • lib/src/main/java/io/ably/lib/types/Annotation.java
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java
  • lib/src/main/java/io/ably/lib/types/Summary.java
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
  • lib/src/main/java/io/ably/lib/rest/RestAnnotation.java
  • lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotation.java
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: check-liveobjects
  • GitHub Check: check-rest-okhttp
  • GitHub Check: check-realtime
  • GitHub Check: check-realtime-okhttp
  • GitHub Check: check-rest
  • GitHub Check: check (24)
  • GitHub Check: check
  • GitHub Check: check (29)
  • GitHub Check: build
  • GitHub Check: check (19)
  • GitHub Check: check (21)

@github-actions github-actions bot temporarily deployed to staging/pull/1096/javadoc June 9, 2025 17:47 Inactive
@ttypic ttypic force-pushed the ECO-5065/annotation-support branch from 3c5ed0e to a8191ed Compare June 9, 2025 18:50
@github-actions github-actions bot temporarily deployed to staging/pull/1096/features June 9, 2025 18:51 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: 6

♻️ Duplicate comments (10)
lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java (10)

17-27: 🛠️ Refactor suggestion

Add input validation

The method should validate that the annotations array and packer are not null to provide clearer error messages.

 public static void writeMsgpackArray(Annotation[] annotations, MessagePacker packer) {
+    if (annotations == null) {
+        throw new IllegalArgumentException("Annotations array cannot be null");
+    }
+    if (packer == null) {
+        throw new IllegalArgumentException("MessagePacker cannot be null");
+    }
     try {

24-26: ⚠️ Potential issue

Reconsider exception handling strategy

Wrapping IOException in RuntimeException removes the ability for callers to handle I/O errors gracefully. Consider letting the IOException propagate or using AblyException.

-} catch (IOException e) {
-    throw new RuntimeException(e.getMessage(), e);
-}
+} catch (IOException e) {
+    throw new AblyException(e.getMessage(), e);
+}

29-35: 🛠️ Refactor suggestion

Add null safety check

The method doesn't validate the unpacker parameter and could fail with unclear error messages if null is passed.

 public static Annotation[] readMsgpackArray(MessageUnpacker unpacker) throws IOException {
+    if (unpacker == null) {
+        throw new IllegalArgumentException("MessageUnpacker cannot be null");
+    }
     int count = unpacker.unpackArrayHeader();

37-49: ⚠️ Potential issue

Add null validation and improve error handling

The method lacks null validation for the annotations parameter and has inadequate error handling. The current implementation logs IOException but continues execution, potentially returning corrupted data.

 public static HttpCore.RequestBody asMsgpackRequest(Annotation[] annotations) {
+    if (annotations == null) {
+        throw new IllegalArgumentException("Annotations array cannot be null");
+    }
     ByteArrayOutputStream out = new ByteArrayOutputStream();
     try {
         MessagePacker packer = Serialisation.msgpackPackerConfig.newPacker(out);
         int count = annotations.length;
         packer.packArrayHeader(count);
         for (Annotation annotation : annotations) annotation.writeMsgpack(packer);
         packer.flush();
     } catch (IOException e) {
         Log.e(TAG, e.getMessage(), e);
+        throw new RuntimeException("Failed to serialize annotations", e);
     }
     return new HttpUtils.ByteArrayRequestBody(out.toByteArray(), "application/x-msgpack");
 }

51-53: 🛠️ Refactor suggestion

Add input validation for null annotations

The method should validate that the annotations parameter is not null to provide clearer error messages.

 public static HttpCore.RequestBody asJsonRequest(Annotation[] annotations) {
+    if (annotations == null) {
+        throw new IllegalArgumentException("Annotations array cannot be null");
+    }
     return new HttpUtils.JsonRequestBody(Serialisation.gson.toJson(annotations));
 }

55-57: 🛠️ Refactor suggestion

Add null validation for channelOptions parameter

The method should validate that the channelOptions parameter is not null before passing it to the AnnotationBodyHandler constructor.

 public static HttpCore.BodyHandler<Annotation> getAnnotationResponseHandler(ChannelOptions channelOptions) {
+    if (channelOptions == null) {
+        throw new IllegalArgumentException("ChannelOptions cannot be null");
+    }
     return new AnnotationBodyHandler(channelOptions);
 }

59-66: 🛠️ Refactor suggestion

Add null validation for packed parameter

The method should validate that the packed byte array is not null before processing to provide clearer error messages.

 public static Annotation[] readMsgpack(byte[] packed) throws AblyException {
+    if (packed == null) {
+        throw new IllegalArgumentException("Packed byte array cannot be null");
+    }
     try {
         MessageUnpacker unpacker = Serialisation.msgpackUnpackerConfig.newUnpacker(packed);
         return readMsgpackArray(unpacker);
     } catch (IOException ioe) {
         throw AblyException.fromThrowable(ioe);
     }
 }

68-70: ⚠️ Potential issue

Add null validation and specify charset

The method needs null validation for the packed parameter and should specify charset when creating String from bytes to avoid encoding issues.

 public static Annotation[] readMessagesFromJson(byte[] packed) throws MessageDecodeException {
+    if (packed == null) {
+        throw new IllegalArgumentException("Packed byte array cannot be null");
+    }
-    return Serialisation.gson.fromJson(new String(packed), Annotation[].class);
+    return Serialisation.gson.fromJson(new String(packed, StandardCharsets.UTF_8), Annotation[].class);
 }

You'll need to import java.nio.charset.StandardCharsets.


76-78: 🛠️ Refactor suggestion

Add null validation in constructor

The constructor should validate that channelOptions is not null to prevent potential issues in the handleResponseBody method.

 AnnotationBodyHandler(ChannelOptions channelOptions) {
+    if (channelOptions == null) {
+        throw new IllegalArgumentException("ChannelOptions cannot be null");
+    }
     this.channelOptions = channelOptions;
 }

81-101: ⚠️ Potential issue

Add parameter validation and improve decode error handling

The method lacks validation for contentType and body parameters. Additionally, the current decode error handling logs errors but continues processing, potentially returning partial data without the caller knowing some annotations failed to decode.

 @Override
 public Annotation[] handleResponseBody(String contentType, byte[] body) throws AblyException {
+    if (contentType == null) {
+        throw new IllegalArgumentException("Content type cannot be null");
+    }
+    if (body == null) {
+        throw new IllegalArgumentException("Response body cannot be null");
+    }
     try {
         Annotation[] annotations = null;
         if ("application/json".equals(contentType))
             annotations = readMessagesFromJson(body);
         else if ("application/x-msgpack".equals(contentType))
             annotations = readMsgpack(body);
         if (annotations != null) {
+            List<MessageDecodeException> decodeErrors = new ArrayList<>();
             for (Annotation annotation : annotations) {
                 try {
                     if (annotation.data != null) annotation.decode(channelOptions);
                 } catch (MessageDecodeException e) {
                     Log.e(TAG, e.errorInfo.message);
+                    decodeErrors.add(e);
                 }
             }
+            if (!decodeErrors.isEmpty()) {
+                throw new AblyException("Failed to decode " + decodeErrors.size() + " annotations", 400, 40000);
+            }
         }
         return annotations;
     } catch (MessageDecodeException e) {
         throw AblyException.fromThrowable(e);
     }
 }
🧹 Nitpick comments (1)
lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotations.java (1)

34-42: Consider using ConcurrentHashMap for better thread safety

While all access to typeListeners appears to be within synchronized methods, using ConcurrentHashMap would provide additional safety and potentially better performance under concurrent access.

 private final ChannelBase channel;
 private final RestAnnotations restAnnotations;
 private final AnnotationMulticaster listeners = new AnnotationMulticaster();
-private final Map<String, AnnotationMulticaster> typeListeners = new HashMap<>();
+private final Map<String, AnnotationMulticaster> typeListeners = new ConcurrentHashMap<>();
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3c5ed0e and a8191ed.

📒 Files selected for processing (17)
  • .gitmodules (0 hunks)
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (6 hunks)
  • lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotations.java (1 hunks)
  • lib/src/main/java/io/ably/lib/rest/ChannelBase.java (2 hunks)
  • lib/src/main/java/io/ably/lib/rest/RestAnnotations.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Annotation.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/AnnotationAction.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Message.java (7 hunks)
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java (7 hunks)
  • lib/src/main/java/io/ably/lib/types/Summary.java (1 hunks)
  • lib/src/main/java/io/ably/lib/util/Serialisation.java (2 hunks)
  • lib/src/test/java/io/ably/lib/test/common/Setup.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java (1 hunks)
  • lib/src/test/resources/ably-common (0 hunks)
  • lib/src/test/resources/local/testAppSpec.json (1 hunks)
💤 Files with no reviewable changes (2)
  • lib/src/test/resources/ably-common
  • .gitmodules
🚧 Files skipped from review as they are similar to previous changes (12)
  • lib/src/test/java/io/ably/lib/test/common/Setup.java
  • lib/src/test/resources/local/testAppSpec.json
  • lib/src/main/java/io/ably/lib/util/Serialisation.java
  • lib/src/main/java/io/ably/lib/rest/ChannelBase.java
  • lib/src/main/java/io/ably/lib/types/Message.java
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java
  • lib/src/main/java/io/ably/lib/types/AnnotationAction.java
  • lib/src/main/java/io/ably/lib/types/ProtocolMessage.java
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
  • lib/src/main/java/io/ably/lib/types/Annotation.java
  • lib/src/main/java/io/ably/lib/types/Summary.java
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: check-realtime-okhttp
  • GitHub Check: check-liveobjects
  • GitHub Check: check-realtime
  • GitHub Check: check-rest
  • GitHub Check: check-rest-okhttp
  • GitHub Check: build
  • GitHub Check: check (29)
  • GitHub Check: check (24)
  • GitHub Check: check (21)
  • GitHub Check: check (19)
  • GitHub Check: check

@github-actions github-actions bot temporarily deployed to staging/pull/1096/javadoc June 9, 2025 18:57 Inactive
@ttypic ttypic force-pushed the ECO-5065/annotation-support branch from a8191ed to 93d9b31 Compare June 10, 2025 09:26
@github-actions github-actions bot temporarily deployed to staging/pull/1096/features June 10, 2025 09:27 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1096/javadoc June 10, 2025 09:32 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1096/features June 10, 2025 11: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: 6

🧹 Nitpick comments (1)
lib/src/test/java/io/ably/lib/test/util/AblyCommonsReader.java (1)

12-14: Consider making the base URL configurable and using a stable reference.

The hard-coded URL points to the main branch which could be unstable. Consider:

  1. Making the base URL configurable via system properties
  2. Using a stable tag/release instead of main branch
  3. Adding validation for the URL format
public class AblyCommonsReader {
-    private static final String BASE_URL = "https://raw.githubusercontent.com/ably/ably-common/refs/heads/main/";
+    private static final String BASE_URL = System.getProperty("ably.commons.base.url", 
+        "https://raw.githubusercontent.com/ably/ably-common/refs/tags/v1.0.0/");
    private static Gson gson = new Gson();
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 93d9b31 and 594e97a.

📒 Files selected for processing (4)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (5 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceTest.java (3 hunks)
  • lib/src/test/java/io/ably/lib/test/util/AblyCommonsReader.java (1 hunks)
  • lib/src/test/java/io/ably/lib/util/CryptoMessageTest.java (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • lib/src/test/java/io/ably/lib/util/CryptoMessageTest.java
🧰 Additional context used
🧬 Code Graph Analysis (2)
lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (1)
lib/src/test/java/io/ably/lib/test/util/AblyCommonsReader.java (1)
  • AblyCommonsReader (12-52)
lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceTest.java (1)
lib/src/test/java/io/ably/lib/test/util/AblyCommonsReader.java (1)
  • AblyCommonsReader (12-52)
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: check (24)
  • GitHub Check: check (19)
  • GitHub Check: check (29)
  • GitHub Check: check (21)
  • GitHub Check: check-liveobjects
  • GitHub Check: build
  • GitHub Check: check-realtime-okhttp
  • GitHub Check: check-rest-okhttp
  • GitHub Check: check-rest
  • GitHub Check: check-realtime
  • GitHub Check: check
🔇 Additional comments (3)
lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (1)

63-63: File path constant updated correctly.

The path constant properly reflects the new location without the "ably-common/" prefix.

lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceTest.java (2)

45-45: LGTM - Import addition is correct.

The import for AblyCommonsReader is properly added and aligns with the refactoring to use remote JSON fixture loading.


78-78:

Details

✅ Verification successful

Verify the file path change is consistent.

The file path has been updated from "ably-common/test-resources/presence-messages-encoding.json" to "test-resources/presence-messages-encoding.json", removing the "ably-common/" prefix. This change aligns with fetching directly from the Ably Commons repository.

Verify that this path change is consistent across all test files that use similar fixtures:


🏁 Script executed:

#!/bin/bash
# Search for other test files that might reference the old path pattern
rg "ably-common/test-resources.*\.json" --type java
rg "test-resources.*encoding\.json" --type java

Length of output: 451


All test fixture paths updated consistently

  • Both RealtimePresenceTest.java and RealtimeMessageTest.java now reference JSON fixtures under test-resources/... without the ably-common/ prefix.
  • No remaining occurrences of ably-common/test-resources were found in any Java test files.

@github-actions github-actions bot temporarily deployed to staging/pull/1096/javadoc June 10, 2025 11:32 Inactive
@ttypic ttypic force-pushed the ECO-5065/annotation-support branch from 594e97a to 49978fa Compare June 10, 2025 12:16
@github-actions github-actions bot temporarily deployed to staging/pull/1096/features June 10, 2025 12:16 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1096/javadoc June 10, 2025 12:22 Inactive
Copy link
Collaborator

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

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

Apart from review comments, it seems publish, delete and get annotation methods have first param as Message overloads. This is true for both RestAnnotations and RealtimeAnnotations. Seems same exists in case of ably-js and allows to extract serial from message.

@sacOO7
Copy link
Collaborator

sacOO7 commented Jun 11, 2025

Apart from review comments, it seems publish, delete and get annotation methods have first param as Message overloads. This is true for both RestAnnotations and RealtimeAnnotations. Seems same exists in case of ably-js and allows to extract serial from message.

Since a new feature with public API has been added, you can check to update the corresponding README.
Apart from the above comments, PR looks good 👍

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: 4

♻️ Duplicate comments (8)
lib/src/main/java/io/ably/lib/types/Summary.java (3)

63-63: Use TypeToken for proper generic type handling

Using Map.class loses generic type information. This could lead to unchecked cast warnings or runtime ClassCastException.


74-74: Use TypeToken for proper generic type handling

Using List.class loses generic type information.


117-119: Add null check before using MessagePacker

The method should validate that the packer parameter is not null to prevent potential NPE.

lib/src/main/java/io/ably/lib/rest/RestAnnotations.java (3)

44-49: Add null validation in constructor

The constructor should validate input parameters to prevent NullPointerException later in the code.


173-176: Remove throws declaration from async method

Async methods typically don't throw checked exceptions. Any exceptions should be passed to the callback instead.


241-244: Avoid mutating input parameters

Modifying the annotation parameter is a side effect that can surprise callers. Consider creating a copy or using a builder pattern.

lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotations.java (2)

135-139: Avoid mutating input parameters

Similar to RestAnnotations, modifying the annotation parameter is a side effect that can surprise callers.


364-372: Fix inconsistent null handling between subscribe and unsubscribe

The subscribeImpl method converts null type to empty string, but unsubscribeImpl doesn't apply the same conversion, causing a mismatch.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 49978fa and 680d474.

📒 Files selected for processing (11)
  • lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotations.java (1 hunks)
  • lib/src/main/java/io/ably/lib/rest/RestAnnotations.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Summary.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/SummaryClientIdCounts.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/SummaryClientIdList.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/SummaryTotal.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (5 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceTest.java (3 hunks)
  • lib/src/test/java/io/ably/lib/test/util/AblyCommonsReader.java (1 hunks)
  • lib/src/test/java/io/ably/lib/types/SummaryTest.java (1 hunks)
  • lib/src/test/java/io/ably/lib/util/CryptoMessageTest.java (2 hunks)
✅ Files skipped from review due to trivial changes (3)
  • lib/src/main/java/io/ably/lib/types/SummaryTotal.java
  • lib/src/main/java/io/ably/lib/types/SummaryClientIdList.java
  • lib/src/main/java/io/ably/lib/types/SummaryClientIdCounts.java
🚧 Files skipped from review as they are similar to previous changes (4)
  • lib/src/test/java/io/ably/lib/util/CryptoMessageTest.java
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceTest.java
  • lib/src/test/java/io/ably/lib/test/util/AblyCommonsReader.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
lib/src/test/java/io/ably/lib/types/SummaryTest.java (1)
lib/src/main/java/io/ably/lib/types/Summary.java (1)
  • Summary (30-142)
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: check
  • 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 (21)
  • GitHub Check: check (24)
  • GitHub Check: check (19)
  • GitHub Check: check (29)
  • GitHub Check: build

Copy link
Collaborator

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

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

Lgtm.
You may optionally check whether the README needs updating—for example, by adding a snippet that demonstrates the use of annotations

@ttypic ttypic merged commit 9e81158 into main Jun 13, 2025
13 checks passed
@ttypic ttypic deleted the ECO-5065/annotation-support branch June 13, 2025 12:02
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.

3 participants