From eeb47511e7e2a2ac34353711602d9ce8ff97077f Mon Sep 17 00:00:00 2001 From: croway Date: Wed, 2 Sep 2026 15:15:33 +0200 Subject: [PATCH 1/4] docs: upgrade notes for the camel-spring-boot 4.23 starter changes Adds the upgrade guide entries for the camel-spring-boot changes landing in 4.23 under CAMEL-24498, CAMEL-24500, CAMEL-24501, CAMEL-24505, CAMEL-24506, CAMEL-24577, CAMEL-24592 and CAMEL-24593, next to the entries already present for that release. Co-Authored-By: Claude Opus 5 Co-Authored-By: Claude Fable 5.1 --- .../pages/camel-4x-upgrade-guide-4_23.adoc | 257 ++++++++++++++++++ 1 file changed, 257 insertions(+) diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc index 39ac96390335e..e838ac3459b41 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc @@ -1240,6 +1240,263 @@ unaffected. `String` to `java.io.File` is unchanged: there the `String` genuinely is a path. +==== camel-observability-services-starter narrows its injected defaults + +The starter contributes a set of management defaults as soon as it is on the classpath. Three of them were +wider than the Spring Boot or Camel setting they replaced, and have been brought back in line. + +The management listener now binds to loopback. `management.server.port` was injected without a matching +`management.server.address`, so adding the starter opened a second listener on every interface. Spring Boot +ships no separate management listener at all, so that listener and its reach are now both a deliberate choice. + +Deployments whose kubelet probes or Prometheus scrapers reach the pod over the network — which is every +Kubernetes deployment using the health and metrics endpoints — must widen the bind address explicitly: + +[source,properties] +---- +management.server.address = 0.0.0.0 +---- + +Doing so should be paired with a `NetworkPolicy` or with authentication in front of the management port. + +`management.endpoint.health.show-details` is now `when-authorized` instead of `always`, so the aggregate +`/observe/health` endpoint shows its individual indicators to an authenticated caller and a bare status to +everybody else. Camel health checks report on the resources a route talks to, and their detail can identify +those resources. With no Spring Security on the classpath the endpoint behaves as `never`. To restore the +previous behaviour: + +[source,properties] +---- +management.endpoint.health.show-details = always +---- + +The `live` and `ready` health groups keep `show-details=always`. The kubelet reads them unauthenticated and +puts the response body into the probe-failure event, so `kubectl describe pod` still names the indicator that +took the pod down, and those groups hold availability-state indicators that report a status and carry no data. + +`camel.health.exposure-level` is no longer forced to `full` and now follows the Camel default of `default`, +which filters health check metadata — endpoint URIs, route and consumer identifiers — out of the health +response while keeping the check names, error messages and stack traces. To opt back in: + +[source,properties] +---- +camel.health.exposure-level = full +---- + +The defaults are still registered as the lowest precedence property source, so all three settings are +overridden by ordinary application configuration. The full injected set is documented in the +xref:spring-boot::starters/observability-services.adoc[starter documentation]. + + +==== camel-debug-starter no longer opens a JMX connector by default + +`camel.debug.jmx-connector-enabled` now defaults to `false` instead of `true`. Adding +`camel-debug-starter` to the classpath still installs and enables the `BacklogDebugger`, which is what +the starter is for, but it no longer creates an RMI registry and JMX RMI server on +`camel.debug.jmx-connector-port` (`1099`). Nothing listens until the connector is asked for. + +Unlike camel-main, where `camel.debug.enabled` defaults to `false` and so the connector is only reached +after the debugger is explicitly turned on, the starter enables the debugger as soon as it is on the +classpath. That made the dependency alone enough to open a port, and the connector is created without +authentication or transport security: anyone able to reach it can suspend routes and read message +payloads. + +Tooling that attaches to the debugger from another process — the IntelliJ IDEA and VS Code Camel +plugins — needs the connector, and must now request it: + +[source,properties] +---- +camel.debug.jmx-connector-enabled = true +camel.debug.jmx-connector-port = 1099 +---- + +Enable it only on a trusted network, with the port bound to a loopback interface or protected by a +firewall. + +The `camel debug` command of Camel JBang is unaffected: it drives a Spring Boot application through the +local CLI connector from `camel-cli-connector-starter`, not through JMX. + + +==== camel-spring-boot health check stack traces moved to the full exposure level + +The Camel health indicator added the full stack trace of a failed health check as `error.stacktrace` to the +per-check data in `/actuator/health` at every exposure level except `oneline`. A DOWN check whose result +carries an exception — a consumer that lost its broker, a pool that cannot connect — therefore serialised the +whole cause chain into the actuator response at the default exposure level. + +`error.stacktrace` is now emitted only when the exposure level is `full`. `error.message` is still reported at +the `default` level, which mirrors what Spring Boot's own health indicators expose, and matches how the other +runtimes report a failed check: camel-main's management endpoint includes `error-stacktrace` only when the +caller asks for it with `?stackTrace=true`, and camel-quarkus-microprofile-health never emits one. It also +matches the documented meaning of the levels, where `full` is the level that includes all details from the +invoked health checks. The trace is unchanged in the application log. + +A deployment that consumed the trace from the actuator response can opt back in with: + +[source,properties] +---- +camel.health.exposure-level = full +---- + +Note that `full` also stops filtering the health check metadata out of the per-check data, so the output is +more verbose than the previous default in other respects too. + + +==== camel-platform-http-starter deletes multipart uploads when the exchange completes + +Multipart file uploads are copied out of the servlet container into the servlet temporary directory so that they +remain readable after the HTTP request has completed. These temporary copies were never removed and accumulated for +the lifetime of the application. They are now deleted when the exchange is done being routed, that is after the +response has been written, which aligns the starter with the `deleteUploadedFilesOnEnd` option of +`camel-platform-http-vertx` and with `camel-http-common`, where the container deletes its own part files. + +Routes that consume the upload while the exchange is being routed (saving it with the file producer, streaming it to +a remote system, unmarshalling it) are unaffected. A route that stores the temporary path and reads the file after +the exchange has completed must opt out and delete the file itself: + +[source,properties] +---- +camel.component.platform-http.server.delete-uploaded-files-on-end=false +---- + + +==== camel-platform-http-starter path variables follow the matched path + +Path variable headers are now taken from the path Spring matched the request against, instead of from +the undecoded request URI. The values are therefore percent-decoded and carry no matrix parameters, +which is what the vertx engine has always provided. + +For a consumer such as `platform-http:/greeting/{name}`: + +[cols="1,1,1"] +|=== +|Request |Header `name` before |Header `name` now + +|`/greeting/%61dmin` +|`%61dmin` +|`admin` + +|`/greeting/John%20Doe` +|`John%20Doe` +|`John Doe` + +|`/greeting/name;v=1` +|`name;v=1` +|`name` +|=== + +An application that decoded the header itself, or that parsed matrix parameters out of it, must drop +that handling. Requests whose path variables contain no percent-encoding and no matrix parameters are +unaffected. + +`CamelHttpPath` (`Exchange.HTTP_PATH`) is unchanged: it still reports the raw request path with the +servlet context-path removed. + + +==== camel-micrometer-starter bounds the uri tag + +The starter contributes the `uri` low cardinality tag of the `http.server.requests` metrics when +`camel.metrics.uri-tag-enabled = true`. Two things change in this release. + +First, the property is now matched in its documented kebab-case form. The auto-configuration was conditional on +`camel.metrics.uriTagEnabled`, a spelling that Spring Boot cannot resolve from a relaxed binding source, so an +application that configured `camel.metrics.uri-tag-enabled = true`, the name listed in the starter +documentation, never got the Camel uri tag at all. Both spellings now enable it. An application that had the +kebab-case property set therefore starts seeing Camel consumer paths in the `uri` tag where it previously saw +the value computed by Spring. + +Second, when a request does not resolve to a Camel HTTP consumer — a 404, or any request served by something +else than the Camel servlet — the tag was the requested path (servlet path plus path info) verbatim. Micrometer +registers a meter per distinct tag value and keeps it for the lifetime of the process, so the number of meters +followed the number of distinct paths that had been requested, instead of the number of routes. Such requests +now keep the `uri` value computed by Spring's own `DefaultServerRequestObservationConvention`: the mapped +pattern for a Spring MVC endpoint, and a constant such as `UNKNOWN`, `NOT_FOUND` or `REDIRECTION` otherwise. +This is what `camel.metrics.uri-tag-enabled` already documents ("will be marked as UNKNOWN"). Requests that do +resolve to a Camel consumer are unchanged, the tag is the static consumer path, such as `/users/{id}`. + +With `camel.metrics.uri-tag-dynamic = true` the requested path is still used, such as `/camel/users/123`, but +only for requests that resolve to a Camel consumer, and the tag value is now capped at 200 characters. + +Dashboards and alerts that matched on the raw path of requests that are not served by Camel must use the Spring +value instead, for example the mapped pattern `/actuator/health` of a Spring MVC endpoint. + + +==== camel-jasypt-starter defaults to PBEWITHHMACSHA256ANDAES_256 + +`camel.component.jasypt.algorithm` now defaults to `PBEWITHHMACSHA256ANDAES_256` instead of `PBEWithMD5AndDES`. +The starter already recognises that algorithm as one that requires an initialization vector, so +`org.jasypt.iv.RandomIvGenerator` is installed automatically when `camel.component.jasypt.iv-generator-class-name` +is not set. + +This is a breaking change for existing encrypted values: a value produced under `PBEWithMD5AndDES` cannot be +decrypted with the new default, and startup fails with an `EncryptionOperationNotPossibleException` when the +property is resolved. Either re-encrypt the values with the new algorithm, or pin the previous default: + +[source,properties] +---- +camel.component.jasypt.algorithm = PBEWithMD5AndDES +---- + +Whichever Jasypt tooling is used to produce the ciphertext must be given the same algorithm *and* a random IV +generator — the Jasypt CLI defaults to no IV generator, and a value encrypted without one cannot be decrypted by +the starter: + +[source,bash] +---- +jbang org.apache.camel:camel-jasypt: \ + -c encrypt -p "$JASYPT_PASSWORD" -i my-secret-value \ + -a PBEWITHHMACSHA256ANDAES_256 -riga SHA1PRNG +---- + +The `camel-jasypt` component itself is unchanged: `JasyptPropertiesParser` leaves the algorithm unset, so it still +falls back to the Jasypt library default of `PBEWithMD5AndDES`. Aligning the component with the starter is a +separate change; until it lands, an application that configures `JasyptPropertiesParser` directly keeps the old +algorithm unless it sets one. + +The starter's usage documentation no longer shows the master password next to the encrypted value it protects. Use +the `sysenv:` or `sys:` prefixes of `camel.component.jasypt.password` to read it from the environment or a JVM +system property, or inject it from an external secret store. + + +==== Starter configuration options that cannot be bound are reported + +The starters bind `camel.component.*`, `camel.dataformat.*` and `camel.language.*` onto the Camel component, +data format or language they configure. Two steps of that binding used to discard a configured value without +reporting it, so a mistyped or unbindable option left the target at its default and nothing appeared in the +log. Both now report the value they cannot use, which matches what `camel.rest.*` has always done. + +An option of a complex (object) type is configured with a reference to a bean, such as: + +[source,properties] +---- +camel.component.http.ssl-context-parameters = #bean:mySslContextParameters +---- + +The generated converter used to return `null` for any value that did not start with `#`, and for a value +naming a bean that does not exist. A typo in the bean id therefore produced a component with the option +unset. Such a value now aborts startup with a message naming the value, the target type and the +configuration prefix it was set under. A plain bean id with no `#` prefix — `mySslContextParameters` — is +resolved rather than discarded, as are `#autowired` and `#type:com.foo.MyType`. + +The generated customizers copied the whole configuration onto the target with `failIfNotSet=false`, so an +option with no matching setter on the target was dropped without a log line. An option that the application +configured itself and that cannot be set now aborts startup. An option that only carries the default the +generator took from the Camel catalog is logged at `DEBUG` and ignored, since the target keeps its own +default and there is nothing to fix in the application. The options belonging to the auto-configuration +layer itself — `enabled` and `customizer` — are removed before the copy, as they were never options on the +Camel target. + +An application that set an option which never took effect will therefore now fail to start. The remedy is +to correct or remove the reported option. To restore the previous tolerance while doing so: + +[source,properties] +---- +camel.springboot.lenient-configuration-binding = true +---- + +Such an option is then logged at `WARN` with its name, instead of being dropped silently as before. + + === camel-azure-storage-blob and camel-azure-storage-datalake Local downloads configured with `fileDir` now resolve existing filesystem path segments before checking From 3406c55a57c91410e90295b775af801c21a707b5 Mon Sep 17 00:00:00 2001 From: croway Date: Wed, 2 Sep 2026 16:11:41 +0200 Subject: [PATCH 2/4] docs: correct the health check stack trace note for camel-spring-boot 4.23 camel-microprofile-health also emits error.stacktrace at the default exposure level, and Camel Quarkus builds its health responses through that module, so the note no longer claims otherwise and instead states that the same gating is applied there. Co-Authored-By: Claude Fable 5.1 --- .../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc index e838ac3459b41..a0933bca64184 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc @@ -1325,11 +1325,12 @@ carries an exception — a consumer that lost its broker, a pool that cannot con whole cause chain into the actuator response at the default exposure level. `error.stacktrace` is now emitted only when the exposure level is `full`. `error.message` is still reported at -the `default` level, which mirrors what Spring Boot's own health indicators expose, and matches how the other -runtimes report a failed check: camel-main's management endpoint includes `error-stacktrace` only when the -caller asks for it with `?stackTrace=true`, and camel-quarkus-microprofile-health never emits one. It also -matches the documented meaning of the levels, where `full` is the level that includes all details from the -invoked health checks. The trace is unchanged in the application log. +the `default` level, which mirrors what Spring Boot's own health indicators expose; camel-main's management +endpoint is stricter still and includes `error-stacktrace` only when the caller asks for it with +`?stackTrace=true`. `camel-microprofile-health`, through which Camel Quarkus builds its health responses, applies +the same gating from this release so the runtimes stay aligned. It also matches the documented meaning of the +levels, where `full` is the level that includes all details from the invoked health checks. The trace is +unchanged in the application log. A deployment that consumed the trace from the actuator response can opt back in with: From a52e52cd0a147b17440e2029a36dfd600e7f8960 Mon Sep 17 00:00:00 2001 From: croway Date: Wed, 2 Sep 2026 16:28:13 +0200 Subject: [PATCH 3/4] docs: link the observability starter page by URL in the 4.23 upgrade guide The camel-spring-boot docs component is not part of this repository's Antora build, so the xref-check cannot resolve an xref into it. Use the published page URL instead. Co-Authored-By: Claude Fable 5.1 --- .../modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc index a0933bca64184..fd7d410d1a7fc 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc @@ -1285,7 +1285,7 @@ camel.health.exposure-level = full The defaults are still registered as the lowest precedence property source, so all three settings are overridden by ordinary application configuration. The full injected set is documented in the -xref:spring-boot::starters/observability-services.adoc[starter documentation]. +https://camel.apache.org/camel-spring-boot/next/starters/observability-services.html[starter documentation]. ==== camel-debug-starter no longer opens a JMX connector by default From 375aa683d71383d40f0be635385e458f55ad44f9 Mon Sep 17 00:00:00 2001 From: croway Date: Wed, 2 Sep 2026 19:05:02 +0200 Subject: [PATCH 4/4] docs: update the camel-spring-boot binding note for the converter scoping and legacy customizers The generated converters now only resolve bean references for Camel's own configuration classes, and the lenient copyProperties path used by hand-written customizers logs a warning; both are called out. Co-Authored-By: Claude Opus 5 Co-Authored-By: Claude Fable 5.1 --- .../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc index fd7d410d1a7fc..d696fa8ee1bdc 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc @@ -1479,6 +1479,12 @@ unset. Such a value now aborts startup with a message naming the value, the targ configuration prefix it was set under. A plain bean id with no `#` prefix — `mySslContextParameters` — is resolved rather than discarded, as are `#autowired` and `#type:com.foo.MyType`. +These converters are registered with `@ConfigurationPropertiesBinding` and therefore take part in every +`@ConfigurationProperties` binding in the application, not only in Camel's own. A binding whose target class +is neither under `org.apache.camel` nor annotated with `@ConfigurationProperties` for a `camel.` prefix keeps +the previous behaviour, so adding a starter to the classpath cannot make an unrelated application property +fail to bind. + The generated customizers copied the whole configuration onto the target with `failIfNotSet=false`, so an option with no matching setter on the target was dropped without a log line. An option that the application configured itself and that cannot be set now aborts startup. An option that only carries the default the @@ -1497,6 +1503,14 @@ camel.springboot.lenient-configuration-binding = true Such an option is then logged at `WARN` with its name, instead of being dropped silently as before. +This affects hand-written code as well. `CamelPropertiesHelper.setCamelProperties(context, target, properties, +false)`, and `CamelPropertiesHelper.copyProperties` which calls it, are public API used by hand-written +customizers and auto-configuration outside the generated starters. They keep ignoring an option that cannot +be set — that behaviour is unchanged — but each such option is now logged at `WARN` naming the option and the +target class, where previously nothing was logged at all. Applications with hand-written customizers may +therefore see new `WARN` lines at startup for options that have never been applied. The generated starters no +longer use that path; they call `CamelPropertiesHelper.copyConfigurationProperties` instead. + === camel-azure-storage-blob and camel-azure-storage-datalake