Skip to content

feat(gapic-generator-java): Extract resource name heuristicly#12207

Merged
blakeli0 merged 23 commits intomainfrom
feature/heuristic-filter
Mar 31, 2026
Merged

feat(gapic-generator-java): Extract resource name heuristicly#12207
blakeli0 merged 23 commits intomainfrom
feature/heuristic-filter

Conversation

@blakeli0
Copy link
Copy Markdown
Contributor

@blakeli0 blakeli0 commented Mar 26, 2026

This PR extracts resource name heuristically if there are no resource_reference configured for a request.

This logic only applies to the following proto packages:

  • google.cloud.compute.**
  • google.cloud.sql.**
  • google.cloud.bigquery.**

The exact logic is described in go/client-libraries:destination-resource-name. In a nutshell, a canonical resource name is extracted from the template by finding the version literal, then finding the last binding that is a literal/binding pair or named binding, and then extracting the segments between the version literal and the last binding (inclusive).

The logic is mostly implemented in PathTemplate, and used by AbstractTransportServiceStubClassComposer#createResourceNameExtractorClassInstance.

The generated code would be called in the same way as a regular resourceNameExtractor by TracedUnaryCallable.

@blakeli0 blakeli0 requested a review from a team as a code owner March 26, 2026 04:19
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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 implements a new heuristic for extracting resource names during GAPIC client library generation, allowing for more intelligent resource path construction. This heuristic is selectively enabled for specific proto packages to ensure controlled application. Additionally, the changes improve the robustness of endpoint context parsing, preventing failures when encountering malformed server address or port information.

Highlights

  • Heuristic Resource Name Extraction: Introduced a new heuristic for extracting resource names during GAPIC client library generation, allowing for more intelligent resource path construction based on known resource literals.
  • Proto Package Filtering: Implemented filtering for the new heuristic resource name extraction, enabling it only for specific proto packages (e.g., google.cloud.compute, google.cloud.sql, google.cloud.bigquery) to ensure controlled application.
  • PathTemplate Enhancements: Added new utility methods to PathTemplate to identify resource literals and construct canonical resource names, supporting the new heuristic extraction logic.
  • Endpoint Context Robustness: Enhanced the EndpointContext parsing logic to gracefully handle invalid server address or port formats, preventing failures and improving client stability.
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.

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.

@blakeli0 blakeli0 changed the title Filter heuristic resource name extraction by proto package feat(gapic-generator-java): filter heuristic resource name extraction by proto package Mar 26, 2026
Copy link
Copy Markdown
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 new functionality to the PathTemplate class, adding getResourceLiterals and getCanonicalResourceName methods to extract resource literals and canonical resource names from path templates, including support for complex patterns and named bindings. The GAPIC generator has been updated to leverage these new PathTemplate capabilities, enabling automatic generation of resource name extractors for client stubs, especially for methods in heuristic-enabled packages that lack explicit resource references. This involved defining AIP standard methods and heuristic-enabled packages, and updating associated golden files and proto definitions. Additionally, the EndpointContext in GAX was improved to handle invalid endpoint parsing for server address and port more gracefully, treating these as non-critical for client requests. Feedback includes refactoring the complex getCanonicalResourceName method, removing a dead keepBinding variable, correcting typos in test method names, addressing a debugging test method, fixing a typo in service.protoPakkage(), and improving the robustness of binding variable checks in createResourceNameExtractorClassInstance from String.contains() to a more precise regex.

@blakeli0 blakeli0 changed the title feat(gapic-generator-java): filter heuristic resource name extraction by proto package feat(gapic-generator-java): Extract resource name heuristicly Mar 26, 2026
Copy link
Copy Markdown
Contributor

@diegomarquezp diegomarquezp left a comment

Choose a reason for hiding this comment

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

Thanks for the PR. Added a few comments.

int literalCountInBinding = 0;
int currentBindingStartIndex = -1;

for (int i = 0; i < segments.size(); i++) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1 to gemini's comment on complexity of this method and splitting into private helpers. We could also add comments explaining the purpose of each if or nested for loop.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I significantly simplified the logic and added more comments now. PTAL

inBinding = false;
} else if (seg.kind() == SegmentKind.LITERAL) {
String value = seg.value();
if (value.matches("^v\\d+[a-zA-Z0-9]*$")) { // just in case
Copy link
Copy Markdown
Member

@lqiu96 lqiu96 Mar 30, 2026

Choose a reason for hiding this comment

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

From the AIP, I believe the regex should be:

For collection ID: [a-z][a-zA-Z0-9]*
From resource ID: ^[a-z]([a-z0-9-]{0,61}[a-z0-9])?$

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is to skip version literals such as v1, v1beta1.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh I misread this. In that case, can you add a small comment that this is to skip the version in the http path?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added.

// "projects" and "locations", the canonical resource name is
// projects/{project}/locations/{location}. See unit tests for all cases.
// Canonical resource names may be incorrect if the http template contains singleton resources.
public String getCanonicalResourceName(Set<String> knownResources) {
Copy link
Copy Markdown
Member

@lqiu96 lqiu96 Mar 30, 2026

Choose a reason for hiding this comment

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

What is the format of the knownResources? Does it come in as the resource pattern (e.g. something like projects/{project}/locations/{location})?

I believe this would be different from the url format which would be projects/*/locations/*.

Just want to double check this: when the logic compares against the previous segment, it takes care of checking the possible wildcard values with the resource pattern that has no wildcards?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It actually should be renamed to knownResourceLiterals, it includes all resource literals (extracted by previous method getResourceLiterals) from the current service.

@blakeli0 blakeli0 merged commit f46480a into main Mar 31, 2026
116 of 119 checks passed
@blakeli0 blakeli0 deleted the feature/heuristic-filter branch March 31, 2026 18:36
diegomarquezp pushed a commit that referenced this pull request Apr 8, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>1.83.0</summary>

##
[1.83.0](v1.82.0...v1.83.0)
(2026-04-07)


### Features

* [aiplatform] [Memorystore for Redis Cluster] Add support for
([0bd7666](0bd7666))
* [aiplatform] Add container_spec to Reasoning Engine public protos
([0bd7666](0bd7666))
* [aiplatform] Add container_spec to Reasoning Engine public protos
([0bd7666](0bd7666))
* [aiplatform] Add container_spec to Reasoning Engine public protos
([3ba3854](3ba3854))
* [aiplatform] Add container_spec to Reasoning Engine public protos
([3ba3854](3ba3854))
* [aiplatform] add evaluation metrics and autorater configuration to
([0bd7666](0bd7666))
* [backupdr] Adding new workload specific fields for AlloyDB
([6344cb0](6344cb0))
* [ces] update public libraries for CES v1
([6344cb0](6344cb0))
* [ces] update public libraries for CES v1beta
([0bd7666](0bd7666))
* [ces] update public libraries for CES v1beta
([0bd7666](0bd7666))
* [chat] Addition of Section and SectionItem APIs
([0bd7666](0bd7666))
* [chat] Support app authentication with admin-consent scopes for
([0bd7666](0bd7666))
* [databasecenter] A new value `SUB_RESOURCE_TYPE_READ_POOL` is
([6344cb0](6344cb0))
* [dataflow] Add Pausing/Yaml capabilities to public protos
([3ba3854](3ba3854))
* [dataflow] add sha256 field to Package proto
([0bd7666](0bd7666))
* [dataflow] add sha256 field to Package proto
([3ba3854](3ba3854))
* [dataform] add folders and teamFolders related changes to v1
([6344cb0](6344cb0))
* [datalineage] add configmanagement v1 module
([#12355](#12355))
([2def625](2def625))
* [datamanager] add INVALID_MERCHANT_ID to the ErrorReason enum for
([6344cb0](6344cb0))
* [dialogflow-cx] updated v3 dialogflow client libraries with
([6344cb0](6344cb0))
* [dialogflow] updated v2 dialogflow client libraries
([6344cb0](6344cb0))
* [dialogflow] updated v2beta1 dialogflow client libraries
([6344cb0](6344cb0))
* [dlp] added support for detecting key-value pairs in client
([e5e22ed](e5e22ed))
* [document-ai] Added a fields for image and table annotation output
([0bd7666](0bd7666))
* [geocode] new module for geocode
([#12343](#12343))
([474efb1](474efb1))
* [netapp] Add ONTAP passthrough APIs
([6344cb0](6344cb0))
* [network-security] Publish proto definitions for AuthzPolicy,
([6344cb0](6344cb0))
* [redis-cluster] [Memorystore for Redis Cluster] Add support for
([0bd7666](0bd7666))
* [redis-cluster] [Memorystore for Redis Cluster] Add support for
([3ba3854](3ba3854))
* [redis-cluster] [Memorystore for Redis Cluster] Add support for
([3ba3854](3ba3854))
* [securesourcemanager] Add CustomHostConfig to configure custom
([6344cb0](6344cb0))
* [storage] populate the `persisted_data_checksums` field with
([e5e22ed](e5e22ed))
* [texttospeech] Support safety settings for Gemini voices and
([0bd7666](0bd7666))
* [texttospeech] Support safety settings for Gemini voices and
([0bd7666](0bd7666))
* [texttospeech] Support safety settings for Gemini voices and
([0bd7666](0bd7666))
* [texttospeech] Support safety settings for Gemini voices and
([0bd7666](0bd7666))
* [translate] A new field `mime_type` is added to message
([e5e22ed](e5e22ed))
* [valkey] [Memorystore for Valkey] Add support for Flexible CA
([0bd7666](0bd7666))
* [valkey] [Memorystore for Valkey] Add support for Flexible CA
([0bd7666](0bd7666))
* [valkey] [Memorystore for Valkey] Add support for Flexible CA
([3ba3854](3ba3854))
* Add getProjectId getter for ComputeEngineCredentials
([#1833](#1833))
([0a7895a](0a7895a))
* **bigguery:** add url.domain to span tracing
([#12208](#12208))
([6f79c2d](6f79c2d))
* **bigquery observability:** add version attribute to span tracing
([#12132](#12132))
([95c3eb8](95c3eb8))
* **bigquery:** add gcp.resource.destination.id for span tracing
([#12134](#12134))
([5f31ded](5f31ded))
* **bigquery:** add opentelemetry W3C Trace Context to headers
([#12203](#12203))
([965761a](965761a))
* **bigquery:** add resend attribute to span tracing + integration tests
([#12313](#12313))
([167722d](167722d))
* **bigquery:** add url.full attribute to span tracing
([#12176](#12176))
([7fdf9ff](7fdf9ff))
* **bigquery:** add url.template to span tracing
([#12181](#12181))
([30f8afb](30f8afb))
* **bigquery:** added error attributes to span tracing
([#12115](#12115))
([863d23b](863d23b))
* Extract resource name from unary requests for tracing
([#4159](#4159))
([23b16b7](23b16b7))
* **gapic-generator-java:** Extract resource name heuristicly
([#12207](#12207))
([f46480a](f46480a))
* **gax:** Actionable Errors Logging API Tracer
([#12202](#12202))
([8d23279](8d23279))
* **gax:** Add error attributes to golden signal metrics.
([#12564](#12564))
([063dfe5](063dfe5))
* **gax:** add utility for logging actionable errors
([#4144](#4144))
([54fb8a5](54fb8a5))
* **gax:** Implement trace context extraction and injection with
integration test
([#12625](#12625))
([6675310](6675310))
* **observability:** Implement gcp.client.service attribute
([#12315](#12315))
([e99812f](e99812f))
* **observability:** implement url.domain attribute
([#12316](#12316))
([0a865bf](0a865bf))
* **sdk-platform-java:** Add CompositeTracer and CompositeTracerFactory.
([#12321](#12321))
([4b5e8af](4b5e8af))
* Switch Eef metrics to using built in open telemetry
([#4385](#4385))
([759bb22](759bb22))


### Bug Fixes

* Add error attributes to logging
([#12685](#12685))
([a9198ee](a9198ee))
* **bq jdbc:** allow & ignore unknown parameters
([#12352](#12352))
([2332ff1](2332ff1))
* **bq jdbc:** ensure getMoreResults() always moves the cursor
([#12353](#12353))
([ac1f0f4](ac1f0f4))
* **ci:** consolidate duplicate yaml keys in github actions workflows
([#12306](#12306))
([f644a19](f644a19))
* Clean up attributes for traces and metrics
([#12677](#12677))
([914f97f](914f97f))
* fix getLong on NUMERIC
([#2420](#2420))
([75ec5c2](75ec5c2))
* **gax:** Implement lazy resource name evaluation in ApiTracerContext
([#12618](#12618))
([5e47749](5e47749))
* Handle null server address
([#12184](#12184))
([435dd8c](435dd8c))
* **hermetic-build:** do not add release please comments on vertexai
poms
([#12559](#12559))
([5e161a7](5e161a7))
* **o11y:** create noop tracer when artifact ID is not set
([#12307](#12307))
([630d83d](630d83d))
* **o11y:** do not record error.type in successful runs
([#12620](#12620))
([28eebf0](28eebf0))
* **o11y:** remove `gpc.client.language` attribute
([#12621](#12621))
([40d2e43](40d2e43))
* **oauth2:** mask sensitive tokens in HTTP logs
([#1900](#1900))
([3e4ccb7](3e4ccb7))
* **release:** add Version.java as extra files in release-please
([#12617](#12617))
([f5101d9](f5101d9))
* **spanner:** enforce READY-only location aware routing and add
endpoint lifecycle management
([ecb86fd](ecb86fd))
* **spanner:** enforce READY-only location aware routing and add
endpoint lifecycle management
([#12678](#12678))
([ca9edb9](ca9edb9))
* **spanner:** improve grpc-gcp affinity cleanup and location-aware
retries
([a157c2f](a157c2f))
* **spanner:** improve grpc-gcp affinity cleanup and location-aware
retries
([#12682](#12682))
([aca0428](aca0428))
* use dynamic tracer name instead of hardcoded gax-java
([#12190](#12190))
([dea24db](dea24db))


### Dependencies

* bump jackson version to 2.18.3
([#12351](#12351))
([50304c1](50304c1))
* update dependencies.txt for grpc-gcp to 1.9.2
([#4164](#4164))
([f336fdc](f336fdc))
* update dependency com.google.apis:google-api-services-storage to
v1-rev20260204-2.0.0
([#1750](#1750))
([340ecbe](340ecbe))
* update dependency com.google.apis:google-api-services-storage to
v1-rev20260204-2.0.0
([#3519](#3519))
([1531107](1531107))
* update dependency com.google.cloud:google-cloud-storage to v2.64.1
([#1752](#1752))
([8fb6935](8fb6935))
* update dependency com.google.cloud:sdk-platform-java-config to v3.58.0
([#1751](#1751))
([9cc3e22](9cc3e22))
* update dependency com.google.cloud:sdk-platform-java-config to v3.58.0
([#3523](#3523))
([26d772a](26d772a))
* update dependency node to v24
([#3509](#3509))
([f308477](f308477))
* update gcr.io/cloud-devrel-public-resources/storage-testbench docker
tag to v0.62.0
([#3526](#3526))
([ca29d5e](ca29d5e))
* update googleapis/sdk-platform-java action to v2.68.0
([#3522](#3522))
([abae1ac](abae1ac))


### Reverts

* ci: only run default list of graalvm tests if too many modules are
touched
([#12292](#12292))
([92bcdf4](92bcdf4))


### Documentation

* [dataplex] Change Dataplex library from `ALPHA` to `GA`
([6344cb0](6344cb0))
* [run] An existing repeated string field custom_audiences is marked
([015d9a1](015d9a1))
* **hermetic-build:** improve usability of development guide
([#12362](#12362))
([5944127](5944127))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: chingor13 <chingor@google.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