-
Notifications
You must be signed in to change notification settings - Fork 96
fix: Encapsulate the payload of Push notifications #492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Summary of ChangesHello @jmesnil, 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 refactors how push notification payloads are serialized and deserialized to conform with the A2A protocol's specification for payload encapsulation. It introduces a new utility method to wrap Highlights
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this 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 encapsulates the push notification payload with a kind field, aligning with the A2A protocol specification. The implementation introduces a Utils.marshalFrom method to handle the serialization, and updates the server and test code to accommodate this new structure. My review focuses on improving the test code's maintainability by addressing duplicated logic and suggesting a more robust parsing strategy. I've also pointed out a few unused imports that can be cleaned up.
server-common/src/test/java/io/a2a/server/requesthandlers/AbstractA2ARequestHandlerTest.java
Outdated
Show resolved
Hide resolved
server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java
Outdated
Show resolved
Hide resolved
server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java
Outdated
Show resolved
Hide resolved
8d20f65 to
101ddf3
Compare
1d36bdc to
be38665
Compare
be38665 to
084f2f2
Compare
|
/gemini review |
The payload of push notifications is encapsulated by the `kind` of payload as specified in [§ 4.3.3. Push Notification Payload](https://a2a-protocol.org/latest/specification/#433-push-notification-payload) This commit only works for `task` payload and will required more work to support additional payloads (tracked by a2aproject#490). This fixes a2aproject#491 Signed-off-by: Jeff Mesnil <[email protected]>
084f2f2 to
aa41de5
Compare
There was a problem hiding this 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 correctly encapsulates the push notification payload by wrapping it in a JSON object with a kind field, as required by the specification. The introduction of Utils.marshalFrom centralizes this serialization logic effectively. My review includes suggestions to improve the test code by refactoring the duplicated payload-unwrapping logic into a new, more robust utility method. This will enhance maintainability and make the test deserialization logic less brittle.
| @Override | ||
| public A2AHttpResponse post() throws IOException, InterruptedException { | ||
| tasks.add(Utils.OBJECT_MAPPER.readValue(body, Task.TYPE_REFERENCE)); | ||
| JsonNode root = Utils.OBJECT_MAPPER.readTree(body); | ||
| // This will need to be updated for #490 to unmarshall based on the kind of payload | ||
| JsonNode taskNode = root.elements().next(); | ||
| Task task = Utils.OBJECT_MAPPER.treeToValue(taskNode, Task.TYPE_REFERENCE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block of code for deserializing the wrapped task has a couple of areas for improvement:
-
Robustness:
root.elements().next()will throw aNoSuchElementExceptionif the JSON object is empty. It's better to validate that the object contains exactly one field, as per the specification, for example by checkingroot.size(). -
Code Duplication: This logic is duplicated in
PushNotificationSenderTest.java.
To address both points and improve maintainability, you could extract this logic into a new, more robust helper method in io.a2a.util.Utils. This method would be the inverse of marshalFrom. For example:
// In Utils.java
public static <T> T unmarshalWrappedFrom(String data, TypeReference<T> typeRef) throws JsonProcessingException {
JsonNode root = OBJECT_MAPPER.readTree(data);
if (root.size() != 1) {
throw new com.fasterxml.jackson.databind.exc.MismatchedInputException(null, "Expected a single field in the JSON payload, but found " + root.size());
}
JsonNode payloadNode = root.elements().next();
return OBJECT_MAPPER.treeToValue(payloadNode, typeRef);
}Then you could simplify this block to just:
tasks.add(Utils.unmarshalWrappedFrom(body, Task.TYPE_REFERENCE));There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this code will be refined for #490 when additional kind of payload will be supported and will follow these guidelines
| try { | ||
| Task task = Utils.OBJECT_MAPPER.readValue(body, Task.TYPE_REFERENCE); | ||
| JsonNode root = Utils.OBJECT_MAPPER.readTree(body); | ||
| // This assumes there is always one field in the outer JSON object. | ||
| // This will need to be updated for #490 to unmarshall based on the kind of payload | ||
| JsonNode taskNode = root.elements().next(); | ||
| Task task = Utils.OBJECT_MAPPER.treeToValue(taskNode, Task.TYPE_REFERENCE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block of code for deserializing the wrapped task has a couple of areas for improvement:
-
Robustness:
root.elements().next()will throw aNoSuchElementExceptionif the JSON object is empty. It's better to validate that the object contains exactly one field, as per the specification, for example by checkingroot.size(). -
Code Duplication: This logic is duplicated in
AbstractA2ARequestHandlerTest.java.
To address both points and improve maintainability, you could extract this logic into a new, more robust helper method in io.a2a.util.Utils. This method would be the inverse of marshalFrom. For example:
// In Utils.java
public static <T> T unmarshalWrappedFrom(String data, TypeReference<T> typeRef) throws JsonProcessingException {
JsonNode root = OBJECT_MAPPER.readTree(data);
if (root.size() != 1) {
throw new com.fasterxml.jackson.databind.exc.MismatchedInputException(null, "Expected a single field in the JSON payload, but found " + root.size());
}
JsonNode payloadNode = root.elements().next();
return OBJECT_MAPPER.treeToValue(payloadNode, typeRef);
}Then you could simplify this block to just:
tasks.add(Utils.unmarshalWrappedFrom(body, Task.TYPE_REFERENCE));There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
idem, will be refined for #490
|
/gemini summary |
Summary of ChangesThis pull request implements a crucial step towards standardizing push notification payloads by encapsulating them according to the A2A protocol specification. It introduces a new utility for structured serialization of Highlights
Changelog
Activity
|
|
I'm not sure that the TCK tests run by the GitHub action is correctly reporting its status. When I look at the logs for this PR, I have failures (eg https://github.com/a2aproject/a2a-java/actions/runs/19736796539/job/56550560615#step:11:28) but the I'll have a look but it seems that the TCK is expecting to get directly the payload from the push notifications and is not following the spec that mandates to have it wrapped in its kind ( |
The payload of push notifications is encapsulated by the
kindof payload as specified in § 4.3.3. Push Notification PayloadThis commit only works for
taskpayload and will required more work to support additional payloads (tracked by #490).This fixes #491
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:
CONTRIBUTINGGuide.fix:which represents bug fixes, and correlates to a SemVer patch.feat:represents a new feature, and correlates to a SemVer minor.feat!:, orfix!:,refactor!:, etc., which represent a breaking change (indicated by the!) and will result in a SemVer major.Fixes #491🦕