Skip to content

CAMEL-25889: camel-google-mail/drive/calendar/sheets - create the API client per endpoint credentials instead of one per component - #28217

Open
oscerd wants to merge 6 commits into
apache:mainfrom
oscerd:fix/CAMEL-25889
Open

oscerd wants to merge 6 commits into
apache:mainfrom
oscerd:fix/CAMEL-25889

Conversation

@oscerd

@oscerd oscerd commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Fixes CAMEL-25889.

The google-mail, google-mail-stream, google-drive, google-calendar, google-calendar-stream, google-sheets and google-sheets-stream components kept a single API client per component: getClient(configuration) created it from the configuration of the first endpoint that asked for one and returned that same client to every later endpoint of the component, whatever the options of that endpoint were.

Changes

  • Each endpoint now creates its own client from its own options, on first use, and keeps it for its lifetime (a lock-guarded lazy field on the endpoint). The components' getClient(configuration) creates a client for the given configuration. GoogleMailComponent additionally keeps one lazily created client for its own configuration (no-arg getClient(), released on stop) for callers without an endpoint: the google-mail:update-message-labels data type transformer uses it, so it no longer creates a client per exchange and now authenticates with the component-level configuration (the upgrade guide says so). So the client's lifetime follows the endpoint's (endpoints created by toD with per-message tokens are released with the endpoint registry's eviction), and the stream consumers no longer go through the component on every poll.
  • google-drive: the endpoint-level clientFactory option is now used to create the client of that endpoint (the component ignored it before, so the existing CustomClientFactoryTest only checked the getter). GoogleDriveComponent gained a getClient(configuration, clientFactory) overload; the one-argument method keeps its signature.
  • google-mail-stream: when neither clientSecret nor serviceAccountKey is set, getClient now throws an IllegalArgumentException with the same message as the other components instead of returning null. The upgrade guide note says so, and the mail-stream test asserts the exception.
  • Tests: one *ClientPerEndpointOptionsTest per component with a recording fake client factory, no network. They check that every endpoint gets its own client and keeps it, that endpoints with different options (OAuth refresh token, service account delegate, Application Default Credentials vs explicit credentials on sheets) each get their own, and that the google-drive endpoint factory is used. The three stream tests cover both the OAuth and the service-account delegate paths.
  • Upgrade guide note for 4.24.

Checks

  • mvn -DskipTests install in the four modules, the new tests, and the full reactor build (clean install -DskipTests -DskipITs) with no regenerated-file drift.

Claude Code on behalf of oscerd

🤖 Generated with Claude Code

@oscerd
oscerd requested review from davsclaus and gnodet October 21, 2026 08:19
@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@gnodet-bot gnodet-bot left a comment

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.

The fix is conceptually correct and the per-endpoint cache pattern is consistent with camel-dhis2, camel-zendesk, and camel-box. Two findings below.

⚠️ Pre-fix test validation: static trace confirms the old code would fail assertNotSame(first.getClient(), second.getClient()) — the old singleton returned the same client for all endpoints. ✅

This review was generated by an AI agent, Hermès on behalf of @gnodet.

Comment thread docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc Outdated

@gnodet-bot gnodet-bot left a comment

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.

Following up on my earlier review — both issues have been addressed:

  • ✅ Upgrade guide now documents the google-mail-stream credential-validation change.
  • ✅ shouldKeepOneClientPerDelegate added to all three stream test files (calendar-stream, mail-stream, sheets-stream).

One medium finding below.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@gnodet-bot gnodet-bot left a comment

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.

Following up on my earlier review — both findings have been addressed.

  1. ✅ Upgrade guide entry — the google-mail-stream IAE behavior change is now documented.
  2. ✅ Service-account delegate tests — shouldKeepOneClientPerDelegate added to all three stream components (GoogleCalendarStreamClientPerEndpointOptionsTest, GoogleMailStreamClientPerEndpointOptionsTest, GoogleSheetsStreamClientPerEndpointOptionsTest). The tests correctly exercise the service-account code path with distinct delegate values and verify the RecordingClientFactory receives them in order.

Previous findings are all addressed. LGTM.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@gnodet-bot gnodet-bot left a comment

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.

Following up on my earlier review — both findings have been addressed.

  1. ✅ Upgrade guide entry — the google-mail-stream IAE behavior change is now documented.
  2. ✅ Service-account delegate tests — shouldKeepOneClientPerDelegate added to all three stream components (GoogleCalendarStreamClientPerEndpointOptionsTest, GoogleMailStreamClientPerEndpointOptionsTest, GoogleSheetsStreamClientPerEndpointOptionsTest). The tests correctly exercise the service-account code path with distinct delegate values and verify the RecordingClientFactory receives them in order.

Previous findings are all addressed. LGTM.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@gnodet-bot gnodet-bot left a comment

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.

Following up on my earlier review — the remaining open finding has been addressed.

  • ✅ Missing IAE test — shouldFailWithoutCredentials added to GoogleMailStreamClientPerEndpointOptionsTest confirms getClient() throws IllegalArgumentException when neither clientSecret nor serviceAccountKey is configured, and asserts the message names serviceAccountKey. This is stricter than the suggested test (which omitted the message assertion) — good.

All previous findings are now resolved. LGTM.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@davsclaus davsclaus left a comment

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.

Thanks Andrea, this looks good. Each of the seven components now keeps its clients in a ConcurrentHashMap keyed by the options the client factory actually reads, filled with computeIfAbsent and cleared in doStop(). Endpoints with the same options (including all endpoints that only use the component-level configuration, since those copy the same values) still share one client, and endpoints with different credentials no longer silently use the first endpoint's client. computeIfAbsent also removes the old unsynchronised client == null race, and a factory that throws leaves no entry behind. I checked the keys against the factories: scopes is a String on all seven configurations, so List.equals works and there is no cache miss per call, and the calendar keys include emailAddress, p12FileName and user, which only the calendar factory takes. The removed client component fields had no setter, so they were never configurable options and nothing in the catalog changes. The google-api-client service objects hold no resources of their own (the transport belongs to the factory), so not closing them on stop does not leak anything.

Conventions check: the commits, branch and JIRA linkage follow the project guidelines. The upgrade-guide entry for 4.24 covers both behaviour changes (one client per option set, and google-mail-stream failing early without credentials). Each component has a test that needs no network and uses a recording factory, written in the modules' JUnit style, with no Thread.sleep. The google-drive endpoint clientFactory is now actually used and tested. The three gnodet-bot threads are already resolved and addressed at this head.

Non-blocking notes:

  • Entries leave the map only when the component stops. When endpoints come and go while the component keeps running (a toD with per-call accessToken/refreshToken, or routes reloaded with new tokens in dev mode), the old clients and the credentials in their keys stay until shutdown. That is probably fine for the usual static configuration, but a hint if it matters: tie the client to the endpoint lifecycle (create it in the endpoint's doStart, drop it in doStop), so the component only shares the client for the component-level configuration. It's your call.
  • The stream consumers call getEndpoint().getClient() on every poll and per message, so each call now builds the key list and does a map lookup. That cost is negligible next to the HTTP call, just mentioning it in case the endpoint should hold on to its client after the first lookup.

CI: the build jobs are still running.

This review covers project rules and conventions only. It does not replace CodeRabbit, Sourcery or SonarCloud.

Claude Code on behalf of Claus Ibsen

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • catalog/camel-catalog
  • components/camel-google/camel-google-calendar
  • components/camel-google/camel-google-drive
  • components/camel-google/camel-google-mail
  • components/camel-google/camel-google-sheets
  • docs

🔬 Scalpel shadow comparison — Scalpel: 11 of 707 tested, 25 compile-only — current: 11 all tested

Maveniverse Scalpel detected 11 affected modules (current approach: 11).

Skip-tests mode would test 11 modules (6 direct + 7 downstream), skip tests for 25 (generated code, meta-modules)

Modules Scalpel would test (11)
  • camel-google-calendar ← components/camel-google/camel-google-calendar/src/main/java/org/apache/camel/component/google/calendar/GoogleCalendarComponent.java, components/camel-google/camel-google-calendar/src/main/java/org/apache/camel/component/google/calendar/GoogleCalendarEndpoint.java, components/camel-google/camel-google-calendar/src/main/java/org/apache/camel/component/google/calendar/stream/GoogleCalendarStreamComponent.java, components/camel-google/camel-google-calendar/src/main/java/org/apache/camel/component/google/calendar/stream/GoogleCalendarStreamEndpoint.java, components/camel-google/camel-google-calendar/src/test/java/org/apache/camel/component/google/calendar/GoogleCalendarClientPerEndpointOptionsTest.java, components/camel-google/camel-google-calendar/src/test/java/org/apache/camel/component/google/calendar/stream/GoogleCalendarStreamClientPerEndpointOptionsTest.java
  • camel-google-drive ← components/camel-google/camel-google-drive/src/main/java/org/apache/camel/component/google/drive/GoogleDriveComponent.java, components/camel-google/camel-google-drive/src/main/java/org/apache/camel/component/google/drive/GoogleDriveEndpoint.java, components/camel-google/camel-google-drive/src/test/java/org/apache/camel/component/google/drive/GoogleDriveClientPerEndpointOptionsTest.java
  • camel-google-mail ← components/camel-google/camel-google-mail/src/main/docs/google-mail-component.adoc, components/camel-google/camel-google-mail/src/main/java/org/apache/camel/component/google/mail/GoogleMailComponent.java, components/camel-google/camel-google-mail/src/main/java/org/apache/camel/component/google/mail/GoogleMailEndpoint.java, components/camel-google/camel-google-mail/src/main/java/org/apache/camel/component/google/mail/stream/GoogleMailStreamComponent.java, components/camel-google/camel-google-mail/src/main/java/org/apache/camel/component/google/mail/stream/GoogleMailStreamEndpoint.java, components/camel-google/camel-google-mail/src/main/java/org/apache/camel/component/google/mail/transform/GoogleMailUpdateMessageLabelsDataTypeTransformer.java, components/camel-google/camel-google-mail/src/test/java/org/apache/camel/component/google/mail/GoogleMailClientPerEndpointOptionsTest.java, components/camel-google/camel-google-mail/src/test/java/org/apache/camel/component/google/mail/stream/GoogleMailStreamClientPerEndpointOptionsTest.java
  • camel-google-sheets ← components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/GoogleSheetsComponent.java, components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/GoogleSheetsEndpoint.java, components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/stream/GoogleSheetsStreamComponent.java, components/camel-google/camel-google-sheets/src/main/java/org/apache/camel/component/google/sheets/stream/GoogleSheetsStreamEndpoint.java, components/camel-google/camel-google-sheets/src/test/java/org/apache/camel/component/google/sheets/GoogleSheetsClientPerEndpointOptionsTest.java, components/camel-google/camel-google-sheets/src/test/java/org/apache/camel/component/google/sheets/stream/GoogleSheetsStreamClientPerEndpointOptionsTest.java
  • camel-jbang-mcp ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-mcp ← downstream of org.apache.camel:camel-jbang-core
  • camel-jbang-plugin-tui ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-validate ← downstream of org.apache.camel:camel-yaml-dsl-validator
  • camel-launcher-container ← downstream of org.apache.camel:camel-launcher
  • camel-yaml-dsl-validator ← downstream of org.apache.camel:camel-catalog
  • camel-yaml-dsl-validator-maven-plugin ← downstream of org.apache.camel:camel-yaml-dsl-validator
Modules with tests skipped (25)
  • apache-camel
  • camel-allcomponents
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

All tested modules (38 modules, 6m 23s total)

Total reactor time: 6m 23s

Module Duration Status
Camel :: Launcher 48.0s SUCCESS
Camel :: JBang :: MCP 40.5s SUCCESS
Camel :: Google :: Mail 29.3s SUCCESS
Camel :: JBang :: Plugin :: Validate 28.7s SUCCESS
Camel :: Component DSL 24.3s SUCCESS
Camel :: Catalog :: Camel Catalog 23.0s SUCCESS
Camel :: YAML DSL 22.0s SUCCESS
Camel :: YAML DSL :: Validator 21.1s SUCCESS
Camel :: Google :: Sheets 18.5s SUCCESS
Camel :: Docs 14.3s SUCCESS
Camel :: Kamelet Main 14.0s SUCCESS
Camel :: Catalog :: Camel Report Maven Plugin 13.1s SUCCESS
Camel :: JBang :: Plugin :: Kubernetes 12.3s SUCCESS
Camel :: JBang :: Plugin :: Testing 12.0s SUCCESS
Camel :: Google :: Drive 7.9s SUCCESS
Camel :: Catalog :: Camel Route Parser 7.7s SUCCESS
Camel :: YAML DSL :: Deserializers 7.5s SUCCESS
Camel :: Google :: Calendar 6.2s SUCCESS
Camel :: All Components Sync point 4.8s SUCCESS
Camel :: Catalog :: Suggest (deprecated) 4.6s SUCCESS
Camel :: YAML DSL :: Validator Maven Plugin 3.8s SUCCESS
Camel :: YAML DSL :: Maven Plugins 3.2s SUCCESS
Camel :: Catalog :: Maven 3.0s SUCCESS
Camel :: Endpoint DSL :: Support 2.1s SUCCESS
Camel :: Assembly 1.8s SUCCESS
Camel :: Coverage 1.7s SUCCESS
Camel :: JBang :: Plugin :: Edit 1.5s SUCCESS
Camel :: JBang :: Plugin :: Generate 1.1s SUCCESS
Camel :: Catalog :: Console 1.0s SUCCESS
Camel :: JBang :: Integration tests 0.9s SUCCESS
Camel :: Catalog :: Dummy Component 0.8s SUCCESS
Camel :: JBang :: Plugin :: MCP 0.7s SUCCESS
Camel :: Launcher :: Container 0.7s SUCCESS
Camel :: JBang :: Main 0.6s SUCCESS
Camel :: Endpoint DSL n/a
Camel :: Integration Tests n/a
Camel :: JBang :: Core n/a
Camel :: JBang :: Plugin :: TUI n/a

Top 20 slowest modules:

  • Camel :: Launcher (48.0s)
  • Camel :: JBang :: MCP (40.5s)
  • Camel :: Google :: Mail (29.3s)
  • Camel :: JBang :: Plugin :: Validate (28.7s)
  • Camel :: Component DSL (24.3s)
  • Camel :: Catalog :: Camel Catalog (23.0s)
  • Camel :: YAML DSL (22.0s)
  • Camel :: YAML DSL :: Validator (21.1s)
  • Camel :: Google :: Sheets (18.5s)
  • Camel :: Docs (14.3s)
  • Camel :: Kamelet Main (14.0s)
  • Camel :: Catalog :: Camel Report Maven Plugin (13.1s)
  • Camel :: JBang :: Plugin :: Kubernetes (12.3s)
  • Camel :: JBang :: Plugin :: Testing (12.0s)
  • Camel :: Google :: Drive (7.9s)
  • Camel :: Catalog :: Camel Route Parser (7.7s)
  • Camel :: YAML DSL :: Deserializers (7.5s)
  • Camel :: Google :: Calendar (6.2s)
  • Camel :: All Components Sync point (4.8s)
  • Camel :: Catalog :: Suggest (deprecated) (4.6s)

⚙️ View full build and test results

@oscerd

oscerd commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Both review notes applied in d5638c6: the components no longer hold a client map. Each endpoint creates its own client from its own options on first use (a lock-guarded lazy field) and keeps it for its lifetime, so the clients of endpoints created by toD with per-message tokens go away with the endpoint, and the stream consumers no longer build a key and look the client up on every poll. The components' getClient(configuration) now just creates a client for the given configuration. Tests and the upgrade-guide note follow the per-endpoint semantics; all seven test classes and the full reactor are green locally.

Claude Code on behalf of oscerd

@oscerd
oscerd requested a review from davsclaus October 21, 2026 12:38

@davsclaus davsclaus left a comment

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.

Re-review of f9d7e32..d5638c6. Thanks Andrea, moving the client onto the endpoint is cleaner than the component map, and it covers both of my earlier notes: the client goes away with its endpoint, and the stream consumers no longer build a key on every poll. The double-checked volatile field with the lock is correct, and keeping the client across an endpoint stop/start is fine, since nothing needs closing.

One regression from this commit, and one related gap:

  1. google-mail:update-message-labels now builds a client per exchange. GoogleMailUpdateMessageLabelsDataTypeTransformer.getGmailClient() calls component.getClient(component.getConfiguration()) on every transform(). That call used to hit the map (or, on main, the component's single client field). Now it creates a new client every time. With serviceAccountKey, every message reads the key file again and makes a token request (GoogleCredentialsHelper.loadServiceAccountAsLegacyCredential calls credential.refreshToken()). With refreshToken, every message starts from a credential with no access token, so it refreshes once per message. Could the transformer (or the component, for its own configuration) keep one lazily created client?
  2. Upgrade note for the transformer. On main the transformer used whichever client the component had already created, which in the documented example is the client of the downstream google-mail:messages/modify endpoint. With this PR it uses only the component-level configuration, so a route that sets credentials only on the endpoint URI now gets an IllegalArgumentException from the transformer. That is the more correct behaviour, but it is worth a sentence in the 4.24 upgrade guide entry, or in the transformer section of google-mail-component.adoc.

Minor: in the API endpoints, afterConfigureProperties() calls getClient() to build apiProxy, so the client is in fact created when the endpoint is created, not "on first use" as the javadoc says. Not a problem, just so the comment matches.

This review was generated by an AI agent (Claude Code on behalf of davsclaus) and may contain inaccuracies. Please verify all suggestions before applying.

Comment thread docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc Outdated
@oscerd
oscerd requested a review from davsclaus October 21, 2026 16:59

@davsclaus davsclaus left a comment

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.

Re-review of d5638c6..750cfd0. Thanks Andrea, both points are addressed.

  • GoogleMailComponent.getClient() now keeps one lazily created client for the component-level configuration. It uses a volatile field with double-checked locking, a factory that throws leaves nothing behind, and doStop() clears it. The update-message-labels transformer uses it, so it no longer builds a client (and fetches a token) per exchange. Endpoints keep creating and owning their own clients, and shouldKeepOneClientForTheComponentConfiguration covers both.
  • The 4.24 upgrade guide now explains that the transformer only uses the camel.component.google-mail.* credentials.

Optional, non-blocking:

  • The "Data Type Transformer: update-message-labels" section of google-mail-component.adoc could mention in one sentence that the transformer uses the credentials configured on the component, since endpoint-URI credentials no longer reach it.
  • The upgrade-guide line ending "...first API call. The google-mail:update-message-labels data type" is longer than the rest of the paragraph; re-wrapping it would keep the section tidy.

LGTM once CI is green.

This review was generated by an AI agent (Claude Code on behalf of davsclaus) and may contain inaccuracies. Please verify all suggestions before applying.

@oscerd

oscerd commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Both optional points applied in c8d9446: the "Data Type Transformer: update-message-labels" section of google-mail-component.adoc (and its catalog mirror) now says the transformer uses the credentials configured on the component, and the upgrade-guide paragraph is re-wrapped. Documentation only, no code change.

The previous CI run failed on JDK 21 in camel-aws2-eks with a Maven Central transfer error for software.amazon.awssdk:eks:pom:2.56.0 (the JDK 25 job was cancelled by fail-fast), which is unrelated to this change; CI runs again on the new head.

Claude Code on behalf of oscerd

@oscerd
oscerd requested a review from davsclaus October 22, 2026 07:14
oscerd and others added 6 commits October 22, 2026 09:20
… client per endpoint credentials instead of one per component

The google-mail, google-mail-stream, google-drive, google-calendar, google-calendar-stream, google-sheets and google-sheets-stream components kept a single API client per component, created from the configuration of the first endpoint that asked for one and returned to every later endpoint whatever its own options were.

Each component now keeps one client per distinct set of the options the client is created from (clientId, clientSecret, refreshToken, accessToken, serviceAccountKey, delegate, scopes, applicationName, and emailAddress, p12FileName and user on the calendar components), in a thread-safe map that is cleared when the component stops. Endpoints with the same options keep sharing a client; endpoints with different options get their own. The google-drive component also honours the endpoint-level clientFactory option, which it ignored before, and google-mail-stream now fails with a clear message instead of returning a null client when no credentials are configured.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
…ntials and test the per-delegate clients of the stream components

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
…ent client map

Following review: the client's lifetime now follows the endpoint's, so clients of endpoints created with per-message credentials go away with the endpoint, and the stream consumers no longer look the client up on every poll. The components' getClient(configuration) creates a client for the given configuration.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
…ion for the update-message-labels transformer

Following review: the transformer asked the component for a client on every exchange, which created a client per message once the components stopped caching. The component now keeps one lazily created client for its own configuration, released on stop, and the transformer uses it. The upgrade guide notes that the transformer authenticates with the component-level configuration.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
…former uses and re-wrap the upgrade note

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
@oscerd

oscerd commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Rebased on main (e6885df) to resolve the conflict in camel-4x-upgrade-guide-4_24.adoc, where main gained several notes around the spot this PR used. The note is now placed between the camel-gson/camel-jsonb and the camel-jbang validate notes; its text and the code are unchanged (verified by diffing the rebased commits against the previous head). All six commits are re-signed.

Claude Code on behalf of oscerd

@davsclaus davsclaus left a comment

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.

Re-review of 750cfd0..4ba336e. Thanks Andrea.

I compared the PR diff against its merge base before and after the rebase. The Java code and the tests are unchanged since my last approval. Only the documentation changed:

  1. The "Data Type Transformer: update-message-labels" section of google-mail-component.adoc now says the transformer uses the credentials configured on the component. The catalog copy under catalog/camel-catalog/src/generated/resources/.../docs/ is identical to the source doc.
  2. The 4.24 upgrade-guide entry is re-wrapped to the width of the rest of the file and sits in its new place after the rebase onto main. The text is the same as before.

The design I approved still holds. Each endpoint creates and owns its client from its own options, so no endpoint can get another endpoint's client. GoogleMailComponent keeps one lazily created client only for its own configuration, used by the update-message-labels transformer and cleared in doStop().

No new findings, blocking or otherwise. All review threads are resolved.

CI: dependency-review and license-check passed. The build jobs (JDK 21 and 25) are still pending. To merge once CI is green.

Claude Code on behalf of @davsclaus.

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants