This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 0bdacc9c8925 chore: add Exchange header naming conventions design
document
0bdacc9c8925 is described below
commit 0bdacc9c892568d2ade283b6eb1138166429b58e
Author: Guillaume Nodet <[email protected]>
AuthorDate: Fri May 22 16:57:44 2026 +0200
chore: add Exchange header naming conventions design document
Add design/headers.adoc documenting the Exchange header naming conventions
for Apache Camel components.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
AGENTS.md | 1 +
design/headers.adoc | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 223 insertions(+)
diff --git a/AGENTS.md b/AGENTS.md
index 2ed270bd6e10..b502ee0e0490 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -126,6 +126,7 @@ jump straight to implementation after reading the issue
description and the curr
- **Security** (secrets, SSL/TLS, serialization, policy enforcement):
[`design/security.adoc`](design/security.adoc)
- **Tracing / Telemetry** (OpenTelemetry, spans, context propagation):
[`design/tracing.adoc`](design/tracing.adoc)
- **MDC / Logging** (MDC propagation, logging context):
[`design/mdc.adoc`](design/mdc.adoc)
+ - **Headers** (naming conventions, constants, upgrade policy):
[`design/headers.adoc`](design/headers.adoc)
5. **Understand the broader context**: If the issue involves a module that
replaced or deprecated
another (e.g., `camel-opentelemetry2` replacing `camel-opentelemetry`),
understand *why* the
replacement was made and what was intentionally changed vs. accidentally
omitted.
diff --git a/design/headers.adoc b/design/headers.adoc
new file mode 100644
index 000000000000..660355d2eef9
--- /dev/null
+++ b/design/headers.adoc
@@ -0,0 +1,222 @@
+---
+title: Exchange header naming conventions
+authors:
+ - "@oscerd"
+ - "@gnodet"
+reviewers: []
+approvers: []
+creation-date: 2026-05-22
+last-updated: 2026-05-22
+status: implementable
+see-also: []
+replaces: []
+superseded-by: []
+---
+
+== Summary
+
+This document defines the naming conventions for Apache Camel Exchange headers.
+All component headers must follow these rules so that header names are
+predictable, self-documenting, and compatible with the framework's
+`HeaderFilterStrategy` security mechanism.
+
+== Motivation
+
+Camel has 300+ components, many contributed independently over 15+ years.
+Without a written standard, header string values drifted into at least four
+different styles: `dns.name`, `QUERY`, `operationName`, `kafka.PARTITION_KEY`.
+This inconsistency causes:
+
+* Confusion for users who must memorize per-component formats.
+* Security gaps: `DefaultHeaderFilterStrategy` strips `Camel*` headers
+ case-insensitively. Headers that don't use the `Camel` prefix bypass this
+ filter, which matters when untrusted input flows through the Exchange
+ (see link:security.adoc[]).
+* Tooling friction: code generators, catalog introspection, and IDE completion
+ work best when header names follow a single predictable pattern.
+
+== Convention
+
+=== Header string values
+
+Every component-owned Exchange header string value MUST follow:
+
+----
+"Camel" + ComponentName + Feature
+----
+
+All segments are PascalCase, concatenated without separators.
+
+[cols="1,1,1", options="header"]
+|===
+| Component | Java constant | String value
+
+| camel-kafka
+| `KafkaConstants.TOPIC`
+| `CamelKafkaTopic`
+
+| camel-file
+| `FileConstants.FILE_NAME`
+| `CamelFileName`
+
+| camel-jira
+| `JiraConstants.ISSUE_KEY`
+| `CamelJiraIssueKey`
+
+| camel-pdf
+| `PdfHeaderConstants.PDF_DOCUMENT_HEADER_NAME`
+| `CamelPdfDocument`
+|===
+
+*ComponentName* is the PascalCase form of the Camel component scheme
+(e.g., `kafka` -> `Kafka`, `elasticsearch` -> `Elasticsearch`,
+`aws2-s3` -> `Aws2S3`).
+
+=== Core framework headers
+
+Headers defined in `org.apache.camel.Exchange` use the `Camel` prefix directly
+(no component name), because they are framework-wide:
+
+----
+CamelFileName, CamelHttpResponseCode, CamelBatchSize, ...
+----
+
+=== Java constant names
+
+Java constant field names use `UPPER_SNAKE_CASE`:
+
+[source,java]
+----
+public static final String ISSUE_KEY = "CamelJiraIssueKey";
+----
+
+The constant name describes the concept; the string value encodes the
+component namespace.
+
+=== Constants class
+
+Each component declares its header constants in a dedicated class:
+
+----
+<ComponentName>Constants.java
+----
+
+located in the component's main package
+(`org.apache.camel.component.<name>`).
+
+Each constant MUST carry an `@Metadata` annotation:
+
+[source,java]
+----
+@Metadata(description = "The issue key", javaType = "String")
+public static final String ISSUE_KEY = "CamelJiraIssueKey";
+----
+
+The `@Metadata` annotation drives automatic documentation generation (component
+doc pages, catalog JSON, Endpoint DSL).
+
+=== Header prefix constants
+
+Some components use prefix-based headers (e.g., `CamelSolrField.title`,
+`CamelSolrParam.rows`). The prefix constant follows the same convention:
+
+[source,java]
+----
+public static final String HEADER_FIELD_PREFIX = "CamelSolrField.";
+----
+
+=== Protocol and standard headers
+
+Headers that are part of an external wire protocol or standard (HTTP headers,
+JMS properties, Swift API headers, etc.) are *exempt* from the `Camel` prefix
+rule. They use the standard's own name because the framework passes them
+through to the underlying transport.
+
+Examples:
+
+* Swift: `X-Container-Meta-`, `X-Versions-Location`
+* HTTP: `Content-Type`, `Accept`
+* JMS: standard JMS property names
+
+When a component has both Camel-convention headers and protocol pass-through
+headers, document the distinction clearly (see `camel-openstack` Swift
+constants for an example).
+
+=== Exchange properties
+
+Exchange *properties* (set via `Exchange.setProperty()`) are internal to the
+route and are NOT visible to `HeaderFilterStrategy`. They do not require the
+`Camel` prefix, though many core properties use it by convention.
+
+== Security interaction
+
+The `Camel*` prefix is not just cosmetic. `DefaultHeaderFilterStrategy`
+strips headers matching `Camel*` and `org.apache.camel.*` case-insensitively
+from inbound messages. This prevents untrusted external senders from injecting
+Camel-internal routing directives.
+
+When a component header does *not* use the `Camel` prefix, it bypasses this
+security filter entirely. This is why aligning all component headers to the
+`Camel*` namespace is both a consistency improvement and a security hardening
+measure.
+
+See the link:security.adoc[] design document and the
+xref:ROOT:security-model.adoc[] for the full threat model.
+
+== Renaming existing headers
+
+When renaming a non-conforming header to follow this convention:
+
+=== What to change
+
+1. Update the string value in the constants class.
+2. Regenerate all downstream artifacts:
+ - `mvn install -pl <module> -DskipTests`
+ - `mvn install -pl catalog/camel-catalog -DskipTests`
+ - `mvn generate-sources -pl dsl/camel-endpointdsl -DskipTests`
+ - `mvn generate-sources -pl dsl/camel-componentdsl -DskipTests`
+3. Update documentation (`.adoc` files, Javadoc) to reference the new names.
+4. Update tests to use the Java constants (not literal strings).
+
+=== Upgrade guide
+
+Every header rename is a breaking change and MUST be documented in the upgrade
+guide (`docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_XX.adoc`):
+
+* List every old value -> new value.
+* Note which Endpoint DSL method names changed.
+* State that code using the Java constants is unaffected.
+* Warn that code using literal string header names must be updated.
+
+=== Backward compatibility
+
+The project's current policy (as of 4.21) is a *hard break* with no deprecated
+aliases. The Java constant names stay the same, so code using constants
compiles
+and works without changes. But code using literal header strings (XML/YAML
+routes, Simple expressions, tests with hardcoded strings) will silently stop
+matching.
+
+This trade-off favors a clean, consistent header namespace over a gradual
+migration. The upgrade guide is the primary migration aid.
+
+=== Backport policy
+
+When a header rename is backported to a maintenance branch (e.g.,
+`camel-4.18.x`, `camel-4.14.x`):
+
+* Add an upgrade guide entry on the maintenance branch.
+* Also add the corresponding entry on `main` to keep the version-specific
+ upgrade guides in sync (see backport upgrade-guide policy in the project
+ contribution guidelines).
+
+== Scope
+
+This convention applies to:
+
+* All new components (mandatory).
+* Existing components when headers are modified for any reason (opportunistic
+ alignment).
+* Dedicated alignment PRs (the ongoing CAMEL-2357x/CAMEL-2359x effort).
+
+Headers in core (`Exchange.java`) already follow the convention and are not
+being renamed.