You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Claus Ibsen (Jira)" <ji...@apache.org> on 2026/10/16 15:00:00 UTC

[jira] [Updated] (CAMEL-25678) 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

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

Claus Ibsen updated CAMEL-25678:
--------------------------------
    Fix Version/s: 4.24.0

> 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
>             Fix For: 4.24.0
>
>
> 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)