Skip to content

CAMEL-25879: camel-infinispan - the key option of the producer takes precedence over the key header - #28174

Merged
davsclaus merged 4 commits into
apache:mainfrom
Croway:fix/CAMEL-25879
Oct 22, 2026
Merged

davsclaus merged 4 commits into
apache:mainfrom
Croway:fix/CAMEL-25879

Conversation

@Croway

@Croway Croway commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

CAMEL-25879

The infinispan and infinispan-embedded producers resolved the key of every operation as message.getHeader(InfinispanConstants.KEY, configuration::getKey), so the CamelInfinispanKey header won over the key option of the endpoint. An Infinispan consumer sets that header to the key of each cache event, so a route forwarding events to a producer with a fixed key worked on the key of the event instead.

Changes

  • InfinispanProducer.getKey(Message): the key option when it is set, otherwise the CamelInfinispanKey header. Used by the 13 operations that read a key.
  • Component docs (infinispan, infinispan-embedded, and the catalog copies): new section "Key and cache name headers" on the precedence of the two headers, and on removing the CamelInfinispan* headers between an Infinispan consumer and producer. CamelInfinispanCacheName still takes precedence over the cache name of the endpoint.
  • Upgrade guide 4.24: routes that set key on the endpoint and override it per message with the header must remove key from the endpoint.

Tests

publishKeyAndValueByExplicitlySpecifyingTheKeyAndValueOptionsHeaderHavePriorities (shared by the embedded and remote producer tests) asserted the previous precedence. It is renamed ...KeyOptionHasPriority and now expects the put on the key of the endpoint, while the CamelInfinispanValue header still wins over the value option. All 99 tests of camel-infinispan-embedded pass; the remote InfinispanRemoteProducerIT uses the same test and was not run locally (needs a container).

@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.

@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 Federico, the docs section is a good addition. I'd rather not flip the precedence of the key in the producer, though:

  1. The rest of Camel uses the opposite rule. Across Camel, a header on the message overrides the endpoint option: CamelAwsS3Key over keyName (AWS2S3Utils.determineKey), CamelCaffeineKey over key (CaffeineCacheProducer). In this producer, CamelInfinispanValue, CamelInfinispanOldValue, CamelInfinispanDefaultValue and CamelInfinispanCacheName also still win over their options. After this PR, key would be the only exception, which is harder to explain than the current rule.
  2. The current behaviour is deliberate. The key option was added as an alternative to the header in CAMEL-15609 (c022730), together with ...HeaderHavePriorities, a test that asserts the header wins. Routes that set a default key on the endpoint and override it per message would break without any error: the value would go to the endpoint key. The same happens when InfinispanEmbeddingsDataTypeTransformer sets the key header. The upgrade guide note helps, but nothing fails, so users may not notice.
  3. Bridge routes already remove the inbound headers. Consumer to producer is the same case as s3 to s3 or file to file. The new docs section already shows the fix (removeHeaders("CamelInfinispan*")). I'd keep that section, reworded to say that the header takes precedence over the key option, together with its catalog copies, and drop the producer change, the test rename and the upgrade guide entry.

CI is still running on the current head.

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

@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.

LGTM, thanks Federico. Approving, which replaces my earlier request for changes: this is a hardening. A route that forwards events from an Infinispan consumer to a producer with a fixed key must not let the event's CamelInfinispanKey header pick the entry, and the upgrade guide tells routes that relied on overriding key per message what to change. The earlier point about CAMEL-15609 choosing header-first stands as history only; the new precedence is the intended one.

Small nit, optional: "An infinispan consumer" / "an infinispan producer" in the new docs section.

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

@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.

Clean fix — centralising the key-resolution logic into a single getKey() helper eliminates 13 duplicated message.getHeader(…, configuration::getKey) call sites cleanly. The test coverage and upgrade guide look good.

One minor observation inline.

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 grammar nit ("An `infinispan`" / "An `infinispan-embedded`") is fixed in the second commit. The Javadoc suggestion on `getKey()` is still open.

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.

LGTM, thanks Federico. Since my approval the only change is the "an infinispan" wording, in both component docs and their catalog copies. I resolved that thread.

The bot's suggestion to add Javadoc on getKey() is optional. The docs section already explains that key wins over its header and the cache-name header wins over the endpoint.

Claude Code on behalf of davsclaus. 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 20, 2026 •

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • catalog/camel-catalog
  • components/camel-infinispan/camel-infinispan-common
  • components/camel-infinispan/camel-infinispan-embedded
  • components/camel-infinispan/camel-infinispan
  • docs
  • dsl/camel-componentdsl
  • dsl/camel-endpointdsl

🔁 1 test passed only after a retry on JDK 25 (1 retried attempt)

Recovered flaky tests on JDK 25 (1)
Module Test Failed attempts First failure
dsl/camel-jbang/camel-jbang-plugin-tui LaunchManagerOutcomeTest.startedWhenTheStatusFileSaysSo 1 expected: null but was: LaunchOutcome[ok=false, log=null]

ℹ️ These tests did not fail the build. Surefire retried them and they passed.
Retries are enabled project-wide by surefire.rerunFailingTestsCount in parent/pom.xml.


🔬 Scalpel shadow comparison — Scalpel: 12 of 707 tested, 23 compile-only — current: 12 all tested

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

Skip-tests mode would test 12 modules (7 direct + 9 downstream), skip tests for 23 (generated code, meta-modules)

Modules Scalpel would test (12)
  • camel-infinispan ← components/camel-infinispan/camel-infinispan/src/generated/resources/META-INF/org/apache/camel/component/infinispan/remote/infinispan.json, components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc
  • camel-infinispan-common ← components/camel-infinispan/camel-infinispan-common/src/main/java/org/apache/camel/component/infinispan/InfinispanConfiguration.java, components/camel-infinispan/camel-infinispan-common/src/main/java/org/apache/camel/component/infinispan/InfinispanProducer.java, components/camel-infinispan/camel-infinispan-common/src/test/java/org/apache/camel/component/infinispan/InfinispanProducerTestSupport.java
  • camel-infinispan-embedded ← components/camel-infinispan/camel-infinispan-embedded/src/generated/resources/META-INF/org/apache/camel/component/infinispan/embedded/infinispan-embedded.json, components/camel-infinispan/camel-infinispan-embedded/src/main/docs/infinispan-embedded-component.adoc
  • 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-langchain4j-embeddings ← downstream of org.apache.camel:camel-infinispan
  • camel-langchain4j-embeddingstore ← downstream of org.apache.camel:camel-langchain4j-embeddings
  • 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 (23)
  • apache-camel
  • camel-allcomponents
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • 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

⚠️ Some tests are disabled on GitHub Actions (@DisabledIfSystemProperty(named = "ci.env.name")) and require manual verification:

  • components/camel-infinispan/camel-infinispan: 2 test(s) disabled on GitHub Actions
All tested modules (39 modules, 5m 34s total)

Total reactor time: 5m 34s

Module Duration Status
Camel :: Launcher 50.2s SUCCESS
Camel :: JBang :: MCP 40.0s SUCCESS
Camel :: JBang :: Plugin :: Validate 28.9s SUCCESS
Camel :: Catalog :: Camel Catalog 22.0s SUCCESS
Camel :: YAML DSL 21.2s SUCCESS
Camel :: YAML DSL :: Validator 20.9s SUCCESS
Camel :: AI :: LangChain4j :: EmbeddingStore 20.1s SUCCESS
Camel :: Component DSL 18.4s SUCCESS
Camel :: Docs 14.3s SUCCESS
Camel :: Kamelet Main 13.9s SUCCESS
Camel :: JBang :: Plugin :: Testing 11.9s SUCCESS
Camel :: JBang :: Plugin :: Kubernetes 11.5s SUCCESS
Camel :: Catalog :: Camel Route Parser 7.5s SUCCESS
Camel :: YAML DSL :: Deserializers 7.4s SUCCESS
Camel :: Infinispan :: Common 7.1s SUCCESS
Camel :: Catalog :: Camel Report Maven Plugin 6.7s SUCCESS
Camel :: YAML DSL :: Validator Maven Plugin 6.0s SUCCESS
Camel :: All Components Sync point 5.0s SUCCESS
Camel :: Assembly 3.5s SUCCESS
Camel :: Catalog :: Maven 2.6s SUCCESS
Camel :: YAML DSL :: Maven Plugins 2.5s SUCCESS
Camel :: Catalog :: Suggest (deprecated) 2.4s SUCCESS
Camel :: JBang :: Plugin :: Edit 1.5s SUCCESS
Camel :: Coverage 1.4s SUCCESS
Camel :: JBang :: Integration tests 1.2s SUCCESS
Camel :: Endpoint DSL :: Support 1.1s SUCCESS
Camel :: JBang :: Plugin :: Generate 1.1s SUCCESS
Camel :: Catalog :: Dummy Component 1.0s SUCCESS
Camel :: JBang :: Main 0.8s SUCCESS
Camel :: Catalog :: Console 0.8s SUCCESS
Camel :: JBang :: Plugin :: MCP 0.7s SUCCESS
Camel :: Launcher :: Container 0.6s SUCCESS
Camel :: AI :: LangChain4j :: Embedding n/a
Camel :: Endpoint DSL n/a
Camel :: Infinispan :: Embedded n/a
Camel :: Infinispan :: Remote n/a
Camel :: Integration Tests n/a
Camel :: JBang :: Core n/a
Camel :: JBang :: Plugin :: TUI n/a

Top 20 slowest modules:

  • Camel :: Launcher (50.2s)
  • Camel :: JBang :: MCP (40.0s)
  • Camel :: JBang :: Plugin :: Validate (28.9s)
  • Camel :: Catalog :: Camel Catalog (22.0s)
  • Camel :: YAML DSL (21.2s)
  • Camel :: YAML DSL :: Validator (20.9s)
  • Camel :: AI :: LangChain4j :: EmbeddingStore (20.1s)
  • Camel :: Component DSL (18.4s)
  • Camel :: Docs (14.3s)
  • Camel :: Kamelet Main (13.9s)
  • Camel :: JBang :: Plugin :: Testing (11.9s)
  • Camel :: JBang :: Plugin :: Kubernetes (11.5s)
  • Camel :: Catalog :: Camel Route Parser (7.5s)
  • Camel :: YAML DSL :: Deserializers (7.4s)
  • Camel :: Infinispan :: Common (7.1s)
  • Camel :: Catalog :: Camel Report Maven Plugin (6.7s)
  • Camel :: YAML DSL :: Validator Maven Plugin (6.0s)
  • Camel :: All Components Sync point (5.0s)
  • Camel :: Assembly (3.5s)
  • Camel :: Catalog :: Maven (2.6s)

⚙️ View full build and test results

@oscerd oscerd 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.

TL;DR

The new key lookup (endpoint option first) reaches all 13 operations that read a key, and the renamed test covers both sides. Net-new: the new docs snippet fails as written, and the upgrade note could say that the cache-name header still wins. Nothing blocking.

Blockers

  • None

Other findings: 4 (1 important, 2 suggestions, 1 small)

1. [Important] The new snippet PUTs a null value (components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc:217-219, components/camel-infinispan/camel-infinispan-embedded/src/main/docs/infinispan-embedded-component.adoc:231-233, and the catalog copies)
After removeHeaders("CamelInfinispan*"), neither the CamelInfinispanValue header nor the value option is set, so onPut calls cache.put("myKey", null) (InfinispanProducer.java:72,88). An embedded cache rejects that: in Infinispan 16.3.0, CacheImpl.put calls assertKeyValueNotNull ("Null values are not supported!"). The CAMEL-25879 example had a value, and adding it back makes the snippet runnable: .to("infinispan:target?operation=PUT&key=myKey&value=myValue");

2. [Suggestion] Upgrade note and the cache-name header (docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc:1982-1990)
The note explains why a consumer-to-producer route with a fixed key used the key of the event, which reads as if that route works now. It still writes into the consumer's cache: InfinispanConsumer.java:51 sets CamelInfinispanCacheName on every event, and InfinispanManager.java:34 / InfinispanEmbeddedManager.java:137 use that header before the cache of the endpoint. That is why the Jira example removes it. One more sentence would help people upgrading: "The CamelInfinispanCacheName header still takes precedence over the cache of the endpoint, so such a route must remove the CamelInfinispan* headers first, see Key and cache name headers in the component docs."

3. [Suggestion] Show the precedence where tooling reads it (InfinispanConfiguration.java:29, InfinispanConstants.java:36)
The descriptions of the key option ("Set a specific key for producer operations") and the CamelInfinispanKey header don't mention the new rule. These texts feed the option and header tables, the catalog, IDE completion and the Endpoint DSL Javadoc, and this pair now behaves differently from the producer's other option/header pairs. Adding something like "When set, it takes precedence over the CamelInfinispanKey header." to the key description would make that visible; the infinispan JSON, catalog and Endpoint DSL then need regenerating.

4. [Small] Placement of the 4.24 note (camel-4x-upgrade-guide-4_24.adoc:1982)
The note is appended at the end of the file, where other open PRs add their 4.24 notes too, so each of those merges would force a rebase here. Moving it between two existing notes avoids that.

Reviewed with Claude Code on behalf of oscerd. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

@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.

All previous review findings are addressed. ✅

  • getKey() Javadoc — Correctly documents the endpoint-key-first precedence and the deliberate asymmetry with getCache() (which lets CamelInfinispanCacheName header win over the endpoint cache).
  • Docs snippet — PUT now includes both key=myKey and value=myValue, making it runnable on embedded caches.
  • Key option description — Updated in catalog/DSL JSON to note precedence over the CamelInfinispanKey header.
  • Upgrade note — Enriched with the CamelInfinispanCacheName caveat and moved to alphabetical position (between milo and protobuf).
  • Test — Renamed and updated to confirm key-option-wins / value-header-wins asymmetry.

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

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

✅ Generated files are up to date

An earlier CI run reported uncommitted generated changes; the latest run no longer does.

@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 Federico. Since my last approval (a6e9070) the branch was rebased, and the new commits address the open points from Andrea's review and from gnodet-bot:

  • getKey() now has a Javadoc that explains the endpoint-first precedence and the opposite rule of getCache() (header first).
  • The docs snippet sets value=myValue, so the PUT is runnable on an embedded cache.
  • The key option description says it takes precedence over the CamelInfinispanKey header. The component and catalog JSON, the Endpoint DSL and the Component DSL (the "Regen" commit) are regenerated.
  • The 4.24 upgrade-guide entry for this behaviour change is in place. It now also says that CamelInfinispanCacheName still wins over the cache of the endpoint, and it sits between the milo and protobuf entries rather than at the end of the file.

The code change itself is the same as what I approved.

Conventions check: the "Regen" commit has no CAMEL-25879: prefix. The squash-merge message will take care of that. CI was still building when I looked; dependency-review, license-check and upload are green.

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.

Croway and others added 4 commits October 21, 2026 21:21
…precedence over the key header

The producer resolved the key of every operation from the CamelInfinispanKey
header first and fell back to the key option of the endpoint, so the events of
an Infinispan consumer, which set CamelInfinispanKey to the key of the event,
overrode a key configured on the producer endpoint.

The producer now uses the key option when it is set, and the header only when
the endpoint does not set key. The component docs describe the precedence of the
key and cache name headers and how to forward consumer events to a producer, and
the 4.24 upgrade guide lists the change.
…, key precedence in the option description and the upgrade note

- the docs snippet sets a value, since a PUT without one fails on an embedded cache
- the key option description and the getKey() Javadoc state that key wins over the CamelInfinispanKey header
- the upgrade note says the CamelInfinispanCacheName header still wins, and moves away from the end of the file

@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 — all previous findings are confirmed addressed in the current head.The only change since my last review is the Regen commit (regenerated DSL/catalog files from the updated key option description in InfinispanConfiguration.java). No logic changes.This review was generated by an AI agent, Hermès on behalf of @gnodet.

@davsclaus davsclaus added this to the 4.24.0 milestone Oct 22, 2026
@davsclaus davsclaus added the enhancement New feature or request label Oct 22, 2026
@davsclaus
davsclaus merged commit 42204f7 into apache:main Oct 22, 2026
7 checks passed
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.

5 participants