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 Camel 4.21 to 4.22

camel-jbang

The Camel JBang CLI (Camel CLI) and TUI have been promoted from Preview to Stable support level. The MCP Server has also been promoted to Stable.

The Camel JBang CLI now automatic resolves quarkus version to use, instead of hardcoded 3.33.1.1 (https://github.com/apache/camel/commit/d1f4713ebdf787ab04a31c50a6f07e3ca66f0c2b).

The camel cmd route-diagram and camel cmd route-topology now accept one or more Camel route source files (instead of only the name/pid of a running integration), so diagrams and inter-route topology can be generated at design/source time without starting the application first, for example:

camel cmd route-diagram routes/*.yaml
camel cmd route-topology routes/*.yaml

route-diagram previously only accepted a single source file; both commands now accept a set of files. route-topology previously required a running integration and printed "No running Camel integration found" when none matched; it now falls back to loading the given files the same way route-diagram already did.

As part of this, camel.main.dumpRoutes=json (used internally by these commands, and available to users dumping route structure to a folder) now additionally writes a route-topology.json file alongside the per-route structure files when topology dumping is enabled (the default). This file is now always written, with empty nodes/edges arrays if there are no routes to connect, so its presence reliably signals that the dump has completed (previously it was silently skipped when there were no routes).

The Camel TUI (camel tui) accepts --theme=dark or --theme=light to choose the color palette at startup. When omitted, the persisted camel.tui.theme value from .camel-cli.properties is used.

The Camel TUI now has a Settings…​ entry in the F2 actions menu for choosing the theme, the starting tab, and the default run-from-folder. These are stored under camel.tui.* keys (camel.tui.theme, camel.tui.startTab, camel.tui.defaultFolder) in the Camel CLI configuration file. Each key is read from and written back to the file where it currently lives: a key present in the local ./camel-cli.properties stays local (project override), while every other key defaults to the global ~/.camel-cli.properties.

The Camel TUI (camel tui) theme is now backed by CSS stylesheets and ships a switchable light/dark palette. Press F4 to toggle at runtime; the selection is persisted as camel.tui.theme in .camel-cli.properties.

The Camel CLI user configuration file has been renamed from camel-jbang-user.properties to camel-cli.properties (global ~/.camel-cli.properties, local ./camel-cli.properties). The dot convention is unchanged: the global file is a hidden dotfile, the local file is visible. On first run the CLI automatically renames a pre-existing global ~/.camel-jbang-user.properties to ~/.camel-cli.properties and a pre-existing local ./camel-jbang-user.properties to ./camel-cli.properties; an existing new file is never overwritten.

Camel CLI launcher Java runtime discovery

The self-contained Camel CLI launcher scripts (bin/camel.sh and bin/camel.bat in the camel-launcher distribution) now share a single Java runtime discovery contract. Candidates are evaluated in this fixed order, and the first one that exists, is executable, and reports a Java major version of at least 17 is used:

  1. JAVACMD (explicit override, unchanged).

  2. $JAVA_HOME/bin/java (%JAVA_HOME%\bin\java.exe on Windows). This is also how the SDKMAN java candidate is honored, since SDKMAN exports JAVA_HOME.

  3. The first java (java.exe) found on PATH.

  4. CAMEL_FALLBACK_JAVA, a new variable set by package-manager installs when the JDK location is deterministic.

Candidates older than Java 17, missing, non-executable, or with unparseable version output are skipped. If none qualify, the launcher now exits nonzero with a diagnostic listing the checked sources instead of attempting to run an unsuitable Java.

The obsolete macOS JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/…​ default was removed from camel.sh; set JAVA_HOME or JAVACMD, or ensure a Java 17+ java is on PATH. The Gentoo java-config auto-detection and the IBM AIX $JAVA_HOME/jre/sh/java probe were also removed; set JAVA_HOME or JAVACMD explicitly on those platforms. JAVA_OPTS handling is unchanged: when unset, the default -Xmx512m heap is applied.

Native camel.exe in the launcher distribution

The camel-launcher distribution now ships two native Windows executables: bin/camel-x64.exe (x86_64) and bin/camel-arm64.exe (aarch64), alongside bin/camel.bat. Both are thin bootstraps: they forward all arguments to the adjacent camel.bat (preserving spaces and Unicode) and return its exit code. They exist so package managers that require a genuine executable (such as WinGet) work correctly. Users may continue to invoke bin\camel.bat; all three behave identically.

The native executables are now cross-compiled from any host OS using clang/llvm-mingw, replacing the previous MSVC-only build that required a Windows host. The build is activated by -Dcamel.exe.build=true or -Prelease and requires llvm-mingw on PATH.

If you have tooling that referenced bin/camel.exe, update it to use bin/camel-x64.exe (for x86_64 Windows) or bin/camel-arm64.exe (for ARM64 Windows).

OpenTelemetry agent export target changes

The --open-telemetry-agent-export option has been extended with new values and a deprecation:

  • observability (new) — exports traces to VictoriaTraces and logs to VictoriaLogs when the observability infra stack is running (camel infra run observability).

  • otlp (new) — generic external OTLP export for traces. Replaces jaeger as the recommended value for sending traces to any external OTLP-compatible collector.

  • jaeger (deprecated) — still works as an alias for otlp. Use otlp instead.

  • tui (unchanged) — embedded receiver in the TUI (default).

The camel.opentelemetry2.exportTarget property in OpenTelemetryTracer now accepts any non-empty value to signal external export mode (previously only "jaeger" was recognized).

Website installers for the Camel CLI

Two canonical installer scripts are now available for installing the Camel CLI Launcher without a package manager:

curl -fsSL https://camel.apache.org/install.sh | sh
irm https://camel.apache.org/install.ps1 | iex

With no arguments, both installers resolve and install the latest published release. An exact version can be requested instead with --version X.Y.Z (install.sh) or -Version X.Y.Z (install.ps1); the requested version is validated and matched against the fetched manifest before anything is downloaded.

Both installers download the release archive from Maven Central, verify it against a SHA-256 recorded in a signed-path manifest before extracting it, and reject archives containing absolute paths, ../ traversal, escaping symlinks/reparse points, or more than one top-level directory. The staged launcher is then run once to confirm a Java 17+ runtime can be discovered (see "Camel CLI launcher Java runtime discovery" above); if that check fails, the previously active installation, if any, is left untouched and the installer exits nonzero.

Installation is always per-user and never requires elevation or sudo:

  • POSIX (install.sh) installs under ${XDG_DATA_HOME:-$HOME/.local/share}/camel-cli/versions/<version> and activates it via a symlink at $HOME/.local/bin/camel. The installer never writes to shell profile files (.bashrc, .profile, etc.); if $HOME/.local/bin is not already on PATH, it prints guidance instead.

  • Windows (install.ps1) installs under %LOCALAPPDATA%\Apache Camel\cli\versions\<version> and activates it via a camel.cmd shim at %LOCALAPPDATA%\Apache Camel\bin\camel.cmd that delegates to the staged camel-x64.exe or camel-arm64.exe (auto-detected). The bin directory is added once, case-insensitively, to the current user’s PATH; the machine PATH is never modified.

Previously installed version directories are left in place after an upgrade or downgrade and must be removed manually. Reinstalling the same version replaces that version directory.

camel-langchain4j-agent

The Agent.chat() method return type has changed from String to Result<String> (from dev.langchain4j.service.Result). This allows the agent producer to expose token usage (input, output, total token count) and finish reason as exchange headers, consistent with the chat, tools, and embeddings components.

If you have a custom Agent implementation, update the chat method signature:

// Before
String chat(AiAgentBody<?> aiAgentBody, ToolProvider toolProvider);

// After
Result<String> chat(AiAgentBody<?> aiAgentBody, ToolProvider toolProvider);

camel-langchain4j-chat

The helper classes OpenAiChatLanguageModelBuilder and HugginFaceChatLanguageModelBuilder have been removed. They were not wired into the component; the chatModel is autowired instead.

If you used these helpers directly, configure your ChatModel with LangChain4j’s own builders or Spring Boot starters and inject it into the component. === camel-openai

The conversationMemory feature on the chat-completion operation has two behavior fixes:

  • User messages are now stored in the CamelOpenAIConversationHistory exchange property (configurable via conversationHistoryProperty) alongside assistant responses. Previously only assistant turns were appended, so code that reads the history property directly will see roughly twice as many entries (alternating user and assistant messages) compared to Camel 4.21 and earlier.

  • When systemMessage is set together with conversationMemory=true, the conversation history is now correctly cleared via exchange.removeProperty(). Previously removeHeader() was used on a property that is stored as an exchange property, so the documented reset had no effect and stale history was kept.

camel-management - Throughput MBean attribute uses EWMA smoothing

The Throughput attribute on the ManagedPerformanceCounter JMX MBean now reports an EWMA (exponentially weighted moving average) value with a 1-minute decay window, instead of the previous raw instantaneous rate. This produces a smoother, more stable reading that converges to the true average throughput rather than oscillating between zero and spike values.

If you have tooling that consumes the JMX throughput value and expects the old instantaneous behavior, be aware that the reported value will now ramp up and decay gradually.

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 processorClient is 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-debezium

The camel-debezium component has upgraded from Debezium 3.5.2 to 3.6.0.

The following 10 Oracle connector options have been removed by Debezium 3.6.0 and are no longer available:

  • logMiningBatchSizeDefault

  • logMiningBatchSizeIncrement

  • logMiningBatchSizeMax

  • logMiningBatchSizeMin

  • logMiningSleepTimeDefaultMs

  • logMiningSleepTimeIncrementMs

  • logMiningSleepTimeMaxMs

  • logMiningSleepTimeMinMs

  • logMiningScnGapDetectionGapSizeMin

  • logMiningScnGapDetectionTimeIntervalMaxMs

If you use any of these options, remove them from your configuration as they will cause errors.

camel-fory with JDK 25+ - Breaking change

Due to new requirements from Apache Fory, when using Apache Fory Dataformat, the JVM parameter --add-opens java.base/java.lang.invoke=ALL-UNNAMED must be provided.

camel-pqc - potential breaking change

The pqc data format now encrypts the message payload with authenticated encryption (AEAD) instead of the previous unauthenticated ECB mode. 128-bit block ciphers are encrypted with GCM and the ChaCha20 stream cipher is encrypted with ChaCha20-Poly1305, so both the confidentiality and the integrity of the data are now protected, and tampered or corrupted messages are detected and rejected on decryption.

As a consequence:

  • The wire format changed. A 12-byte AEAD nonce is now written between the encapsulation and the ciphertext, and the ciphertext carries an authentication tag:

    [4 bytes: encapsulation length] [N bytes: encapsulation] [12 bytes: AEAD nonce] [M bytes: ciphertext + auth tag]

    Data encrypted by Camel 4.21 or earlier (unauthenticated ECB, no nonce) cannot be decrypted by Camel 4.22 or later. Re-encrypt any data at rest with the new version.

  • Only symmetric algorithms that support AEAD are accepted: AES, ARIA, CAMELLIA, CAST6, DSTU7624, GOST3412-2015, SEED, SM4 (GCM) and CHACHA7539 (ChaCha20-Poly1305). The previously accepted RC2, RC5, CAST5, GOST28147, DESEDE and the unauthenticated stream ciphers GRAIN128, HC128, HC256 and SALSA20 are no longer supported and are rejected when the route starts. The default (AES) is unchanged.

  • The message is now processed in memory rather than streamed: the authenticated cipher must verify the authentication tag before releasing any plaintext, so the whole payload is held in memory during marshal and unmarshal. For very large payloads, enable stream caching on the route.

  • The bufferSize option has been removed. It only configured the previous streaming implementation and no longer has any effect with authenticated encryption.

camel-file / camel-ftp / camel-azure-files / camel-smb - preSort option enhanced

The preSort option on the File, FTP, FTPS, SFTP, Azure Files, and SMB consumers has changed from a boolean to a String. Previously, preSort=true sorted files by name only. The option now supports the following values:

  • name — sort by file name ascending (same behavior as old preSort=true)

  • modified — sort by last-modified timestamp ascending (oldest first)

  • size — sort by file size ascending (smallest first)

  • -name, -modified, -size — descending (reverse) order

  • true — backward compatible alias for name

  • false or not set — disabled (default, unchanged)

The pre-sort is applied on the raw file listing before any filtering or eager limiting, which makes it possible to combine preSort=modified with eagerMaxMessagesPerPoll=true and maxMessagesPerPoll=10 to efficiently consume the 10 oldest files without creating Exchange objects for every file on the server.

camel-file - forceWrites option deprecated

The forceWrites producer option on the File endpoint has been deprecated. This option has had no effect since Camel 2.20, when the file-writing implementation was refactored to use java.nio.file.Files.move() and Files.copy() instead of FileChannel-based streaming. The forceWrites flag was intended to call FileChannel.force(true) (fsync) after writing, but no write path has invoked it for several major versions.

The default value has been changed from true to false to reflect the actual behavior. The option will be removed in a future release.

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-pinecone

The tls endpoint option now correctly documents its default as false (previously the catalog listed the default as true, but the runtime value was always false). No behavioral change — the runtime default was already false.

camel-platform-http-main

When authenticationEnabled=true but neither a basic-auth properties file (basicPropertiesFile) nor a JWT keystore (jwtKeystoreType) is configured, Camel now behaves differently under the prod profile (camel.main.profile=prod).

Under the prod profile, startup now fails instead of starting the embedded HTTP server without authentication. Under the dev profile and with no profile configured, the existing warning-only behavior is retained for backward compatibility.

camel-kafka - metadataMaxAgeMs option moved from producer to common

The metadataMaxAgeMs (metadata.max.age.ms) option was incorrectly labeled as producer-only, but is applied to both consumer and producer Kafka clients. The label has been corrected to common.

If you use the Endpoint DSL, the metadataMaxAgeMs method has moved from the producer (advanced) builder to the common builder.

camel-kafka - saslAuthType behavior changes

When saslAuthType is set, the generated JAAS configuration and additional SASL properties are now applied using putIfAbsent semantics, so explicitly configured saslJaasConfig, callback handler classes, or token endpoint URLs take precedence over the auto-generated values.

For OAuth (saslAuthType=OAUTH), the JAAS string now contains only login-module parameters (clientId, clientSecret, scope). The oauth.token.endpoint.uri and callback handler class are set as separate Kafka client properties instead of being embedded in the JAAS string, matching the Kafka client’s expected configuration format.

For Kerberos (saslAuthType=KERBEROS), if the principal is not configured, the configurer now assumes an external JAAS configuration (e.g. via java.security.auth.login.config) and skips JAAS string generation instead of throwing an exception. This supports deployment scenarios where Kerberos is configured externally.

camel-kafka - Producer no longer silently drops scalar Jackson nodes

With useIterator=true, the Kafka producer splits an Iterable body into one record per element. A Jackson JsonNode implements Iterable, so a scalar value node (e.g. an IntNode produced by transform().jq(".my-value")) was seen as an empty iterable and produced no record, silently discarding the message with no exception or log.

Scalar value nodes are now sent as a single record. Only container nodes (ArrayNode, ObjectNode) are still split, which is unchanged. Any convertBodyTo(…​) previously used as a workaround is no longer required.

camel-kafka - sslEndpointAlgorithm=none now disables hostname verification

Setting sslEndpointAlgorithm to none or false now correctly disables SSL hostname verification by setting ssl.endpoint.identification.algorithm to an empty string. Previously the property was simply omitted, which caused Kafka clients to fall back to their default (https), leaving hostname verification silently enabled.

camel-kafka - Auto-generated groupId shared across consumer threads

When no groupId is configured, the auto-generated UUID is now shared across all consumer threads (consumersCount). Previously each thread received its own random UUID, causing each thread to independently consume all partitions, which resulted in every message being processed consumersCount times.

camel-kafka - Batch producer respects endpoint key for plain list elements

The batch producer (when the body is a List) now respects the endpoint-configured key option for elements that do not have a CamelKafkaKey header. Previously, elements without the header would get a null record key even when key=fixedKey was configured on the endpoint. Additionally, plain list elements (not Exchange or Message) are now properly converted to the configured serializer type.

camel-kafka - queueBufferingMaxMessages option deprecated

The queueBufferingMaxMessages producer option has been deprecated. This option has had no effect since the old Scala Kafka producer was removed in Camel 2.17 (CAMEL-9467). Use bufferMemorySize or maxBlockMs instead.

camel-kafka - Manual commit no longer auto-commits offsets

When using allowManualCommit=true together with a DefaultKafkaManualCommitFactory or DefaultKafkaManualAsyncCommitFactory, the framework previously auto-committed offsets for every processed record — even when the route did not call KafkaManualCommit.commit(). This defeated the purpose of manual commit mode and could cause message loss.

The framework no longer auto-commits offsets after processing each partition when manual commit is enabled. Offsets are only committed when the route explicitly calls KafkaManualCommit.commit() on the exchange header. The configured factory still controls whether that explicit commit executes synchronously or asynchronously.

camel-jbang catalog tables fill the terminal width

The camel catalog commands (camel catalog component, camel catalog dataformat, camel catalog language, camel catalog transformer, camel catalog kamelet, …​) now size the DESCRIPTION column to the detected terminal width instead of the previous fixed 80-character cap, so wide terminals show more of the description before it is truncated with an ellipsis. The NAME column width is also standardized across these commands (it previously differed per command, for example 60 for transformer and 30 elsewhere).

Terminal width is now detected on Windows (cmd / PowerShell) via mode con, in addition to the existing COLUMNS / stty size detection. When no terminal can be detected (for example when the output is piped or redirected), the width falls back to 120 columns. For full, untruncated output suitable for scripting, use the --json option.

The camel infra list table now sizes its DESCRIPTION column to the terminal width, and truncates the IMPLEMENTATION and SERVICE_DATA columns with an ellipsis instead of letting the raw service data overflow the terminal. The complete, structured service data remains available via --json.

camel-aws2-kinesis - Fixed-shardId consumer no longer calls DescribeStream on every poll

The Kinesis consumer with a configured shardId previously called the DescribeStream API on every poll cycle to locate the shard, risking AWS rate limits (10 TPS per account) and failing for streams with more than 100 shards (no pagination). The consumer now uses the same cached shard list from the ShardMonitor background thread that the multi-shard path already uses. The ShardMonitor uses the ListShards API (paginated, 100 TPS limit) and now paginates through all pages, supporting streams with any number of shards.

This is a transparent performance improvement with no configuration changes required.

camel-aws2-kinesis - Per-record partition keys in batch producer

The batch producer (body is an Iterable) previously applied a single CamelAwsKinesisPartitionKey header to all records, routing them all to the same shard. A new CamelAwsKinesisPartitionKeys header (List<String>) is now supported: when set, each record in the batch is assigned the partition key at the corresponding index. If the list has fewer entries than records, the remaining records fall back to the single CamelAwsKinesisPartitionKey header. The existing single-key behavior is unchanged when the new header is not set.

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 (see the localWorkDirectory note in the 4.21 upgrade guide).

Ordinary object names are unaffected. A name that resolves outside fileDir is now rejected with an IllegalArgumentException.

camel-weaviate - potential breaking change

The Weaviate Java client has been upgraded from v5 (io.weaviate:client) to v6 (io.weaviate:client6). This is a major upgrade with several breaking changes.

Scheme default value

The scheme endpoint option now defaults to http. Previously it had no default. Routes that relied on the old behavior (passing no scheme) should explicitly set scheme=http or scheme=https as appropriate.

Collection name case sensitivity

Weaviate v6 requires collection names to start with an uppercase letter (PascalCase). Existing routes using lowercase collection names (e.g., weaviate:myCollection) must be updated to use PascalCase (e.g., weaviate:MyCollection).

New gRPC configuration options

The v6 client requires a gRPC connection in addition to the HTTP connection. Two new endpoint options have been added: grpcHost (defaults to the HTTP host) and grpcPort (defaults to 50051). When connecting to a Weaviate server that exposes gRPC on a non-default host or port, these options must be set explicitly.

Response body types changed

The exchange body returned by the producer no longer uses io.weaviate.client.base.Result<T> wrappers. Code that casts the response body must be updated:

Action Old body type New body type

CREATE_COLLECTION

Result<Boolean>

Boolean

CREATE

Result<WeaviateObject>

WeaviateObject<Map<String, Object>>

UPDATE_BY_ID

Result<Boolean>

Boolean

DELETE_BY_ID

Result<Boolean>

Boolean

DELETE_COLLECTION

Result<Boolean>

Boolean

QUERY

Result<GraphQLResponse>

QueryResponse<Map<String, Object>>

QUERY_BY_ID

Result<List<WeaviateObject>>

Optional<WeaviateObject<Map<String, Object>>>

The WeaviateObject class has also moved from io.weaviate.client.v1.data.model to io.weaviate.client6.v1.api.collections and uses accessor methods (uuid(), properties()) instead of getter methods (getId(), getProperties()).

Client type changed

The autowired client type has changed from io.weaviate.client.WeaviateClient to io.weaviate.client6.v1.api.WeaviateClient. Routes that inject a custom WeaviateClient instance must update the import and construction to use the v6 API (e.g., WeaviateClient.connectToCustom(…​) instead of new WeaviateClient(config)).

Readiness check removed

The v5 client performed a readiness check (misc().readyChecker()) during client creation and threw an exception if the Weaviate server was not ready. The v6 client no longer performs this check at startup. Errors will now surface on the first operation instead of during endpoint initialization.

Proxy configuration removed

The v6 client no longer supports HTTP proxy configuration. The proxyHost, proxyPort, and proxyScheme endpoint options have been removed.

New operations

Four new operations have been added to the Weaviate component, leveraging v6 client capabilities:

  • BATCH_CREATE — Insert multiple objects in a single call. The exchange body must be a List<WeaviateObject<Map<String, Object>>>. Returns an InsertManyResponse.

  • HYBRID_QUERY — Keyword + vector hybrid search. The exchange body is the query text (String). Supports CamelWeaviateQueryTopK (default 10), CamelWeaviateHybridAlpha (0.0 = pure BM25, 1.0 = pure vector), CamelWeaviateQueryVector (optional pre-computed vector to override server-side vectorizer), and CamelWeaviateFields headers. Returns a QueryResponse<Map<String, Object>>.

  • BM25_QUERY — Keyword-only (BM25) search. The exchange body is the query text (String). Supports CamelWeaviateQueryTopK and CamelWeaviateFields headers. Returns a QueryResponse<Map<String, Object>>.

  • AGGREGATE — Returns aggregate statistics for a collection. No body required. Returns an AggregateResponse with totalCount() and per-property aggregations.

camel-spring-boot - Duration configuration properties

The following configuration properties are now bound as java.time.Duration instead of raw milliseconds (long/int):

  • camel.routecontroller.initial-delay

  • camel.routecontroller.back-off-delay

  • camel.routecontroller.back-off-max-delay

  • camel.routecontroller.back-off-max-elapsed-time

  • camel.startupcondition.interval

  • camel.startupcondition.timeout

Plain numeric values in application.properties/application.yaml are still interpreted as milliseconds, so existing configurations keep working unchanged. In addition, readable duration values such as 5s or 2m are now supported.

This is a source-incompatible change for code that reads these values programmatically: the getters and setters of SupervisingRouteControllerConfiguration and CamelStartupConditionConfigurationProperties now use java.time.Duration instead of long/int.

The clustered route controller property camel.clustered.controller.initial-delay is unchanged: it keeps its String type because it supports Camel time patterns (for example 10 seconds) that Duration binding does not.

camel-spring-rabbitmq - replyTimeout default aligned

The replyTimeout option on the component level has been fixed to default to 30 seconds, aligning it with the endpoint-level default that was documented since Camel 3.20.7 / 3.21. Previously, the component-level default was still 5 seconds, which would override the endpoint’s declared 30-second default. If you were relying on the effective 5-second timeout, you can restore it by explicitly setting replyTimeout=5000 on the component or endpoint.

camel-spring-rabbitmq - queue durable default changed to true

The queue durable default has been changed from false to true when using autoDeclare. This aligns queues with the exchange default (which was already durable=true) and with RabbitMQ 4.3+ which no longer permits non-durable, non-exclusive queues by default (the transient_nonexcl_queues deprecated feature is now denied by default).

If you were relying on non-durable queues, you can restore the previous behavior by explicitly setting arg.queue.durable=false&arg.queue.exclusive=true on the endpoint URI. Note that RabbitMQ 4.3+ requires non-durable queues to also be exclusive.

camel-core - Multicast UseOriginalAggregationStrategy fix

The Multicast EIP now correctly honors UseOriginalAggregationStrategy, consistent with the Splitter and Recipient List EIPs. Previously, Multicast did not bind the original exchange on the strategy, so the strategy was silently ineffective — especially in error scenarios where the aggregated result could overwrite the original exchange body instead of preserving it.

camel-sql - PostgreSQL aggregation repositories fixed

PostgresAggregationRepository and ClusteredPostgresAggregationRepository were broken since Camel 3.4: every insert failed with a parameter-index error because the version column was bound but not included in the generated INSERT …​ ON CONFLICT DO NOTHING statement. Both repositories now include the version column in the insert, and the clustered variant also writes the instance_id column to the completed table when recoveryByInstance is enabled (previously instance-scoped recovery could never match any row).

The aggregation tables used with these repositories must have the version BIGINT column, as already required by JdbcAggregationRepository for reading and updating aggregates. When recoveryByInstance is enabled, the completed table must have the instance_id VARCHAR(255) column as documented.

camel-pqc - String payloads are signed and verified as UTF-8

The sign, verify, hybridSign and hybridVerify operations previously encoded a String message body using the JVM default charset (String.getBytes()). The default charset is platform dependent, so signing on one JVM and verifying on another with a different default could disagree on the bytes of a non-ASCII payload and make verification fail.

String bodies are now always encoded as UTF-8. On Java 18 and newer the default charset is already UTF-8 (JEP 400), so this is a no-op there; on Java 17 with a non-UTF-8 default, the signature of a non-ASCII String payload changes. Binary bodies (byte[], InputStream) are unaffected, as they are signed byte-for-byte. === camel-sql - Schema-qualified aggregation repository names

The table-name validation in JdbcAggregationRepository now accepts schema-qualified names such as myschema.aggregation. Previously the validation regex only allowed simple identifiers ([a-zA-Z_][a-zA-Z0-9_]*), rejecting any name containing a dot. Names starting with a digit, containing spaces, or with multiple dots (e.g. catalog.schema.table) are still rejected.

camel-sql - New exceptions from aggregation and template parsing

The remove() method in JdbcAggregationRepository and ClusteredJdbcAggregationRepository now throws OptimisticLockingException when it detects a stale version during the delete. Previously a stale remove was silently treated as successful. If your error handling or aggregation strategy catches specific exception types around remove(), you may need to account for OptimisticLockingException.

The TemplateParser now catches TokenMgrError (a JavaCC lexer error) and wraps it in ParseRuntimeException. Previously a malformed stored-procedure template with characters outside the token alphabet would propagate as a raw java.lang.Error.

camel-aws-cloudtrail - consumer event delivery fixed

The CloudTrail consumer previously kept its lookup cursor in a static field (shared across all cloudtrail consumers in the JVM), issued a single non-paginated LookupEvents call with a default maxResults of 1, and advanced the cursor by the newest event time plus one second. As a result it could silently drop events. The consumer now keeps the cursor per-endpoint, paginates through every page of the window, and de-duplicates events by id at the window boundary.

Two behavior changes follow:

  • The default maxResults is now 50 (the AWS maximum). With pagination this is a page-size hint, not a per-poll cap; set it lower to reduce page sizes.

  • On startup the consumer tails events from the moment it starts, rather than first replaying the single most-recent historical event.

camel-aws2-kinesis - Custom KinesisResumeAction requires a public no-arg constructor

Custom KinesisResumeAction subclasses registered in the Camel registry under the CamelKinesisDbResumeAction key must now provide a public no-arg constructor. The consumer creates a separate instance per shard via reflection to avoid concurrent mutation when multiple shards are processed in parallel. Per-shard state (builder, shardId, streamName) is injected via setters after construction. Any initialization that was previously done in a parameterized constructor should be moved to setters or to the evalEntry method.

camel-aws2-sqs - per-message delay skipped for delay queues and FIFO queues

The SQS producer no longer sets per-message DelaySeconds when delayQueue=true (delay is queue-level) or when the queue is FIFO (AWS rejects per-message delay with InvalidParameterValue). Previously the CamelAwsSqsDelayHeader header was applied unconditionally, which could cause AWS errors on FIFO queues and was redundant on delay queues. If your route relied on per-message delay overrides on a delay queue, the override will now be silently ignored.

camel-xslt-saxon - secure processing now applied unconditionally

The secureProcessing option (default true) is now applied to the Saxon TransformerFactory unconditionally. Previously it was only set when saxonExtensionFunctions was configured, meaning the default configuration silently ran without FEATURE_SECURE_PROCESSING.

Additionally, the Saxon factory now sets ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_STYLESHEET to empty strings (matching the behavior of the plain xslt component), restricting stylesheet-driven external fetches.

Users of Saxon Professional or Enterprise editions who rely on Java extension functions called from XSLT stylesheets must now explicitly set secureProcessing=false on the endpoint.

camel-core - InMemorySagaCoordinator now propagates finalization outcome

The InMemorySagaCoordinator used for the Saga EIP (when no external LRA coordinator is configured) previously returned an already-completed future from compensate() and complete(), meaning the exchange finished before any compensation or completion endpoints had been invoked. Finalization failures were only logged as warnings and never propagated to the caller.

The coordinator now returns the actual finalization future, so the exchange waits for the compensation or completion callbacks to finish (including retries). If all retry attempts fail, the failure is propagated as an exception on the exchange, consistent with the camel-lra coordinator behavior.

This is a behavior change: routes that previously completed immediately regardless of compensation/completion outcome will now wait for finalization and may see exceptions that were previously swallowed. If your route relies on fire-and-forget saga finalization, consider using MANUAL completion mode instead.

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-azure-storage-datalake - openInputStream no longer uses Blob Query API

The getFile operation on the Data Lake consumer/producer now uses the standard client.openInputStream().getInputStream() instead of client.openQueryInputStream("SELECT * from BlobStorage"). The previous implementation relied on the Blob Query API, which had known issues requiring a SkipLastByteInputStream workaround. The SkipLastByteInputStream class in camel-util has been deprecated and will be removed in a future version.

camel-azure-storage-blob - page-blob range calculation corrected

The page-blob getRange calculation has been corrected from end - start to end - start + 1, since Azure page blob ranges are inclusive on both ends. If you had a workaround adjusting the range values to compensate for this off-by-one, it should be removed.

camel-bindy - BigDecimal precision default changed

The @DataField.precision() attribute default has changed from 0 to -1 (meaning "unset"). Previously, a BigDecimal field without an explicit precision would throw ArithmeticException on unmarshal when the input had decimal places, and silently truncated decimals to zero on marshal. With this fix, omitting precision preserves the original scale from the input value.

The @DataField.rounding() attribute is now honored for BigDecimal fields that do not use a pattern. Previously it was only applied when a pattern was specified.

If you relied on the implicit precision=0 behavior to round BigDecimal values to integers, add precision = 0 explicitly to your @DataField annotation.

camel-xslt / camel-xslt-saxon - transformerFactoryConfigurationStrategy now honored

The transformerFactoryConfigurationStrategy option is now applied on all factory creation paths. Previously on xslt-saxon it was never invoked, and on plain xslt it was only invoked when transformerFactoryClass was explicitly set.