[ 
https://issues.apache.org/jira/browse/CAMEL-25678?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Work on CAMEL-25678 started by shashank.
----------------------------------------
> camel-core - Switch EIP case values and the Dynamic Router uriDelimiter do 
> not resolve property placeholders, so a case value with a placeholder never 
> matches and the slip is not split
> ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25678
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25678
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> Every String option of an EIP is passed through property-placeholder 
> resolution when the route is created ({{AbstractReifier.parseString}}); this 
> is also how route template and Kamelet parameters reach an EIP. Two options 
> are used as written instead.
> h3. 1. Switch EIP: the case value
> {{SwitchReifier.createProcessor}} (main cd2ce899764e, lines 51-56) builds the 
> dispatch table from {{c.getValue().toLowerCase(Locale.ENGLISH)}}. The {{uri}} 
> of the case and of {{otherwise}} goes through {{staticUri}}, which calls 
> {{parseString}}, but the value does not. A case such as
> {code:java}
> from("direct:tickets")
>     .doSwitch(header("tier"))
>         .doCase("{{gold.code}}", "direct:gold")
>         .otherwise("direct:standard");
> {code}
> is keyed by the text \{\{gold.code\}\}. No selector result matches it (only a 
> header that literally contains the text \{\{gold.code\}\} does), so every 
> message goes to {{otherwise}}, or continues after the Switch without a 
> destination when there is no {{otherwise}}. Nothing is logged. The same 
> happens in XML and YAML, and for a route template or Kamelet parameter used 
> as a case value (doCase("\{\{tier\}\}", ...) in a {{routeTemplate}}), where a 
> placeholder is the only way to pass the parameter. The duplicate check also 
> compares the unresolved text, so two cases that resolve to the same value are 
> not rejected at startup as the documentation says.
> The Switch documentation says that case and fallback URIs support property 
> placeholders and that values are "literal"; in the design (CAMEL-24988) 
> "literal" is used in contrast to patterns and wildcards. It does not say that 
> values do not support placeholders.
> h3. 2. Dynamic Router EIP: uriDelimiter
> {{DynamicRouterReifier.createProcessor}} (lines 36-37) uses 
> {{definition.getUriDelimiter()}} as written. {{RoutingSlipReifier}} (line 38) 
> and {{RecipientListReifier}} (line 56) resolve their delimiter with 
> {{parseString}}. With uriDelimiter("\{\{delim\}\}") and a slip 
> {{"mock:a;mock:b"}}, the slip is not split and the exchange is sent to one 
> endpoint whose uri is the whole slip (for {{mock:}}, a mock named 
> {{a;mock:b}}); with other components it fails or sends to an unexpected 
> endpoint.
> h3. Reproduction
> New tests in camel-core; on main:
> * {{SwitchEndpointTest.caseValueResolvesPropertyPlaceholder}}: 
> doCase("\{\{switch.tier\}\}", "mock:gold") with {{switch.tier=gold}}, headers 
> {{gold}}, {{GOLD}} and the literal text \{\{switch.tier\}\}: {{mock://gold 
> Body of message: 0. Expected: <first> but was: <third>}} (only the literal 
> placeholder text matched).
> * {{SwitchEndpointTest.caseValueResolvesRouteTemplateParameter}}: a route 
> template with doCase("\{\{tier\}\}", "mock:gold") and {{tier=silver}}: 
> {{mock://gold Body of message: 0. Expected: <first> but was: <second>}}.
> * {{SwitchValidationTest.rejectsDuplicateValuesAfterResolvingPlaceholders}}: 
> doCase("\{\{switch.tier\}\}", ...) and {{doCase("gold", ...)}} start without 
> error: {{Expected java.lang.Exception to be thrown, but nothing was thrown.}}
> * {{DynamicRouterUriDelimiterPlaceholderTest}}: a slip {{mock:a;mock:b}} with 
> uriDelimiter("\{\{slip.delimiter\}\}") and {{slip.delimiter=;}}: {{mock://a 
> Received message count. Expected: <1> but was: <0>}}.
> h3. Proposed fix
> Resolve both with {{parseString}} in the reifier: the case value before it is 
> lower-cased (and before the duplicate check), the {{uriDelimiter}} before the 
> default is applied. Values without placeholders are unchanged. A placeholder 
> of a property that does not exist then fails the route at startup, as it does 
> for the other options.
> Not changed, same pattern, smaller impact (follow-ups if wanted): 
> {{RollbackReifier}} uses {{message}} as written (only the text of the 
> exception), and {{TransformDataTypeReifier}} uses {{fromType}}/{{toType}} as 
> written (fails at startup with "No transformer").
> How it was found: a Lean 4 model of the Switch dispatch table (case value, 
> placeholder resolution, case folding) against the Switch documentation: on 
> main no selector result can select a case whose value contains a placeholder, 
> and with the value resolved before folding the table matches the 
> documentation for every value; the counterexample is checked by {{decide}}. A 
> follow-up sweep of all reifiers for String options that are not passed to 
> {{parseString}} found the Dynamic Router delimiter. The model is a sketch; 
> the tests are the evidence.
> Affected: main (cd2ce899764e; tested). Switch: camel-4.23.x (same line 54, 
> read, not run); the Switch EIP is not on camel-4.22.x and older. Dynamic 
> Router: camel-4.23.x, camel-4.22.x, camel-4.18.x and camel-4.14.x have the 
> same lines 36-37 (read, not run).
> Duplicate check (2026-10-15): JIRA text "uriDelimiter" (only CAMEL-25083, 
> iterating a delimiter-only string), "switch case value placeholder", 
> "dynamicRouter placeholder", summaries with "placeholder" since June 2026 
> (CAMEL-24414, CAMEL-24282, CAMEL-24696 and others, none about these options); 
> GitHub pull requests "Switch EIP", "uriDelimiter", "SwitchReifier" (nothing 
> open or related).
> _Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to