Federico Mariani created CAMEL-24147:
----------------------------------------

             Summary: camel-lra: participant callback URLs are not URL-encoded 
and parseQuery is lossy - compensation breaks for URIs with query parameters or 
options with special characters
                 Key: CAMEL-24147
                 URL: https://issues.apache.org/jira/browse/CAMEL-24147
             Project: Camel
          Issue Type: Bug
          Components: camel-lra
            Reporter: Federico Mariani
         Attachments: LRAUrlEncodingIssueTest.java

h3. Problem

Two related defects:

# {{LRAUrlBuilder.query()}} concatenates keys and values raw 
(components/camel-lra/src/main/java/org/apache/camel/service/lra/LRAUrlBuilder.java:89-98)
 - no {{URLEncoder}}. {{LRAClient.join()}} embeds the compensation/completion 
endpoint URI and all evaluated saga option values as query parameters of the 
participant callback URL registered with the LRA coordinator (Link header). Any 
value containing {{&}}, {{=}}, {{#}}, {{+}} or a space corrupts the callback 
URL.
# {{LRASagaRoutes.parseQuery}} splits with {{element.split("=")}} and takes 
index 1 (LRASagaRoutes.java:71-73), so even a single embedded {{=}} drops 
everything after the second {{=}}. Should be {{split("=", 2)}} with symmetric 
encoding/decoding. Valueless parameters also trigger the noisy 
{{saveArrayAccess}} WARN with a stack trace.

h3. Consequence

For a saga step with e.g. 
{{compensation("seda:cancelOrder?concurrentConsumers=2&size=1000")}} the 
reconstructed URI does not match the registered one, {{verifyRequest()}} throws 
"URI ... is not allowed", and *compensation never runs while the LRA 
coordinator believes it succeeded*. Option values are corrupted the same way 
({{ACME&region=EU}} arrives as {{ACME}}; {{a+b}} arrives as {{a b}} because 
{{URLDecoder}} is applied to text that was never encoded).

This goes unnoticed today only because the documented examples all use plain 
{{direct:}} URIs without parameters.

h3. Reproducer

Attached {{LRAUrlEncodingIssueTest.java}} (goes into 
{{components/camel-lra/src/test/java/org/apache/camel/service/lra/}}, no LRA 
coordinator needed, both tests fail on current main):

* {{testCallbackUrlRoundTrip}}: builds the compensate callback URL exactly like 
{{LRAClient.join()}} and parses it back exactly like 
{{LRASagaRoutes.verifyRequest()}} - values do not round-trip.
* {{testVerifyRequestAcceptsRegisteredUriWithQueryParams}}: simulates the 
coordinator invoking the compensate callback (CamelHttpQuery fallback path of 
CAMEL-17751) - {{verifyRequest}} rejects the registered compensation URI.

h3. Suggested fix

URL-encode key and value in {{LRAUrlBuilder.query()}}, and parse with 
{{split("&")}} / {{split("=", 2)}} plus matching decoding in {{parseQuery}}.

Found during a broader Saga EIP / camel-lra code review (July 2026).

_Claude Code on behalf of Croway_



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to