You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Federico Mariani (Jira)" <ji...@apache.org> on 2026/07/16 09:31:00 UTC
[jira] [Updated] (CAMEL-24147) 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
[ https://issues.apache.org/jira/browse/CAMEL-24147?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Federico Mariani updated CAMEL-24147:
-------------------------------------
Attachment: LRAUrlEncodingIssueTest.java
> 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
> Priority: Major
> 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®ion=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)