Skip to content

Conversation

@ehsavoie
Copy link
Collaborator

Description

Thank you for opening a Pull Request!
Before submitting your PR, there are a few things you can do to make sure it goes smoothly:

  • Follow the CONTRIBUTING Guide.
  • Make your Pull Request title in the https://www.conventionalcommits.org/ specification.
    • Important Prefixes for release-please:
      • fix: which represents bug fixes, and correlates to a SemVer patch.
      • feat: represents a new feature, and correlates to a SemVer minor.
      • feat!:, or fix!:, refactor!:, etc., which represent a breaking change (indicated by the !) and will result in a SemVer major.
  • Ensure the tests pass
  • Appropriate READMEs were updated (if necessary)

Fixes #<issue_number_goes_here> 🦕

Signed-off-by: Emmanuel Hugonnet <ehugonne@redhat.com>
@ehsavoie ehsavoie requested review from fjuma and kabir November 20, 2025 17:39
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ehsavoie, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request primarily focuses on improving the extensibility and debuggability of the event handling system. It achieves this by adjusting the visibility of core event queue methods to public, thereby allowing for more flexible overriding and interaction. Additionally, it enhances the logging capabilities for message events by providing a detailed string representation.

Highlights

  • Event Queue Extensibility: The signalQueuePollerStarted() and tap() methods in the EventQueue abstract class and its concrete implementations (MainQueue and ChildQueue) have been changed from package-private to public. This modification enhances the extensibility and overridability of the event queue, allowing external components to interact with these methods.
  • Improved Message Event Logging: A comprehensive toString() method has been added to the MessageEvent class. This provides a more detailed string representation of MessageEvent objects, including all fields of the encapsulated Message, which will aid in debugging and logging.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request aims to make the EventQueue overridable by changing the visibility of several methods. While this is a valid goal, the changes widen the API surface by using public instead of protected. My review includes suggestions to use protected to maintain better encapsulation, which is a more appropriate choice for methods intended for subclass extension rather than general public use. Additionally, I've provided a suggestion to improve the implementation of the toString() method in MessageEvent for better performance and readability.

public abstract void awaitQueuePollerStart() throws InterruptedException ;

abstract void signalQueuePollerStarted();
public abstract void signalQueuePollerStarted();
Copy link
Contributor

Choose a reason for hiding this comment

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

high

While making this method overridable is the goal, changing its visibility to public exposes it as part of the public API for all clients of EventQueue. This can be risky, as incorrect calls to signalQueuePollerStarted() could disrupt the queue's internal state management (e.g., related to awaitQueuePollerStart). To allow subclasses to override it without exposing it to all consumers, it's better to use the protected access modifier. This maintains better encapsulation while still allowing extension.

Suggested change
public abstract void signalQueuePollerStarted();
protected abstract void signalQueuePollerStarted();

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

if it is protected you can have a delegate

}

abstract EventQueue tap();
public abstract EventQueue tap();
Copy link
Contributor

Choose a reason for hiding this comment

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

high

To allow this method to be overridden by subclasses in other packages while maintaining good encapsulation, it's preferable to use the protected access modifier instead of public. Making it public exposes it to all consumers of the EventQueue class, which might not be the intention. protected correctly signals that this method is part of the extension API for subclasses.

Suggested change
public abstract EventQueue tap();
protected abstract EventQueue tap();

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

if it is protected you can have a delegate

}

EventQueue tap() {
public EventQueue tap() {
Copy link
Contributor

Choose a reason for hiding this comment

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

high

To align with the recommended change of making EventQueue.tap() a protected method, this overriding implementation should also be protected. This ensures consistent visibility and maintains the intended level of encapsulation.

Suggested change
public EventQueue tap() {
protected EventQueue tap() {

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

if it is protected you can have a delegate


@Override
void signalQueuePollerStarted() {
public void signalQueuePollerStarted() {
Copy link
Contributor

Choose a reason for hiding this comment

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

high

To align with the recommended change of making EventQueue.signalQueuePollerStarted() a protected method, this overriding implementation should also be protected. This keeps the API contract consistent across the class hierarchy.

Suggested change
public void signalQueuePollerStarted() {
protected void signalQueuePollerStarted() {


@Override
EventQueue tap() {
public EventQueue tap() {
Copy link
Contributor

Choose a reason for hiding this comment

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

high

To align with the recommended change of making EventQueue.tap() a protected method, this overriding implementation should also be protected. This ensures consistent visibility and maintains the intended level of encapsulation for the class hierarchy.

Suggested change
public EventQueue tap() {
protected EventQueue tap() {


@Override
void signalQueuePollerStarted() {
public void signalQueuePollerStarted() {
Copy link
Contributor

Choose a reason for hiding this comment

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

high

To align with the recommended change of making EventQueue.signalQueuePollerStarted() a protected method, this overriding implementation should also be protected. This keeps the API contract consistent and prevents unintended external calls.

Suggested change
public void signalQueuePollerStarted() {
protected void signalQueuePollerStarted() {

Comment on lines +27 to +36
String messageAsString = "{"
+ "role=" + message.getRole()
+ ", parts=" + message.getParts()
+ ", messageId=" + message.getMessageId()
+ ", contextId=" + message.getContextId()
+ ", taskId=" + message.getTaskId()
+ ", metadata=" + message.getMetadata()
+ ", kind=" + message.getKind()
+ ", referenceTaskIds=" + message.getReferenceTaskIds()
+ ", extensions=" + message.getExtensions() + '}';
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

For building strings from multiple parts, using java.util.StringJoiner (available since Java 8) is more efficient and readable than repeated string concatenation. It avoids creating multiple intermediate String objects and improves maintainability.

Suggested change
String messageAsString = "{"
+ "role=" + message.getRole()
+ ", parts=" + message.getParts()
+ ", messageId=" + message.getMessageId()
+ ", contextId=" + message.getContextId()
+ ", taskId=" + message.getTaskId()
+ ", metadata=" + message.getMetadata()
+ ", kind=" + message.getKind()
+ ", referenceTaskIds=" + message.getReferenceTaskIds()
+ ", extensions=" + message.getExtensions() + '}';
String messageAsString = new java.util.StringJoiner(", ", "{", "}")
.add("role=" + message.getRole())
.add("parts=" + message.getParts())
.add("messageId=" + message.getMessageId())
.add("contextId=" + message.getContextId())
.add("taskId=" + message.getTaskId())
.add("metadata=" + message.getMetadata())
.add("kind=" + message.getKind())
.add("referenceTaskIds=" + message.getReferenceTaskIds())
.add("extensions=" + message.getExtensions())
.toString();

@ehsavoie ehsavoie merged commit 9cfda0f into a2aproject:main Nov 20, 2025
10 checks passed
@jmesnil jmesnil added this to the 1.0.0 milestone Dec 11, 2025
@ehsavoie ehsavoie deleted the extensible branch December 19, 2025 16:23
kabir pushed a commit to kabir/a2a-java that referenced this pull request Dec 23, 2025
# Description

Thank you for opening a Pull Request!
Before submitting your PR, there are a few things you can do to make
sure it goes smoothly:

- [X] Follow the [`CONTRIBUTING` Guide](../CONTRIBUTING.md).
- [X] Make your Pull Request title in the
<https://www.conventionalcommits.org/> specification.
- Important Prefixes for
[release-please](https://github.com/googleapis/release-please):
- `fix:` which represents bug fixes, and correlates to a
[SemVer](https://semver.org/) patch.
- `feat:` represents a new feature, and correlates to a SemVer minor.
- `feat!:`, or `fix!:`, `refactor!:`, etc., which represent a breaking
change (indicated by the `!`) and will result in a SemVer major.
- [X] Ensure the tests pass
- [X] Appropriate READMEs were updated (if necessary)

Fixes #<issue_number_goes_here> 🦕

Signed-off-by: Emmanuel Hugonnet <ehugonne@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants