Skip to content

Conversation

@kabir
Copy link
Collaborator

@kabir kabir commented Sep 25, 2025

Interaction with the RDBMS happens with JPA.

Also renamed the JPA TaskStore AgentCard and AgentExecutor test producers since I am not a fan of having lots of classes with the same name

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @kabir, 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 delivers a significant enhancement by introducing a new module that enables the persistence of push notification configurations using a relational database via JPA. This change moves away from an in-memory storage solution, providing greater durability and scalability for managing push notification settings. The implementation is designed for ease of adoption, acting as a direct replacement for existing in-memory stores, and is thoroughly tested to ensure robust operation.

Highlights

  • New JPA-backed PushNotificationConfigStore: Introduced a new module, pushnotificationconfigstore-database-jpa, which provides a JPA-based implementation for persisting PushNotificationConfig objects to a relational database. This replaces the default in-memory store, offering persistent storage.
  • Drop-in Replacement: The new JpaDatabasePushNotificationConfigStore is designed as a drop-in replacement for the InMemoryPushNotificationConfigStore, annotated to take precedence automatically.
  • Database Schema and Configuration: The module defines a database schema for a2a_push_notification_configs with a composite primary key and includes detailed configuration examples for both Quarkus and WildFly/Jakarta EE environments.
  • Comprehensive Testing: Extensive unit and integration tests have been added to ensure the correct functionality and reliability of the JPA-backed PushNotificationConfigStore.
  • Documentation and Build Updates: The main extras/README.md and the parent pom.xml have been updated to include the new module. Additionally, the taskstore-database-jpa/README.md was updated for consistency in database naming.
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 introduces a new module for a JPA-backed PushNotificationConfigStore, which is a great addition for persistent storage. The implementation is solid and well-tested with both unit and integration tests. My review includes a few suggestions for improvement, mainly around code cleanup (removing unused imports), consistency (adding newlines at end of files), a small fix in the documentation, and a performance optimization in the setInfo method to make it more efficient.

Interaction with the RDBMS happens with JPA
```xml
<dependency>
<groupId>io.github.a2asdk</groupId>
<artifactId>a2a-java-extras-pushnotificationconfigstore-database-jpa</artifactId>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Very minor, wondering if we should add some hyphens in pushnotificationconfigstore

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@fjuma I'm not sure :-) I originally had some, but then noticed that the taskstore one did not. But I agree it is a bit long.
How about push-notification-config-store, and renaming the other one to task-store?

Copy link
Collaborator

Choose a reason for hiding this comment

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

That sounds good to me.

@kabir
Copy link
Collaborator Author

kabir commented Sep 26, 2025

/gemini review

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 introduces a valuable feature: a JPA-backed implementation of PushNotificationConfigStore, allowing push notification configurations to be persisted in a relational database. This is a great enhancement for production deployments. The implementation is well-structured, using standard JPA practices with entities and an embedded ID. The addition of comprehensive unit and integration tests ensures the new component is robust and works as expected. The refactoring to rename test utility classes for better clarity is also a welcome improvement. My review includes a few suggestions to refine the JPA usage and improve code clarity.

Comment on lines 51 to 56
// Create new entity
JpaPushNotificationConfig jpaConfig = JpaPushNotificationConfig.createFromConfig(taskId, notificationConfig);
em.merge(jpaConfig);
LOGGER.debug("Persisted new PushNotificationConfig for Task '{}' with ID: {}",
taskId, notificationConfig.id());
}
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 persisting a new entity instance, em.persist() is generally preferred over em.merge(). While merge works, it's designed to handle detached entities by copying their state to a managed instance. Since you've confirmed the entity is new with em.find(), using persist is more idiomatic and can be slightly more efficient as it doesn't need to perform a check to see if the entity is already managed.

                // Create new entity
                JpaPushNotificationConfig jpaConfig = JpaPushNotificationConfig.createFromConfig(taskId, notificationConfig);
                em.persist(jpaConfig);
                LOGGER.debug("Persisted new PushNotificationConfig for Task '{}' with ID: {}",
                        taskId, notificationConfig.id());
            

Comment on lines +92 to +95
} catch (Exception e) {
LOGGER.error("Failed to retrieve PushNotificationConfigs for Task '{}'", taskId, e);
throw e;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The catch (Exception e) block is too broad. It's better to catch more specific exceptions. In this context, the operations within the try block (JPA queries and stream processing of deserialized objects) are expected to throw RuntimeException subclasses (like PersistenceException or the one we throw for JSON errors). Catching Exception could unintentionally catch checked exceptions that are not declared in the method signature, or other unexpected exceptions. To make the code safer and more explicit, you should catch RuntimeException.

        } catch (RuntimeException e) {
            LOGGER.error("Failed to retrieve PushNotificationConfigs for Task '{}'", taskId, e);
            throw e;
        }

Comment on lines 54 to 60
public void setConfig(String taskId, PushNotificationConfig config) throws JsonProcessingException {
configJson = Utils.OBJECT_MAPPER.writeValueAsString(config);
if (this.id == null) {
this.id = new TaskConfigId(taskId, config.id());
}
this.config = config;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The setConfig method's responsibility is a bit unclear because it contains logic to set the entity's ID. An entity's primary key should be immutable after it's been persisted. While the logic is guarded by a null check, it's better to separate the concerns of creation and updating. The createFromConfig factory method already handles ID assignment during creation. This method should focus solely on updating the configuration data of an existing entity.

I suggest simplifying setConfig to only update the configJson and config fields, and removing the taskId parameter. The call in JpaDatabasePushNotificationConfigStore would then be simplified to existingJpaConfig.setConfig(notificationConfig);.

    public void setConfig(PushNotificationConfig config) throws JsonProcessingException {
        configJson = Utils.OBJECT_MAPPER.writeValueAsString(config);
        this.config = config;
    }

@fjuma fjuma merged commit 3f89c77 into a2aproject:main Sep 26, 2025
4 checks passed
kabir added a commit to kabir/a2a-java that referenced this pull request Dec 23, 2025
…#301)

Interaction with the RDBMS happens with JPA.

Also renamed the JPA TaskStore AgentCard and AgentExecutor test
producers since I am not a fan of having lots of classes with the same
name
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.

2 participants