This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new ea62eb669e6b CAMEL-23594: camel-kamelet - Fix kamelet properties being
URL-encoded in YAML DSL
ea62eb669e6b is described below
commit ea62eb669e6b65a92b17e79e4377e904af9eb0e9
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Jun 22 11:44:46 2026 +0200
CAMEL-23594: camel-kamelet - Fix kamelet properties being URL-encoded in
YAML DSL
The YAML DSL was URL-encoding kamelet parameters via
URISupport.createQueryString() (encode=true by default), but
KameletComponent uses useRawUri()=true so the encoding was never
reversed. This caused values like application/json to arrive as
application%2Fjson in kamelet templates.
Skip encoding for kamelet URIs in YamlRoutesBuilderLoader, matching
what KameletDeserializer and YamlSupport already do with
createQueryString(params, false).
Supersedes #23391.
Closes #24170
Co-Authored-By: Claude <[email protected]>
---
.../ROOT/pages/camel-4x-upgrade-guide-4_21.adoc | 10 +++++++
.../camel/dsl/yaml/YamlRoutesBuilderLoader.java | 3 ++-
.../org/apache/camel/dsl/yaml/KameletTest.groovy | 31 ++++++++++++++++++++++
.../dsl/yaml/PipeLoaderErrorHandlerTest.groovy | 8 +++---
.../apache/camel/dsl/yaml/PipeLoaderTest.groovy | 22 +++++++--------
5 files changed, 58 insertions(+), 16 deletions(-)
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
index eb06df2d01e4..eb57a78ee4b4 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
@@ -451,6 +451,16 @@ defense-in-depth only. The primary mitigation should be
configured at the messag
* ActiveMQ Artemis: `deserializationAllowList` / `deserializationDenyList`
(see the Artemis docs)
* ActiveMQ Classic: the `org.apache.activemq.SERIALIZABLE_PACKAGES` system
property
+=== camel-kamelet
+
+Kamelet endpoint URIs constructed from YAML DSL `parameters:` blocks are no
longer URL-encoded at runtime.
+Previously, property values containing special characters (such as `/`) were
incorrectly URL-encoded
+(e.g., `application/json` became `application%2Fjson`), which caused issues
because the Kamelet component
+uses raw URIs and does not decode them. This fix aligns the YAML DSL
`parameters:` handling with how
+inline kamelet URIs (e.g., `kamelet:myKamelet?key=value`) already work.
+
+If you have workarounds in place to deal with encoded kamelet property values,
they can be removed.
+
=== camel-jms
JMS `ObjectMessage` support is now disabled by default. Java object
serialization is a recurring source
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
index 16862746b179..feab814755ab 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/java/org/apache/camel/dsl/yaml/YamlRoutesBuilderLoader.java
@@ -603,7 +603,8 @@ public class YamlRoutesBuilderLoader extends
YamlRoutesBuilderLoaderSupport {
}
if (params != null && !params.isEmpty()) {
- String query = URISupport.createQueryString(params);
+ // kamelet uses useRawUri so parameters should not be encoded
+ String query = URISupport.createQueryString(params, !kamelet);
// CAMEL-23284: restore property placeholders that were URL-encoded
query = query.replace("%7B%7B", "{{").replace("%7D%7D", "}}");
uri = uri + "?" + query;
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletTest.groovy
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletTest.groovy
index b9ef38fcb29a..05b913beeebc 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletTest.groovy
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/KameletTest.groovy
@@ -390,4 +390,35 @@ class KameletTest extends YamlTestSupport {
then:
MockEndpoint.assertIsSatisfied(context)
}
+
+ def "kamelet (properties not url encoded)"() {
+ setup:
+ addTemplate('setPayloadWithType') {
+ from('kamelet:source')
+ .setBody().simple('{{contentType}}')
+ .to("kamelet:sink")
+ }
+
+ loadRoutes '''
+ - from:
+ uri: "direct:start"
+ steps:
+ - kamelet:
+ name: "setPayloadWithType"
+ parameters:
+ contentType: "application/json"
+ - to: "mock:result"
+ '''
+
+ withMock('mock:result') {
+ expectedMessageCount 1
+ expectedBodiesReceived 'application/json'
+ }
+ when:
+ withTemplate {
+ to('direct:start').withBody('hello').send()
+ }
+ then:
+ MockEndpoint.assertIsSatisfied(context)
+ }
}
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/PipeLoaderErrorHandlerTest.groovy
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/PipeLoaderErrorHandlerTest.groovy
index 5f068ae0f5fc..c0dcf4647112 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/PipeLoaderErrorHandlerTest.groovy
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/PipeLoaderErrorHandlerTest.groovy
@@ -79,11 +79,11 @@ class PipeLoaderErrorHandlerTest extends YamlTestSupport {
errorHandlerFactory != null
errorHandlerFactory instanceof DeadLetterChannelDefinition
var eh = errorHandlerFactory as DeadLetterChannelDefinition
- eh.deadLetterUri ==
'kamelet:error-handler?kafkaTopic=my-first-test&logMessage=ERROR%21&kafkaServiceAccountId=scott&kafkaBrokers=my-broker&kafkaServiceAccountSecret=tiger'
+ eh.deadLetterUri ==
'kamelet:error-handler?kafkaTopic=my-first-test&logMessage=ERROR!&kafkaServiceAccountId=scott&kafkaBrokers=my-broker&kafkaServiceAccountSecret=tiger'
eh.redeliveryPolicy.maximumRedeliveries == "1"
eh.redeliveryPolicy.redeliveryDelay == "2000"
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
outputs.size() == 1
with (outputs[0], ToDefinition) {
endpointUri == 'kamelet:log-sink'
@@ -189,7 +189,7 @@ class PipeLoaderErrorHandlerTest extends YamlTestSupport {
eh.redeliveryPolicy.redeliveryDelay == "2000"
eh.getUseOriginalMessage() == "true"
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
outputs.size() == 1
with (outputs[0], ToDefinition) {
endpointUri == 'kamelet:log-sink'
@@ -231,7 +231,7 @@ class PipeLoaderErrorHandlerTest extends YamlTestSupport {
errorHandlerFactory != null
errorHandlerFactory instanceof NoErrorHandlerDefinition
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
outputs.size() == 1
with (outputs[0], ToDefinition) {
endpointUri == 'kamelet:log-sink'
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/PipeLoaderTest.groovy
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/PipeLoaderTest.groovy
index 64c7f6705dc5..66af9b152ab6 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/PipeLoaderTest.groovy
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/PipeLoaderTest.groovy
@@ -53,7 +53,7 @@ class PipeLoaderTest extends YamlTestSupport {
with (context.routeDefinitions[0]) {
routeId == 'timer-event-source'
- input.endpointUri ==
'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello
world!'
input.lineNumber == 7
outputs.size() == 1
with (outputs[0], ToDefinition) {
@@ -294,7 +294,7 @@ class PipeLoaderTest extends YamlTestSupport {
with (context.routeDefinitions[0]) {
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
outputs.size() == 1
with (outputs[0], ToDefinition) {
endpointUri == 'kafka:my-topic'
@@ -352,11 +352,11 @@ class PipeLoaderTest extends YamlTestSupport {
errorHandlerFactory != null
errorHandlerFactory instanceof DeadLetterChannelDefinition
var eh = errorHandlerFactory as DeadLetterChannelDefinition
- eh.deadLetterUri ==
'kamelet:error-handler?kafkaTopic=my-first-test&logMessage=ERROR%21&kafkaServiceAccountId=scott&kafkaBrokers=my-broker&kafkaServiceAccountSecret=tiger'
+ eh.deadLetterUri ==
'kamelet:error-handler?kafkaTopic=my-first-test&logMessage=ERROR!&kafkaServiceAccountId=scott&kafkaBrokers=my-broker&kafkaServiceAccountSecret=tiger'
eh.redeliveryPolicy.maximumRedeliveries == "1"
eh.redeliveryPolicy.redeliveryDelay == "2000"
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
outputs.size() == 1
with (outputs[0], ToDefinition) {
endpointUri == 'kamelet:log-sink'
@@ -395,7 +395,7 @@ class PipeLoaderTest extends YamlTestSupport {
with (context.routeDefinitions[0]) {
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
outputs.size() == 1
with (outputs[0], ToDefinition) {
endpointUri == 'knative:channel/my-messages'
@@ -475,7 +475,7 @@ class PipeLoaderTest extends YamlTestSupport {
with (context.routeDefinitions[0]) {
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
outputs.size() == 1
with (outputs[0], ToDefinition) {
endpointUri ==
'knative:event/org.apache.camel.event.messages?kind=Broker&name=foo-broker'
@@ -585,7 +585,7 @@ class PipeLoaderTest extends YamlTestSupport {
with (context.routeDefinitions[0]) {
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
input.lineNumber == 7
outputs.size() == 1
with (outputs[0], KameletDefinition) {
@@ -627,7 +627,7 @@ class PipeLoaderTest extends YamlTestSupport {
with (context.routeDefinitions[0]) {
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
input.lineNumber == 7
inputType.urn == 'text/plain'
outputType.urn == 'application/octet-stream'
@@ -673,7 +673,7 @@ class PipeLoaderTest extends YamlTestSupport {
with (context.routeDefinitions[0]) {
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
input.lineNumber == 7
inputType.urn == 'camel:text/plain'
outputType.urn == 'camel:application/octet-stream'
@@ -717,7 +717,7 @@ class PipeLoaderTest extends YamlTestSupport {
with (context.routeDefinitions[0]) {
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
input.lineNumber == 7
outputs.size() == 3
with (outputs[0], TransformDataTypeDefinition) {
@@ -769,7 +769,7 @@ class PipeLoaderTest extends YamlTestSupport {
with (context.routeDefinitions[0]) {
routeId == 'timer-event-source'
- input.endpointUri == 'kamelet:timer-source?message=Hello+world%21'
+ input.endpointUri == 'kamelet:timer-source?message=Hello world!'
input.lineNumber == 7
outputs.size() == 3
with (outputs[0], TransformDataTypeDefinition) {