Apache Camel 4.x Upgrade Guide
This document is for helping you upgrade your Apache Camel application from Camel 4.x to 4.y. For example, if you are upgrading Camel 4.0 to 4.2, then you should follow the guides from both 4.0 to 4.1 and 4.1 to 4.2.
|
The Camel Upgrade Recipes project provides automated assistance for some common migration tasks. Note that manual migration is still required. See the documentation page for details. |
Upgrading from 4.18.3 to 4.18.4
camel-core - Multicast EIP honors UseOriginalAggregationStrategy
The UseOriginalAggregationStrategy binding has been moved from Splitter and RecipientListProcessor
into MulticastProcessor (their shared base class), so all three EIPs (Multicast, Splitter,
RecipientList) now consistently bind the original exchange on the strategy. Previously, Multicast
never called newInstance(exchange), which made the strategy silently ineffective — especially in
error scenarios where the aggregated result could overwrite the original exchange body instead of
preserving it.
camel-azure-servicebus - Camel-managed message lock renewal
When consuming from Azure Service Bus in PEEK_LOCK mode with maxAutoLockRenewDuration > 0, Camel now
actively renews message locks using a dedicated ServiceBusReceiverAsyncClient and Camel’s internal
PeriodTaskScheduler. This addresses a limitation where the Azure SDK’s built-in lock renewal is tied
to the processMessage callback duration, which returns immediately for asynchronous Camel routes —
causing long-running exchanges to silently lose their message locks.
The new behavior activates automatically when all of the following are true:
-
No custom
processorClientis provided -
Receive mode is
PEEK_LOCK -
maxAutoLockRenewDuration > 0 -
Session mode is disabled
No configuration changes are required. The existing maxAutoLockRenewDuration option controls how long
Camel will continue renewing a message’s lock.
camel-http - gzip double decompression with HttpClient 5.6+
When using HttpClient 5.6+ (including transitively via a Spring Boot BOM on Camel 4.18.x), HttpClient
auto-decompresses gzip response bodies but may leave stale Content-Encoding, Content-Length, and
Content-MD5 headers. Camel now reads content encoding from entity.getContentEncoding() instead of
the response header and strips stale compression headers after the HTTP call. This prevents a second
decompression attempt that could fail with ZipException: Not in GZIP format against gzip-compressing
servers with default settings.
camel-mail - MimeMultipartDataFormat inbound header filtering
When unmarshalling a MIME message with headersInline=true, the mime-multipart data format now applies a
HeaderFilterStrategy to the headers copied from the MIME content onto the Camel message. Camel-internal headers
(the Camel* namespace, matched case-insensitively) present in the external MIME headers are no longer copied onto
the message, consistent with the inbound header filtering already performed by the camel-mail consumer.
Ordinary application headers are unaffected. If a route relied on Camel* headers being propagated from the MIME
content, set them explicitly after unmarshalling.
camel-knative - structured-mode CloudEvent header filtering
When consuming a CloudEvent in structured content mode (application/cloudevents+json), the Knative component now
applies a HeaderFilterStrategy to the event fields (extensions) mapped from the payload onto the Camel message.
Camel-internal headers (the Camel* namespace, matched case-insensitively) present as structured-event fields are
no longer mapped onto the message, consistent with the inbound header filtering already performed on the binary
content-mode / HTTP header path.
Ordinary CloudEvent extension attributes are unaffected. If a route relied on Camel*-named fields being
propagated from the structured payload, set them explicitly after consuming the event.
camel-ironmq - message envelope header filtering
When consuming a message with preserveHeaders=true, the IronMQ consumer now applies a HeaderFilterStrategy to
the header entries embedded in the JSON message envelope before mapping them onto the Camel message. Camel-internal
headers (the Camel* namespace, matched case-insensitively) present in the envelope are no longer mapped onto the
message, consistent with the inbound header filtering performed by other consumers.
Ordinary application headers are unaffected. If a route relied on Camel* headers being propagated from the
message envelope, set them explicitly after consuming the message.
camel-azure-eventhubs - producer now filters Camel-internal headers
The azure-eventhubs producer now applies a DefaultHeaderFilterStrategy to the headers copied onto
EventData application properties. Camel-internal headers (the Camel* namespace, matched
case-insensitively) are no longer forwarded to Azure Event Hubs, consistent with the inbound header
filtering performed by other components.
Ordinary application headers are unaffected.
camel-atmosphere-websocket - potential breaking change
The Exchange header constants in WebsocketConstants have been renamed to follow the
Camel naming convention used across the rest of the component catalog. The Java field
names are unchanged; only the header string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Routes that reference the constant symbolically (for example
setHeader(WebsocketConstants.CONNECTION_KEY, …)) continue to work without changes.
Routes that set the header by its literal string value must be updated to use the new
value.
Upgrading from 4.18.1 to 4.18.3
camel-jackson - potential breaking change
The camel-jackson data format now creates its default ObjectMapper with
MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES enabled, consistent with the mapper used by the
component’s JSON data-type transformer. This is defense-in-depth against gadget-chain deserialization: when
polymorphic / default typing is enabled, Jackson refuses unsafe base types (such as Object, Serializable
or Comparable).
This only affects routes that enable polymorphic / default typing on an unsafe base type; ordinary
marshalling and unmarshalling are unchanged. If you rely on that behaviour, supply your own ObjectMapper
(via the objectMapper option or the registry) configured without this feature.
camel-jacksonxml - potential breaking change
The camel-jacksonxml data format now creates its default XmlMapper with
MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES enabled, mirroring the same hardening applied to
camel-jackson. This is defense-in-depth against gadget-chain deserialization: when polymorphic / default
typing is enabled, Jackson refuses unsafe base types (such as Object, Serializable or Comparable).
This only affects routes that enable polymorphic / default typing on an unsafe base type; ordinary
marshalling and unmarshalling are unchanged. If you rely on that behaviour, supply your own XmlMapper
(via the xmlMapper option) configured without this feature.
camel-jackson-avro and camel-jackson-protobuf - potential breaking change
The camel-jackson-avro and camel-jackson-protobuf data formats now create their default AvroMapper /
ProtobufMapper with MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES enabled, mirroring the same hardening
applied to camel-jackson and camel-jacksonxml. This is defense-in-depth against gadget-chain deserialization:
when polymorphic / default typing is enabled, Jackson refuses unsafe base types (such as Object, Serializable
or Comparable).
This only affects routes that enable polymorphic / default typing on an unsafe base type; ordinary
marshalling and unmarshalling are unchanged. If you rely on that behaviour, supply your own mapper
(via the objectMapper option) configured without this feature.
camel-oauth
UserProfile token verification now fails closed when no JWK set is available: a signed token can no
longer be accepted when the configured JWK set is missing or empty, since its signature cannot be
verified in that case. Deployments with a correctly resolved JWK set are unaffected; this aligns the
legacy UserProfile path with the JwtTokenValidator SPI path.
camel-ftp, camel-sftp, camel-mina-sftp, camel-azure-files, camel-smb
When localWorkDirectory is used, the remote-file consumers now ensure the downloaded local work file
stays within the configured work directory, so a remote file name containing ../ sequences can no longer
resolve to a path outside it. The containment check honours the existing jailStartingDirectory option
(default true); set jailStartingDirectory=false to disable it. A remote file that resolves outside the
local work directory is rejected with a GenericFileOperationFailedException.
camel-spring-ws - potential breaking change
The spring-ws consumer now applies a HeaderFilterStrategy to the SOAP headers it maps onto the
Camel Exchange. The default headerFilterStrategy is a new SpringWebserviceHeaderFilterStrategy
that filters header names starting with Camel / camel (case-insensitive) in both the inbound and
outbound directions, aligning the component with the rest of the Camel component catalog
(camel-cxf, camel-mail, camel-coap, …). SOAP header element and attribute names that fall in
that namespace are no longer propagated as Exchange headers. Routes that relied on receiving such
header names from inbound SOAP headers can supply a custom headerFilterStrategy (via the new
headerFilterStrategy endpoint option) to restore the previous behaviour.
camel-netty-http / camel-undertow - potential breaking change
The muteException consumer option now defaults to true in camel-netty-http and
camel-undertow, aligning these components with the other HTTP server components
(camel-http, camel-jetty, camel-servlet, and camel-platform-http), which have
been defaulting muteException to true for a long time.
When an exchange fails processing on the consumer side, the HTTP response now has an
empty body. Previously the response body contained the exception stack trace as
text/plain.
Routes that rely on the exception stack trace being present in the response body must
set muteException=false explicitly on the endpoint or component after the upgrade:
netty-http:http://0.0.0.0:8080/foo?muteException=false
undertow:http://0.0.0.0:8080/foo?muteException=false
Note that muteException takes precedence over transferException, as it already does
in the other HTTP server components. Routes using transferException=true on these two
components must now also set muteException=false for the serialized exception to be
returned in the response.
camel-keycloak
The KeycloakSecurityPolicy route policy now always verifies the access token when one is present - signature,
issuer and expiry for local JWT verification, or active state and issuer when token introspection is enabled -
even when neither requiredRoles nor requiredPermissions is configured. Previously the token was only verified
when at least one role or permission was required.
Routes that attach a KeycloakSecurityPolicy without any roles or permissions and that previously forwarded an
unverified or invalid token will now have such requests rejected with a CamelAuthorizationException. Provide a
valid, verifiable token (or configure requiredRoles / requiredPermissions) for these routes.
camel-whatsapp
The camel-whatsapp webhook consumer now supports optional verification of inbound webhook event
callbacks via the new webhookSecret endpoint option. When set, event callbacks whose
X-Hub-Signature-256 HMAC-SHA256 signature is missing or invalid are rejected with HTTP 403; when
the option is not set, behaviour is unchanged.
camel-core
The org.apache.camel.support.DefaultHeaderFilterStrategy changed default setting for lowercase from false to true.
camel-jms
JMS ObjectMessage support is now disabled by default. Java object serialization is a recurring source
of security issues, and Camel JMS routes rarely use ObjectMessage in practice. The component will now
refuse to create or read jakarta.jms.ObjectMessage instances unless the new objectMessageEnabled
option is explicitly set to true.
This affects the following endpoint/component options that rely on ObjectMessage internally:
-
jmsMessageType=Object(or sending aSerializablebody that is auto-detected asObject) -
transferExchange=true -
transferException=true -
receiving a JMS
ObjectMessageproduced by an external sender
To restore the previous behavior, enable the option at the component or endpoint level:
camel.component.jms.objectMessageEnabled=true
Or, on a single endpoint:
jms:queue:foo?objectMessageEnabled=true
camel-sjms / camel-sjms2
The same default applies to camel-sjms (and camel-sjms2, which inherits from it): JMS ObjectMessage
support is now disabled by default and gated by a new objectMessageEnabled option (default false)
on SjmsComponent / SjmsEndpoint.
This affects the same endpoint/component options as camel-jms:
-
jmsMessageType=Object(or sending aSerializablebody that is auto-detected asObject) -
transferException=true -
receiving a JMS
ObjectMessageproduced by an external sender
To restore the previous behavior, enable the option at the component or endpoint level:
camel.component.sjms.objectMessageEnabled=true
camel.component.sjms2.objectMessageEnabled=true
Or, on a single endpoint:
sjms:queue:foo?objectMessageEnabled=true
sjms2:queue:foo?objectMessageEnabled=true
camel-aws-bedrock
The applyGuardrail producer operation now reads the guardrail identifier from a new dedicated header
CamelAwsBedrockGuardrailIdentifier (constant BedrockConstants.GUARDRAIL_IDENTIFIER, typed String)
instead of CamelAwsBedrockGuardrailConfig. The CamelAwsBedrockGuardrailConfig header is typed
GuardrailConfiguration and is reserved for the converse and converseStream operations; the
previous code path silently produced null whenever a route mixed converse and applyGuardrail
calls. If you were not setting the guardrail identifier via header, the endpoint-level
guardrailIdentifier option continues to work without changes.
camel-hazelcast
Hazelcast instances created and managed by Camel (when no user-supplied
Config or HazelcastInstance is provided) now apply a default
JavaSerializationFilterConfig on the SerializationConfig of the
Config built by Camel. The default whitelists the class name prefixes
java., javax., org.apache.camel. and blacklists java.net..
This affects:
-
camel-hazelcastcomponent endpoints when neitherhazelcastInstance,hazelcastConfigUri, nor a referencedConfigis supplied -
HazelcastAggregationRepositoryandHazelcastIdempotentRepositorywhen nohazelcastInstanceis supplied -
HazelcastUtil#newInstance()(no-arg)
A user-supplied JavaSerializationFilterConfig (set on the
SerializationConfig of a Config provided via hazelcastConfigUri, a
referenced Config bean, or already wired into a pre-built
HazelcastInstance) is respected and is not overwritten.
Applications that store classes outside the default whitelist on a
Hazelcast topic, queue, map, list, set, or in one of the repositories
above must provide their own Config with a
JavaSerializationFilterConfig configured for their class names.
camel-jgroups - potential breaking change
The Exchange header constants in JGroupsConstants have been renamed to follow
the Camel naming convention used across the rest of the component catalog. The
Java field names are unchanged; only the header string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
This is a breaking change for routes that read or write these headers by
their literal string value. Routes that reference the constant symbolically
(for example setHeader(JGroupsConstants.HEADER_JGROUPS_DEST, …)) continue
to work without changes. Routes that set the header by its literal string
value (for example setHeader("JGROUPS_DEST", …)) must be updated to use
the new value (setHeader("CamelJGroupsDest", …)).
camel-lucene
The Exchange header values exposed by LuceneConstants have been renamed to follow the standard
Camel naming convention. The field names are unchanged, so routes referencing the constants
(LuceneConstants.HEADER_QUERY, LuceneConstants.HEADER_RETURN_LUCENE_DOCS) continue to work
without modification. However, routes that set or read these headers using the raw string values
must be updated:
-
QUERY→CamelLuceneQuery -
RETURN_LUCENE_DOCS→CamelLuceneReturnLuceneDocs
As a consequence, the generated Endpoint DSL header accessors on LuceneHeaderNameBuilder
have been renamed accordingly:
-
qUERY()→luceneQuery() -
returnLuceneDocs()→luceneReturnLuceneDocs()
camel-jgroups-raft
The Exchange header constants in JGroupsRaftConstants have been renamed to
follow the Camel naming convention used across the rest of the component
catalog. The Java field names are unchanged; only the header string values
have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Routes that reference the constant symbolically (for example
setHeader(JGroupsRaftConstants.HEADER_JGROUPSRAFT_SET_TIMEOUT, …)) continue
to work without changes. Routes that set the header by its literal string value
(for example setHeader("JGROUPSRAFT_SET_TIMEOUT", …)) must be updated to
use the new value (setHeader("CamelJGroupsRaftSetTimeout", …)).
camel-elasticsearch-rest-client
The Exchange header constants in ElasticSearchRestClientConstant have been
renamed to follow the Camel naming convention used across the rest of the
component catalog. The Java field names are unchanged; only the header string
values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Routes that reference the constant symbolically (for example
setHeader(ElasticSearchRestClientConstant.SEARCH_QUERY, …)) continue to
work without changes. Routes that set the header by its literal string value
(for example setHeader("SEARCH_QUERY", …)) must be updated to use the
new value (setHeader("CamelElasticsearchSearchQuery", …)).
camel-neo4j
When using the RETRIEVE_NODES or DELETE_NODE operations with the CamelNeo4jMatchProperties
header, the property names provided in the JSON match map are now validated before the MATCH /
DELETE WHERE clause is built. Property names must be valid identifiers matching
[A-Za-z_][A-Za-z0-9_]*. A request whose match map contains a property name that does not match
this pattern now fails fast with an IllegalArgumentException (wrapped in a
Neo4jOperationException) instead of producing a malformed query. Property values continue to be
passed as bound query parameters and are unaffected.
camel-mail
The SMTP producer no longer extracts dynamic JavaMail session properties from message headers by
default. Previously any message header whose key started with mail.smtp. (or mail.smtps.) was
applied to a per-message JavaMailSender, which meant an upstream producer that mapped untrusted
input into the exchange header map (for example platform-http query parameters, JMS or Kafka
messages from untrusted producers) could override transport-security settings such as
mail.smtp.ssl.trust or mail.smtp.starttls.enable, or redirect the SMTP connection.
This behaviour is now disabled by default. Routes that legitimately rely on per-message
mail.smtp. / mail.smtps. headers must opt back in on the endpoint:
.to("smtp://mymailserver:1234?useJavaMailSessionPropertiesFromHeaders=true");
Even with the opt-in, route authors should still strip the namespace with
removeHeaders("mail.smtp.", "mail.smtps.") between any untrusted ingress and the mail producer.
In addition, the inbound MailHeaderFilterStrategy now blocks the mail.smtp. / mail.smtps.
prefix as well, so an external mail message can no longer inject these into a downstream exchange.
camel-jira - potential breaking change
The Exchange header constants in JiraConstants have been renamed to follow the
Camel naming convention used across the rest of the component catalog. The Java
field names are unchanged; only the header string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Routes that reference the constants symbolically (for example
setHeader(JiraConstants.ISSUE_KEY, …)) continue to work without changes.
Routes that set the header by its literal string value (for example
setHeader("IssueKey", …)) must be updated to use the new value
(setHeader("CamelJiraIssueKey", …)).
As a consequence, the generated Endpoint DSL header accessors on
JiraHeaderNameBuilder have been renamed accordingly:
-
issueAssigneeId()→jiraIssueAssigneeId() -
issueAssignee()→jiraIssueAssignee() -
issueComponents()→jiraIssueComponents() -
issueChanged()→jiraIssueChanged() -
issueKey()→jiraIssueKey() -
issuePriorityId()→jiraIssuePriorityId() -
issuePriorityName()→jiraIssuePriorityName() -
projectKey()→jiraIssueProjectKey() -
issueSummary()→jiraIssueSummary() -
issueTransitionId()→jiraIssueTransitionId() -
issueTypeId()→jiraIssueTypeId() -
issueTypeName()→jiraIssueTypeName() -
issueWatchedIssues()→jiraIssueWatchedIssues() -
issueWatchersAdd()→jiraIssueWatchersAdd() -
issueWatchersRemove()→jiraIssueWatchersRemove() -
parentIssueKey()→jiraParentIssueKey() -
childIssueKey()→jiraChildIssueKey() -
linkType()→jiraLinkType() -
minutesSpent()→jiraMinutesSpent()
camel-pdf - potential breaking change
The Exchange header constants in PdfHeaderConstants have been renamed to
follow the Camel naming convention used across the rest of the component
catalog. The Java field names are unchanged; only the header string values
have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Routes that reference the constants symbolically (for example
setHeader(PdfHeaderConstants.PDF_DOCUMENT_HEADER_NAME, …)) continue to
work without changes. Routes that set the header by its literal string value
(for example setHeader("pdf-document", …)) must be updated to use the
new value (setHeader("CamelPdfDocument", …)).
As a consequence, the generated Endpoint DSL header accessors on
PdfHeaderNameBuilder have been renamed accordingly:
-
protectionPolicy()→pdfProtectionPolicy() -
pdfDocument()→pdfDocument()(unchanged in name, returns the new value) -
decryptionMaterial()→pdfDecryptionMaterial() -
filesToMerge()→pdfFilesToMerge()
camel-arangodb - potential breaking change
Two Exchange header constants in ArangoDbConstants that were not in the
Camel namespace (and therefore not filtered by the default
HeaderFilterStrategy) have been renamed to follow the Camel naming
convention. The Java field names are unchanged; only the header string values
have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
The remaining constants (MULTI_UPDATE, MULTI_INSERT, MULTI_DELETE,
AQL_QUERY, AQL_QUERY_BIND_PARAMETERS, AQL_QUERY_OPTIONS) were already
Camel-prefixed and are unchanged.
Routes that reference the constants symbolically (for example
setHeader(ArangoDbConstants.ARANGO_KEY, …)) continue to work without
changes. Routes that set the header by its literal string value (for example
setHeader("key", …)) must be updated to use the new value
(setHeader("CamelArangoDbKey", …)).
As a consequence, the generated Endpoint DSL header accessors on
ArangoDbHeaderNameBuilder have been renamed: key() → arangoDbKey() and
resultClassType() → arangoDbResultClassType().
camel-jt400 - potential breaking change
The two Exchange header constants in Jt400Constants that were not in the
Camel namespace (and therefore not filtered by the default
HeaderFilterStrategy) have been renamed to follow the Camel naming
convention. The Java field names are unchanged; only the header string values
have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
Jt400Constants.KEY is the data-queue key used for keyed-data-queue read and
write operations. The remaining constants (MESSAGE, MESSAGE_ID,
MESSAGE_FILE, MESSAGE_TYPE, MESSAGE_SEVERITY, MESSAGE_DFT_RPY,
MESSAGE_REPLYTO_KEY) were already Camel-prefixed and are unchanged.
Routes that reference the constants symbolically (for example
setHeader(Jt400Constants.KEY, …)) continue to work without changes. Routes
that set the header by its literal string value (for example
setHeader("KEY", …)) must be updated to use the new value
(setHeader("CamelJt400Key", …)).
As a consequence, the generated Endpoint DSL header accessors on
Jt400HeaderNameBuilder have been renamed: kEY() → jt400Key() and
senderInformation() → jt400SenderInformation().
camel-mail - potential breaking change
The consumer-side dispatch header constants in MailConstants that control
post-processing of a consumed mail message used header values outside the
Camel namespace (copyTo, moveTo, delete) and were therefore not
filtered by the default HeaderFilterStrategy. They have been renamed to
follow the Camel naming convention (companion to the CAMEL-23522
mail.smtp.* hardening). The Java field names are unchanged; only the header
string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
The standard RFC 5322 message header constants (MAIL_SUBJECT = Subject,
MAIL_FROM = From, MAIL_TO = To, MAIL_CC = Cc, MAIL_BCC = Bcc,
MAIL_REPLY_TO = Reply-To, MAIL_CONTENT_TYPE = contentType) are
unchanged, as they map directly to the corresponding email fields and
renaming them would break mail interoperability.
The equally-named copyTo and moveTo endpoint URI options on the mail
consumer are also unchanged; only the Exchange header values are affected.
Routes that reference the constants symbolically (for example
setHeader(MailConstants.MAIL_DELETE, …)) continue to work without changes.
Routes that set the header by its literal string value (for example
setHeader("delete", true)) must be updated to use the new value
(setHeader("CamelMailDelete", true)).
As a consequence, the generated Endpoint DSL header accessors on
MailHeaderNameBuilder have been renamed: copyTo() → mailCopyTo(),
moveTo() → mailMoveTo(), and delete() → mailDelete().
camel-github2 - potential breaking change
The producer-side Exchange header constants in GitHub2Constants have been
renamed to follow the Camel naming convention used across the rest of the
component catalog. The Java field names are unchanged; only the header string
values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
The consumer-side constants (GITHUB_COMMIT_AUTHOR, GITHUB_COMMIT_COMMITTER,
GITHUB_COMMIT_SHA, GITHUB_COMMIT_URL, GITHUB_EVENT_PAYLOAD) were already
Camel-prefixed (CamelGitHubCommitAuthor, etc.) and are unchanged, as is the
GITHUB_CLIENT registry-lookup key (github2Client).
Routes that reference the constants symbolically (for example
setHeader(GitHub2Constants.GITHUB_PULLREQUEST, …)) continue to work without
changes. Routes that set the header by its literal string value (for example
setHeader("GitHubPullRequest", …)) must be updated to use the new value
(setHeader("CamelGitHubPullRequest", …)).
As a consequence, the generated Endpoint DSL header accessor
gitHubPullRequestHeadCommitSHA() on GitHub2HeaderNameBuilder has been
renamed to gitHubPullRequestHeadCommitSha(). The remaining accessors
(gitHubPullRequest(), gitHubInResponseTo(), gitHubIssueTitle()) keep
their names but now return the new Camel-prefixed values.
The deprecated camel-github component (predecessor of camel-github2)
is not affected by this change on the 4.18.x line; it remains present in
4.18.x as deprecated and was only removed on the 4.21 development branch.
|
camel-elasticsearch / camel-opensearch - potential breaking change
The Exchange header constants in ElasticsearchConstants and
OpensearchConstants have been renamed to follow the Camel naming convention
used across the rest of the component catalog. The Java field names are
unchanged; only the header string values have changed.
ElasticsearchConstants:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OpensearchConstants:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ElasticsearchConstants.PROPERTY_SCROLL_ES_QUERY_COUNT and
OpensearchConstants.PROPERTY_SCROLL_OPENSEARCH_QUERY_COUNT were already
Camel-prefixed (CamelElasticsearchScrollQueryCount /
CamelOpenSearchScrollQueryCount) and are unchanged.
Routes that reference the constants symbolically (for example
setHeader(ElasticsearchConstants.PARAM_INDEX_NAME, …)) continue to work
without changes. Routes that set the header by its literal string value
(for example setHeader("indexName", …)) must be updated to use the
new value (setHeader("CamelElasticsearchIndexName", …)).
The generated Endpoint DSL header accessors on
ElasticsearchHeaderNameBuilder and OpensearchHeaderNameBuilder have
been renamed accordingly (operation() → elasticsearchOperation() /
opensearchOperation(), indexId() → elasticsearchIndexId() /
opensearchIndexId(), etc.).
camel-google-functions / camel-google-secret-manager - potential breaking change
The Exchange header constants in GoogleCloudFunctionsConstants and
GoogleSecretManagerConstants that carried a GoogleCloudFunctions /
GoogleSecretManager prefix are not in the Camel namespace and were
therefore not filtered by the default HeaderFilterStrategy. They have been
renamed to add the Camel prefix. The Java field names are unchanged; only
the header string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The GoogleSecretManagerConstants.SECRET_ID, VERSION_ID and REPLICATION
constants were already Camel-prefixed and are unchanged.
Routes that reference the constants symbolically (for example
setHeader(GoogleCloudFunctionsConstants.OPERATION, …)) continue to work
without changes. Routes that set the header by its literal string value (for
example setHeader("GoogleCloudFunctionsOperation", …)) must be updated to
use the new value (setHeader("CamelGoogleCloudFunctionsOperation", …)).
The generated Endpoint DSL header accessor names are unchanged (for example
googleCloudFunctionsOperation()), since the Camel prefix is stripped when
deriving the accessor name; the accessors now return the new Camel-prefixed
values.
The companion rename for camel-google-vision, camel-google-text-to-speech
and camel-google-speech-to-text from the same main-branch PR (#23467) is
not backported to 4.18.x because those components were added after the
4.18.x branch point and do not exist on this maintenance branch.
|
camel-openstack - potential breaking change
The Exchange header constants in OpenstackConstants, KeystoneConstants,
NovaConstants, CinderConstants, GlanceConstants, NeutronConstants,
and SwiftConstants have been renamed to follow the Camel naming convention
used across the rest of the component catalog. The Java field names are
unchanged; only the header string values have changed.
Common constants (in OpenstackConstants):
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Keystone (KeystoneConstants):
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Nova (NovaConstants):
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Cinder (CinderConstants):
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Glance (GlanceConstants):
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Neutron (NeutronConstants):
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Swift (SwiftConstants):
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SwiftConstants.CONTAINER_METADATA_PREFIX, SwiftConstants.VERSIONS_LOCATION,
SwiftConstants.CONTAINER_READ, and SwiftConstants.CONTAINER_WRITE
intentionally keep their previous values (X-Container-Meta-,
X-Versions-Location, X-Container-Read, X-Container-Write) because they
are part of the Swift HTTP protocol contract used by openstack4j to forward
container metadata and ACLs to the Swift backend. Renaming them would break
interoperability with the Swift API.
Routes that reference the constants symbolically (for example
setHeader(OpenstackConstants.OPERATION, …)) continue to work without
changes. Routes that set the header by its literal string value (for example
setHeader("operation", …)) must be updated to use the new value
(setHeader("CamelOpenstackOperation", …)).
The generated Endpoint DSL header accessors on each component’s
HeaderNameBuilder are renamed accordingly (operation() →
openstackOperation(), password() → openstackKeystonePassword(),
adminPassword() → openstackNovaAdminPassword(), etc.).
camel-shiro - potential breaking change
The three Exchange header constants in ShiroSecurityConstants that drive
Shiro authentication used header values outside the Camel namespace
(SHIRO_SECURITY_TOKEN, SHIRO_SECURITY_USERNAME, SHIRO_SECURITY_PASSWORD)
and were therefore not filtered by the default HeaderFilterStrategy. They
have been renamed to follow the Camel naming convention. The Java field names
are unchanged; only the header string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
These headers carry credentials and a serialized authentication token, so filtering them at transport boundaries by default is particularly important.
Routes that reference the constants symbolically (for example
setHeader(ShiroSecurityConstants.SHIRO_SECURITY_USERNAME, …)) continue to
work without changes. Routes that set the header by its literal string value
(for example setHeader("SHIRO_SECURITY_USERNAME", …)) must be updated to
use the new value (setHeader("CamelShiroSecurityUsername", …)).
Because the three header values are now in the Camel* namespace, transports
that filter Camel-internal headers by default (JMS, CXF, HTTP, etc.) will
strip the serialized Shiro authentication token before publishing. This is
the intended behavior for untrusted producers. Trusted Shiro-over-transport
routes that previously relied on the token surviving the boundary must opt
those three headers back in via a custom HeaderFilterStrategy, for example:
public class ShiroFriendlyJmsHeaderFilterStrategy extends JmsHeaderFilterStrategy {
@Override
public boolean applyFilterToCamelHeaders(String name, Object value, Exchange ex) {
if (isShiroSecurityHeader(name)) {
return false;
}
return super.applyFilterToCamelHeaders(name, value, ex);
}
@Override
public boolean applyFilterToExternalHeaders(String name, Object value, Exchange ex) {
if (isShiroSecurityHeader(name)) {
return false;
}
return super.applyFilterToExternalHeaders(name, value, ex);
}
private static boolean isShiroSecurityHeader(String name) {
return ShiroSecurityConstants.SHIRO_SECURITY_TOKEN.equalsIgnoreCase(name)
|| ShiroSecurityConstants.SHIRO_SECURITY_USERNAME.equalsIgnoreCase(name)
|| ShiroSecurityConstants.SHIRO_SECURITY_PASSWORD.equalsIgnoreCase(name);
}
}
jmsComponent.setHeaderFilterStrategy(new ShiroFriendlyJmsHeaderFilterStrategy());
A worked example is in ShiroOverJmsTest in the camel-itest module.
camel-web3j - potential breaking change
The Exchange header constants in Web3jConstants have been renamed to follow the
Camel naming convention used across the rest of the component catalog. The Java
field names are unchanged; only the header string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Routes that reference the constants symbolically (for example
setHeader(Web3jConstants.FROM_ADDRESS, …)) continue to work without changes.
Routes that set the header by its literal string value (for example
setHeader("FROM_ADDRESS", …)) must be updated to use the new value
(setHeader("CamelWeb3jFromAddress", …)).
The Web3jConstants.ETH_HASHRATE constant is dual-purpose: it is both the
CamelWeb3jOperation value that dispatches the ethHashrate RPC and the header
name read by the ETH_SUBMIT_HASHRATE operation. Routes that referenced the
literal string "ETH_HASHRATE" (in either role) must be updated to
"CamelWeb3jEthHashrate". Routes using the symbolic constant reference are
unaffected. The other producer-dispatch operation identifiers (WEB3_CLIENT_VERSION,
ETH_GAS_PRICE, ETH_SEND_TRANSACTION, …) keep their previous string values
because they are operation enum values rather than Exchange header names.
As a consequence, the generated Endpoint DSL header accessors on
Web3jHeaderNameBuilder have been renamed accordingly:
-
iD()→web3jId() -
atBlock()→web3jAtBlock() -
aDDRESS()→web3jAddress() -
aDDRESSES()→web3jAddresses() -
fromAddress()→web3jFromAddress() -
toAddress()→web3jToAddress() -
pOSITION()→web3jPosition() -
blockHash()→web3jBlockHash() -
transactionHash()→web3jTransactionHash() -
sha3HashOfDataToSign()→web3jSha3HashOfDataToSign() -
signedTransactionData()→web3jSignedTransactionData() -
fullTransactionObjects()→web3jFullTransactionObjects() -
iNDEX()→web3jIndex() -
sourceCode()→web3jSourceCode() -
filterId()→web3jFilterId() -
databaseName()→web3jDatabaseName() -
keyName()→web3jKeyName() -
nONCE()→web3jNonce() -
headerPowHash()→web3jHeaderPowHash() -
mixDigest()→web3jMixDigest() -
clientId()→web3jClientId() -
gasPrice()→web3jGasPrice() -
gasLimit()→web3jGasLimit() -
vALUE()→web3jValue() -
dATA()→web3jData() -
fromBlock()→web3jFromBlock() -
toBlock()→web3jToBlock() -
tOPICS()→web3jTopics() -
pRIORITY()→web3jPriority() -
tTL()→web3jTtl() -
privateFor()→web3jPrivateFor() -
privateFrom()→web3jPrivateFrom() -
errorCode()→web3jErrorCode() -
errorData()→web3jErrorData() -
errorMessage()→web3jErrorMessage() -
status()→web3jStatus() -
operation()→web3jHeaderOperation() -
ethHashrate()→web3jEthHashrate()
A new accessor web3jOperation() is also generated for Web3jConstants.OPERATION
(the producer dispatch header). This constant did not appear in the catalog
previously, so no DSL accessor renaming applies to it.
camel-milo - potential breaking change
The MiloConstants.HEADER_AWAIT constant, which controls whether milo-client
writes are awaited, used the header value await — outside the Camel
namespace and therefore not filtered by the default HeaderFilterStrategy. It
has been renamed to follow the Camel naming convention. The Java field name is
unchanged; only the header string value has changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
MiloConstants.HEADER_NODE_IDS was already Camel-prefixed
(CamelMiloNodeIds) and is unchanged.
Routes that reference the constant symbolically (for example
setHeader(MiloConstants.HEADER_AWAIT, …)) continue to work without changes.
Routes that set the header by its literal string value (for example
setHeader("await", …)) must be updated to use the new value
(setHeader("CamelMiloAwait", …)).
As a consequence, the generated Endpoint DSL header accessor await() on
MiloClientHeaderNameBuilder has been renamed to miloAwait().
camel-irc - potential breaking change
The Exchange header constants in IrcConstants have been renamed to follow the
Camel naming convention used across the rest of the component catalog. The Java
field names are unchanged; only the header string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Routes that reference the constant symbolically (for example
header(IrcConstants.IRC_SEND_TO) or
setHeader(IrcConstants.IRC_TARGET, …)) continue to work without changes.
Routes that set or read the header by its literal string value (for example
setHeader("irc.sendTo", …)) must be updated to use the new value:
// before
template.sendBodyAndHeader("irc:bot@irc.server.org/#chan", "hello",
"irc.sendTo", "#otherchan");
// after
template.sendBodyAndHeader("irc:bot@irc.server.org/#chan", "hello",
"CamelIrcSendTo", "#otherchan");
camel-mongodb-gridfs
The Exchange header values exposed by GridFsConstants have been renamed to follow the standard
Camel naming convention, bringing camel-mongodb-gridfs in line with the parent camel-mongodb
component (MongoDbConstants.OPERATION_HEADER = "CamelMongoDbOperation"). The Java field names
are unchanged, so routes referencing the constants symbolically
(e.g. GridFsConstants.GRIDFS_OPERATION, GridFsConstants.GRIDFS_OBJECT_ID) continue to work
without modification. However, routes that set or read these headers using the raw string values
must be updated:
-
gridfs.operation→CamelGridFsOperation -
gridfs.metadata→CamelGridFsMetadata -
gridfs.chunksize→CamelGridFsChunkSize -
gridfs.objectid→CamelGridFsObjectId -
gridfs.fileid→CamelGridFsFileId
As a consequence, the generated Endpoint DSL header accessors on GridFsHeaderNameBuilder
have been renamed accordingly:
-
gridfsOperation()→gridFsOperation() -
gridfsMetadata()→gridFsMetadata() -
gridfsChunksize()→gridFsChunkSize() -
gridfsObjectid()→gridFsObjectId() -
gridfsFileid()→gridFsFileId()
camel-solr
The two Exchange header prefix constants in SolrConstants have been renamed to
follow the Camel naming convention already used by the other constants in the
same file (which were renamed in 4.10 under CAMEL-21697). The Java field names
are unchanged; only the prefix string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
Routes that reference the constants symbolically (for example
setHeader(SolrConstants.HEADER_FIELD_PREFIX + "id", …)) continue to work
without changes. Routes that set the headers by their literal string value
(for example setHeader("SolrField.id", …) or
setHeader("SolrParam.commit", …)) must be updated to use the new prefix
(CamelSolrField.id, CamelSolrParam.commit).
Because the renamed prefixes now begin with Camel, they are stripped by the
standard transport HeaderFilterStrategy (HttpHeaderFilterStrategy, etc.)
when crossing a transport boundary, by design — Camel* headers are
framework-internal and are not propagated over the wire. Routes that bridge an
external transport (HTTP, JMS, …) into a solr: producer and want to drive
Solr document fields or query parameters from a header supplied by the sender
must therefore carry the value in a non-Camel-prefixed application header and
map it to the appropriate CamelSolrField. / CamelSolrParam. header in the
route between the transport from and the solr: to.
camel-dapr - potential breaking change
The dapr component now ships a default DaprHeaderFilterStrategy (extending
DefaultHeaderFilterStrategy) and exposes it via the standard headerFilterStrategy
endpoint/component option, aligning the component with the rest of the Camel component
catalog (camel-iggy, camel-kafka, camel-jms, …). The strategy filters headers
starting with Camel / camel (case-insensitive) in both directions.
In addition, the dapr-pubsub consumer no longer copies the inbound CloudEvent’s
pubsubName and topic into the CamelDaprPubSubName (DaprConstants.PUBSUB_NAME)
and CamelDaprTopic (DaprConstants.TOPIC) message headers. These two constants are
producer-direction routing headers: they are read back on the producer side by
DaprConfigurationOptionsProxy and take precedence over the endpoint-configured
pubSubName / topic. Setting them on a consumed exchange caused a route such as
from("dapr-pubsub:configured-pubsub:configured-topic")
.to("dapr-pubsub:configured-pubsub:another-topic");
to carry the inbound pubsubName / topic into the producer hop instead of using the
configured destination. The remaining CloudEvent metadata headers (CamelDaprID,
CamelDaprSource, CamelDaprType, CamelDaprSpecificVersion,
CamelDaprDataContentType, CamelDaprBinaryData, CamelDaprTime,
CamelDaprTraceParent, CamelDaprTraceState) are unchanged and are still set on the
inbound exchange.
Because a dapr-pubsub consumer subscribes to a single, fixed pubSubName / topic,
the removed headers were redundant with the endpoint configuration. Routes that relied
on reading CamelDaprPubSubName / CamelDaprTopic from a consumed exchange should read
the configured destination from the endpoint URI instead.
camel-schematron - potential breaking change
The Schematron rules-compilation TransformerFactory now runs with secure processing enabled
(FEATURE_SECURE_PROCESSING) and with external DTD and external stylesheet access disabled
(accessExternalDTD and accessExternalStylesheet set to empty), as defense-in-depth against XXE and
external-resource resolution while compiling Schematron rules. This matches the hardening already applied
to the component’s SAXParserFactory. The bundled ISO Schematron skeleton stylesheets continue to be
resolved from the classpath via the component’s URIResolver and are therefore unaffected.
If your Schematron rules legitimately reference an external DTD, external entity, or external stylesheet, those references will no longer be resolved and rule compilation will fail; inline the referenced content instead.
Upgrading from 4.18.0 to 4.18.1
camel-bom
The camel-test module has been removed from camel-bom. This module was included by mistake, as since Camel 4, this is
not a JAR but a pom.xml file. Camel end users should use the camel-test-junit5 / camel-test-junit6 JARs and the others directly.
camel-yaml-io / camel-xml-io
In the YAML DSL we have renamed routePolicy to routePolicyRef on the route node,
as that is the correct name.
Saga EIP
The Saga EIP has fixed the model for how to configure completion and compensation URIs.
For Java DSL there is no changes, but XML and YAML DSL is affected. Here the <compensation> and <completion> tags
has been changed to be an attribute on <saga> instead as shown below:
Before:
<route>
<from uri="direct:start"/>
<saga sagaService="mySagaService">
<compensation uri="mock:compensation"/>
<completion uri="mock:completion"/>
<option key="myOptionKey">
<constant>myOptionValue</constant>
</option>
<option key="myOptionKey2">
<constant>myOptionValue2</constant>
</option>
</saga>
<choice>
<when>
<simple>${body} == 'fail'</simple>
<throwException exceptionType="java.lang.RuntimeException" message="fail"/>
</when>
</choice>
<to uri="mock:end"/>
</route>
In YAML DSL the changes are even simpler as the endpoint is moved from uri to the value of completion or compensation.
- route:
from:
uri: direct:start
steps:
- saga:
sagaService: mySagaService
compensation:
uri: mock:compensation
completion:
uri: mock:completion
key: myOptionKey2
- choice:
when:
- expression:
simple:
expression: "${body} == 'fail'"
steps:
- throwException:
message: fail
exceptionType: java.lang.RuntimeException
- to:
uri: mock:end
After:
<route>
<from uri="direct:start"/>
<saga sagaService="mySagaService" compensation="mock:compensation" completion="mock:completion">
<option key="myOptionKey">
<constant>myOptionValue</constant>
</option>
<option key="myOptionKey2">
<constant>myOptionValue2</constant>
</option>
</saga>
<choice>
<when>
<simple>${body} == 'fail'</simple>
<throwException exceptionType="java.lang.RuntimeException" message="fail"/>
</when>
</choice>
<to uri="mock:end"/>
</route>
- route:
from:
uri: direct:start
steps:
- saga:
sagaService: mySagaService
compensation: mock:compensation
completion: mock:completion
key: myOptionKey2
- choice:
when:
- expression:
simple:
expression: "${body} == 'fail'"
steps:
- throwException:
message: fail
exceptionType: java.lang.RuntimeException
- to:
uri: mock:end
camel-simple
In the simple language then init blocks syntax has changed to require that each variable ends with a semicolon and new line (no trailing comments etc is allowed)
For example
- setBody:
simple:
expression: |-
$init{
// this is a java like comment
$sum := ${sum(${header.lines},100)}
$sku := ${iif(${body} contains 'Camel',123,999)}
}init$
orderId=$sku,total=$sum
Should be changed to have semicolons as shown below:
- setBody:
simple:
expression: |-
$init{
// this is a java like comment
$sum := ${sum(${header.lines},100)};
$sku := ${iif(${body} contains 'Camel',123,999)};
}init$
orderId=$sku,total=$sum
camel-mail
When configured a custom IdempotentRepository on camel-mail endpoint, then Camel will now auto-start
the bean which is similar to what camel-file do as well.
camel-json-patch
The camel-json-patch is now deprecated - the library it uses is not active maintained and this module does not work with Jackon 3.
camel-openapi-java
When using code first Rest DSL and have configured base.path then this will now be exclusively used
for the returned server url in the API specification.
For example here we set base.path=cheese:
restConfiguration().component("jetty").host("localhost").port(getPort())
.contextPath("myapp")
.apiContextPath("/api-doc")
.apiProperty("cors", "true").apiProperty("base.path", "cheese")
.apiProperty("api.title", "The hello rest thing").apiProperty("api.version", "1.2.3");
Then the generated API specification now returns:
"servers" : [ {
"url" : "http://localhost:58678/cheese"
} ],
Previously the context-path would always be used:
"servers" : [ {
"url" : "http://localhost:58678/myapp"
} ],
The intention is to allow to configure the base.path as is in the return API specification.
Upgrading Camel 4.17 to 4.18
camel-simple
The simple language has deprecated binary operators that uses space in the name:
-
not containsuse!containsinstead -
not regexuse!regexinstead -
not rangeuse!rangeinstead -
starts withusestartsWithinstead -
ends withuseendsWithinstead
camel-file
The org.apache.camel.component.file.GenericFileOperations has added method storeFileDirectly.
camel-docling
All not working metadata headers have been removed.
The option extractAllMetadata has been removed. Using includeRawMetadata will have the same effect given that there is no more customMetadata available.
It corresponds to the removal of functionality no more working since 4.17. Given that this functionality was never available in a LTS version,that the next LST version is the next one and the fix requires important change in upstream dependency; it is not going through a deprecation phase and removed directly.
DoclingDocument return type
The CONVERT_TO_JSON and EXTRACT_STRUCTURED_DATA operations now return a DoclingDocument object (ai.docling.core.DoclingDocument) in the exchange body instead of a raw JSON string. This applies to both docling-serve API mode and CLI mode (where the JSON output is parsed into DoclingDocument via Jackson).
Code that previously received a String and manually deserialized it should be updated:
// Before (4.17)
String result = template.requestBody("direct:convert", filePath, String.class);
DoclingDocument doc = mapper.readValue(result, DoclingDocument.class);
// After (4.18)
DoclingDocument doc = template.requestBody("direct:convert", filePath, DoclingDocument.class);
The EXTRACT_METADATA operation also now uses DoclingDocument internally instead of re-parsing a JSON string, though the exchange body type (DocumentMetadata) is unchanged.
EXTRACT_STRUCTURED_DATA differentiation
The EXTRACT_STRUCTURED_DATA operation is now differentiated from CONVERT_TO_JSON when using the docling-serve API. It uses a dedicated request builder that enables table structure recognition (doTableStructure=true) by default. Additional enrichment features (code enrichment, formula enrichment, picture classification) can be enabled via the new configuration properties. Previously, both operations produced identical requests to the server.
The BATCH_EXTRACT_STRUCTURED_DATA operation now has its own dedicated implementation (processBatchStructuredData) that sends structured data requests with table structure recognition enabled, matching its single-document counterpart. Previously, it was handled as a plain batch JSON conversion.
processTimeout and HTTP read timeout
The processTimeout configuration property (default: 30000ms) now also controls the HTTP read timeout when using docling-serve API mode. Previously, the HTTP read timeout was not configurable and used the docling-java client library default. For complex PDF documents that require OCR or enrichment processing, increase processTimeout (e.g., to 120000 for 2 minutes).
OCR bridging to API mode
The enableOCR configuration property is now bridged to the docling-serve API mode when explicitly set to false: it sends doOcr(false) to the server to disable OCR. When left at its default value (true), the server uses its own defaults to preserve backward compatibility. For explicit API-mode OCR control, use the new doOcr property instead.
New advanced configuration properties
18 new configuration properties have been added to expose the full ConvertDocumentOptions from the docling-serve SDK: doOcr, forceOcr, ocrEngine, pdfBackend, tableMode, tableCellMatching, doTableStructure, pipeline, doCodeEnrichment, doFormulaEnrichment, doPictureClassification, doPictureDescription, includeImages, imageExportMode, abortOnError, documentTimeout, imagesScale, and mdPageBreakPlaceholder. All default to null and only take effect when explicitly set. These options are applied to every docling-serve API request via the applyConfigurationToOptions method.
camel-qdrant
The class org.apache.camel.component.qdrant.Qdrant.Headers has been removed. It was deprecated since 4.15. It is replaced by org.apache.camel.component.qdrant.QdrantHeaders.
camel-tahu
The upgrade of Tahu from 1.0.17 to 1.0.18 introduced an API break. HostApplicationEventHandler has been renamed to MultiHostApplicationEventHandler and introduced one more parameter on all methods.
Even if the interface HostApplicationEventHandler is public, I do not expect Camel users to use the implementation TahuHostApplicationEventHandler from Camel. Also the change would be relatively trivial. So replacing it without deprecating it first in order to be able to use the latest Tahu version right away.
Consequently, there is an API break org.apache.camel.tahu.handlers.TahuHostApplicationEventHandler has been removed. It is replaced by org.apache.camel.tahu.handlers.MultiTahuHostApplicationEventHandler.
camel-platform-http-vertx and Rest DSL contract-first
When using Rest DSL in contract first style, then the HTTP engine (vertx-web) instead of a single router to handle all incoming Rest API calls, is now one unique router per API endpoint. This change can affect HTTP request validation as vertx/Quarkus is now also performing this per API endpoint according to the API specification.
All together this would make Camel behave similar for Rest DSL for both code first and contract first style.
camel-nats
The default headerFilterStrategy is now a new NatsHeaderFilterStrategy that filters headers
starting with Camel / camel (case-insensitive) in both the inbound and outbound directions,
aligning the component with the rest of the Camel component catalog (camel-kafka, camel-mail,
camel-coap, camel-google-pubsub, …). Routes that relied on passing through these header
names from NATS messages can supply a custom headerFilterStrategy to restore the previous
behaviour.
camel-xmpp
The default headerFilterStrategy is now a new XmppHeaderFilterStrategy that filters headers
starting with Camel / camel (case-insensitive) in both the inbound and outbound directions,
aligning the component with the rest of the Camel component catalog (camel-kafka, camel-mail,
camel-coap, camel-google-pubsub, …). Routes that relied on passing through these header
names from XMPP messages can supply a custom headerFilterStrategy to restore the previous
behaviour.
Component deprecation
The camel-olingo2 and camel-olingo4 component are deprecated.
This is due the Apache Olingo project is EOL and has been moved to the attic and is no longer maintained.
camel-vertx-websocket
The vertx-websocket consumer now applies a HeaderFilterStrategy to the WebSocket query and
path parameters before mapping them into the Camel message headers. The new default
VertxWebsocketHeaderFilterStrategy filters headers starting with Camel / camel
(case-insensitive) in both the inbound and outbound directions, aligning the component with the
rest of the Camel component catalog (camel-coap, camel-kafka, camel-nats, …). A new
headerFilterStrategy endpoint option is available; routes that relied on receiving
Camel-prefixed header names from WebSocket query or path parameters can supply a custom
headerFilterStrategy to restore the previous behaviour.
camel-atmosphere-websocket
The atmosphere-websocket consumer now applies the endpoint HeaderFilterStrategy to the
WebSocket query parameters before mapping them into the Camel message headers. The inherited
default HttpHeaderFilterStrategy filters headers starting with Camel / camel
(case-insensitive). Routes that relied on receiving Camel-prefixed header names from WebSocket
query parameters can supply a custom headerFilterStrategy to restore the previous behaviour.
camel-iggy
The iggy consumer now applies a HeaderFilterStrategy to the Iggy message user-headers before
mapping them into the Camel message headers. The new default IggyHeaderFilterStrategy filters
headers starting with Camel / camel (case-insensitive) in both the inbound and outbound
directions, aligning the component with the rest of the Camel component catalog. A new
headerFilterStrategy endpoint option is available; routes that relied on receiving
Camel-prefixed user-header names from Iggy messages can supply a custom headerFilterStrategy
to restore the previous behaviour.
camel-undertow - potential breaking change
UndertowHeaderFilterStrategy now also filters the legacy websocket.
Exchange-header prefix (in addition to the Camel / camel* /
org.apache.camel.* prefixes it already filtered). This applies to both the
in (wire → exchange) and out (exchange → wire) directions and follows the
dedicated-filter-strategy shape used by CAMEL-23532 for
camel-vertx-websocket / camel-atmosphere-websocket / camel-iggy.
The constants in UndertowConstants (CONNECTION_KEY, CONNECTION_KEY_LIST,
SEND_TO_ALL, EVENT_TYPE, EVENT_TYPE_ENUM, CHANNEL, EXCHANGE) keep
their existing string values (websocket.connectionKey,
websocket.connectionKey.list, websocket.sendToAll, etc.) because they are
part of the undertow component’s externally-visible API contract; routes
referencing them (symbolically or by literal value) continue to work
unchanged within an undertow route.
The behaviour change applies at undertow’s transport boundary:
-
Outbound (exchange → wire): if an exchange ends up at an undertow producer carrying an Exchange header whose name starts with
websocket., that header will no longer be propagated onto the outbound HTTP/websocket request as a wire-level header. -
Inbound (wire → exchange): if an undertow consumer receives a request whose wire-level headers include a name starting with
websocket., that header will no longer be mapped into the resulting Camel exchange.
Note that the HeaderFilterStrategy only governs the transport boundary; it
does not prevent cross-component header injection (for example, an
http → undertow route where the HTTP consumer maps an attacker-supplied
websocket.connectionKey header into the exchange and the undertow producer
then reads it via in.getHeader(…) to dispatch to a specific peer). For
defence in depth at the trust boundary, route authors should explicitly strip
these headers from untrusted inbound traffic, for example:
from("jetty:http://0.0.0.0:8080/api")
.removeHeaders("websocket.*")
.to("undertow:ws://internal-broker/notifications");
Routes that intentionally relied on undertow mapping websocket.* wire
headers in or out can supply a custom headerFilterStrategy endpoint option
to restore the previous behaviour.
camel-undertow - UndertowHeaderFilterStrategy is now the endpoint default
UndertowEndpoint defaulted its headerFilterStrategy to the base
HttpHeaderFilterStrategy, and pushed that strategy into the DefaultUndertowHttpBinding
it creates lazily, overwriting the UndertowHeaderFilterStrategy that the binding installs
in its own constructor. The undertow-specific filtering was therefore not applied on
endpoint-configured routes.
The endpoint now defaults to UndertowHeaderFilterStrategy, which makes two already
documented behaviours take effect:
-
The legacy
websocket.*Exchange-header prefix, added to the in and out filters in 4.14.8 / 4.18.3 / 4.21.0 (see above), is now filtered at the undertow transport boundary as described there. -
Header names that undertow does not accept (those for which
io.undertow.util.HttpString.tryFromStringreturnsnull) are skipped when mapping external headers in, rather than being mapped onto the message.
Ordinary application headers are unaffected, and Rest DSL consumers already used an
undertow-specific strategy (UndertowRestHeaderFilterStrategy) so their behaviour does not
change. Routes that relied on websocket.* headers crossing the undertow boundary in either
direction, and routes that relied on undertow-invalid header names being mapped, can restore
the previous behaviour by configuring headerFilterStrategy explicitly on the endpoint:
from("undertow:http://0.0.0.0:8080/foo?headerFilterStrategy=#myStrategy")
Routes that already supply a custom headerFilterStrategy or a custom undertowHttpBinding
are unaffected.
camel-aws2-sqs
Sqs2HeaderFilterStrategy now also configures an inbound filter aligned with the existing
outbound regex. Headers starting with Camel / camel (case-insensitive), breadcrumbId and
org.apache.camel.* are now filtered in both the inbound and outbound directions, aligning the
component with the rest of the Camel component catalog (camel-kafka, camel-mail,
camel-coap, camel-google-pubsub, …). Routes that relied on receiving these header names
from inbound SQS messages can supply a custom headerFilterStrategy to restore the previous
behaviour.
camel-aws2-sns
Sns2HeaderFilterStrategy now also configures an inbound filter aligned with the existing
outbound regex. Headers starting with Camel / camel (case-insensitive), breadcrumbId and
org.apache.camel.* are now filtered in both the inbound and outbound directions, aligning the
component with the rest of the Camel component catalog. Routes that relied on receiving these
header names on inbound SNS messages can supply a custom headerFilterStrategy to restore the
previous behaviour.
camel-cxf - potential breaking change
The Exchange header constants in CxfConstants (module camel-cxf-common, shared
by camel-cxf and camel-cxfrs) have been renamed to follow the Camel naming
convention used across the rest of the component catalog. The Java field names are
unchanged; only the header string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
Routes that reference the constant symbolically (for example
setHeader(CxfConstants.OPERATION_NAME, …)) continue to work without changes.
Routes that set the header by its literal string value (for example
setHeader("operationName", …)) must be updated to use the new value
(setHeader("CamelCxfOperationName", …)).
In particular, the documented cxfrs SimpleConsumer dispatch idiom that routes
on the operation name by its literal header name must be updated:
// before
from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer")
.recipientList(simple("direct:${header.operationName}"));
// after
from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer")
.recipientList(simple("direct:${header.CamelCxfOperationName}"));
Behaviour change: cross-transport propagation of the operation header
Because the renamed header value now begins with Camel, it is filtered by the
standard transport HeaderFilterStrategy (JmsHeaderFilterStrategy,
HttpHeaderFilterStrategy, etc.) when crossing a transport boundary, by design
— Camel* headers are framework-internal and are not propagated over the wire.
Routes that bridge an external transport (JMS, HTTP, …) into a cxf: producer
and select the SOAP operation from a header supplied by the sender must
therefore carry the operation in a non-Camel-prefixed application header and
map it to CxfConstants.OPERATION_NAME (CamelCxfOperationName) in the route
between the transport from and the cxf: to:
<!-- before -->
<route>
<from uri="jms:queue:bridge.cxf"/>
<to uri="cxf://bean:serviceEndpoint"/>
</route>
<!-- caller sets the header keyed by the pre-rename value:
setHeader("operationName", "greetMe") -->
<!-- after -->
<route>
<from uri="jms:queue:bridge.cxf"/>
<setHeader name="CamelCxfOperationName">
<simple>${header.operationName}</simple>
</setHeader>
<to uri="cxf://bean:serviceEndpoint"/>
</route>
<!-- caller sets a non-Camel-prefixed application carrier header (any name
that is not stripped by the transport HeaderFilterStrategy works);
the route restores the CXF operation header after the transport hop. -->
The same pattern applies to HTTP-based bridges (platform-http/jetty/netty
-http/http → cxf:) and any other transport whose default
HeaderFilterStrategy filters Camel* headers.
camel-dns - potential breaking change
The Exchange header constants in DnsConstants have been renamed to follow the
Camel naming convention used across the rest of the component catalog. The Java
field names are unchanged; only the header string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Routes that reference the constant symbolically (for example
setHeader(DnsConstants.DNS_SERVER, …)) continue to work without changes.
Routes that set the header by its literal string value (for example
setHeader("dns.server", …) or setHeader("term", …)) must be updated to
use the new value:
// before
from("direct:start")
.setHeader("dns.name", constant("www.example.com"))
.setHeader("dns.type", constant("A"))
.to("dns:lookup");
// after
from("direct:start")
.setHeader("CamelDnsName", constant("www.example.com"))
.setHeader("CamelDnsType", constant("A"))
.to("dns:lookup");
Behaviour change: cross-transport propagation of dns.* headers
Because the renamed header values now begin with Camel, they are filtered by
the standard transport HeaderFilterStrategy (JmsHeaderFilterStrategy,
HttpHeaderFilterStrategy, etc.) when crossing a transport boundary, by design
— Camel* headers are framework-internal and are not propagated over the wire.
Routes that bridge an external transport (HTTP, JMS, …) into a dns:
producer and let the sender choose the DNS operation parameters via headers
must therefore carry those parameters in non-Camel-prefixed application
headers and map them to the corresponding DnsConstants value in the route
between the transport from and the dns: to. Allowing untrusted senders
to drive DnsConstants.DNS_SERVER (the recursive resolver target in
dns:dig) without such a mapping step is not the intended use of the
component.
camel-kafka - potential breaking change
The Exchange header constants in KafkaConstants used header values in the
lowercase / dotted kafka.* namespace, outside the Camel namespace, and were
therefore not filtered by the default HeaderFilterStrategy on upstream HTTP /
REST consumers. They have been renamed to follow the Camel naming convention
used across the rest of the component catalog. The Java field names are
unchanged; only the header string values have changed:
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KafkaConstants.MANUAL_COMMIT was already Camel-prefixed
(CamelKafkaManualCommit) and is unchanged.
Routes that reference the constants symbolically (for example
setHeader(KafkaConstants.OVERRIDE_TOPIC, …)) continue to work without
changes. Routes that set or read the headers by their literal string values
(for example setHeader("kafka.OVERRIDE_TOPIC", …) or Simple expressions such
as ${headers[kafka.TOPIC]}) must be updated to use the new values:
// before
from("platform-http:/api/events")
.setHeader("kafka.OVERRIDE_TOPIC", constant("events.topic"))
.to("kafka:default?brokers=localhost:9092");
// after
from("platform-http:/api/events")
.setHeader(KafkaConstants.OVERRIDE_TOPIC, constant("events.topic"))
.to("kafka:default?brokers=localhost:9092");
The generated Endpoint DSL header accessors on KafkaEndpointBuilderFactory
keep their method names (kafkaOverrideTopic(), kafkaTopic(),
kafkaPartitionKey(), …); only the returned string value reflects the new
CamelKafka* convention.
Behaviour change: cross-transport propagation of kafka.* headers
Because the renamed header values now begin with Camel, they are filtered by
the standard transport HeaderFilterStrategy (HttpHeaderFilterStrategy,
JmsHeaderFilterStrategy, etc.) when crossing a transport boundary, by design
— Camel* headers are framework-internal and are not propagated over the wire.
Routes that bridge an external transport (HTTP, JMS, …) into a kafka:
producer and let the sender choose the destination topic via the
kafka.OVERRIDE_TOPIC header must therefore carry that value in a
non-Camel-prefixed application header and map it to
KafkaConstants.OVERRIDE_TOPIC in the route between the transport from and
the kafka: to. Allowing untrusted senders to drive
KafkaConstants.OVERRIDE_TOPIC (which redirects the producer’s target topic)
without such a mapping step is not the intended use of the component.
camel-salesforce - potential breaking change
The Exchange header constants in SalesforceEndpointConfig have been renamed to
follow the Camel naming convention used across the rest of the component catalog,
so that they are governed by the default HeaderFilterStrategy (which only filters
Camel/camel-prefixed headers). The Java field names are unchanged; only the
header string values have changed.
These parameters are dual-use: they can be supplied either as endpoint options (for
example salesforce:query?sObjectQuery=…) or as message headers. The endpoint
option spelling is unchanged — only the header name has changed.
| Constant | Previous value | New value |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Routes that reference the constants symbolically (for example
setHeader(SalesforceEndpointConfig.SOBJECT_QUERY, …)) continue to work without
changes. Routes that set the value as a header by its literal string (for example
setHeader("sObjectQuery", …)) must be updated to the new value
(setHeader("CamelSalesforceSObjectQuery", …)), or preferably switch to the
symbolic constant. The apexQueryParam. header prefix is likewise renamed to
CamelSalesforceApexQueryParam., so a header such as apexQueryParam.foo must now
be set as CamelSalesforceApexQueryParam.foo.
The configuration-only options that are never read from a message header — apiVersion, format, rawPayload, defaultReplayId, fallBackReplayId,
initialReplayIdMap, replayPreset, pubSubDeserializeType, pubSubPojoClass,
notFoundBehaviour and fallbackToLatestReplayId — are unchanged, as is the
Approval API approval / approval.<property> mechanism (whose endpoint-option and
header spellings are intentionally identical and bound to the approval endpoint
parameter name).
Behaviour change: cross-transport propagation
Because the renamed header values now begin with Camel, they are filtered by the
standard transport HeaderFilterStrategy (HttpHeaderFilterStrategy,
JmsHeaderFilterStrategy, etc.) when crossing a transport boundary, by design — Camel* headers are framework-internal and are not propagated over the wire.
Routes that bridge an external transport (HTTP, JMS, …) into a salesforce:
producer and let the sender choose, for example, the SOQL query, the target SObject
or the Apex endpoint via these headers must carry those values in
non-Camel-prefixed application headers and map them to the corresponding
SalesforceEndpointConfig constants in the route between the transport from and
the salesforce: to. As defence-in-depth, strip inbound Camel-internal headers
arriving from untrusted producers with removeHeaders("CamelSalesforce*") (or the
broader removeHeaders("Camel*")) before the producer.
camel-pqc
The key lifecycle managers now store key metadata as JSON instead of using Java serialization.
AwsSecretsManagerKeyLifecycleManager and HashicorpVaultKeyLifecycleManager previously stored the
KeyMetadata as a Base64-encoded, Java-serialized value; they now store it as JSON, consistent with
FileBasedKeyLifecycleManager. Metadata written by previous versions is still read transparently and
is migrated to JSON the next time the metadata is updated.
Because older versions cannot read the new JSON metadata, downgrading after new key metadata has been written is not supported.
camel-azure-storage-blob / camel-azure-storage-datalake - download contained within fileDir
When fileDir is configured, the Azure Storage Blob and DataLake consumers now ensure the downloaded
local file stays within the configured directory, so a remote object name containing ../ sequences
can no longer resolve to a path outside it. This is consistent with the containment already performed
by the file-based consumers.
Ordinary object names are unaffected. A name that resolves outside fileDir is now rejected with an
IllegalArgumentException.
camel-google-storage - downloads are confined to the configured directory
When the consumer is configured with downloadFileName pointing at a directory, the
remote object name is appended to that directory to build the local file to write.
The resolved path is now verified to stay within the configured directory, and an
IllegalArgumentException is thrown if it does not.
Object names are still allowed to contain / and are mapped to sub-directories of the
download directory as before, so nested object names keep working unchanged. Only names
that resolve outside the configured directory are rejected.
If downloadFileName is configured with an expression (i.e. it contains $), the local
path is built by that expression as before and is not subject to this check.