Claus Ibsen created CAMEL-24921:
-----------------------------------
Summary: camel-core: read a predicate inside ${ } in the Simple
language, as EL and Groovy do
Key: CAMEL-24921
URL: https://issues.apache.org/jira/browse/CAMEL-24921
Project: Camel
Issue Type: Improvement
Components: camel-core
Reporter: Claus Ibsen
h3. What the language does today
Tested on 4.23.0-SNAPSHOT:
|| expression || today ||
| {{$\{header.n > 0 ? 'positive' : 'negative'\}}} | works |
| {{$\{header.n > 0\}}} | error: _Operators go outside the function_ |
| {{$\{header.n\} > 0}} | works |
| {{$\{header.n > 0 && header.n < 10 ? 'in' : 'out'\}}} | error (CAMEL-24920) |
Operators inside the braces are already parsed - as the condition of a ternary
- but only comparisons, never {{&&}} or {{||}}, and never a compound condition.
Outside a ternary the same characters are refused. A person has to hold three
overlapping rules in their head.
h3. Why the wrong form is the natural one
Every other language that uses {{$\{ \}}} treats the braces as a complete
expression: Jakarta EL ({{$\{user != null && !user.list.isEmpty()\}}}), Groovy
GString, JavaScript template literals, Thymeleaf with SpEL. In Simple, {{$\{
\}}} delimits a value and the template is what surrounds it. Both models are
defensible - the trouble is that Simple looks like EL and is not.
h3. Evidence that a better message does not fix it
In the AI route benchmark (20 runs of four HTTP examples with a local model
driving the camel-jbang MCP tools), _Operators go outside the function_ fired
56 times across four series. The message already prints the corrected
expression back. Of the 52 refusals followed by another attempt, only *17 were
free of the same mistake* - it is repeated two times out of three. For
comparison, the hint for {{handled: true}} (CAMEL-24915) was obeyed 11 times
out of 11. A message cures a shape nobody has seen before; it does not cure a
habit carried in from another language.
h3. What it would cost, measured
Corpus: every {{$\{...\}}} in a Camel context across camel (route tests via the
{{simple(...)}} literal, route YAML and XML), camel-kamelets, camel-examples
and camel-jbang-examples. Maven properties and prose excluded. *3425 uses, 804
unique expressions.*
How many would an expression parser re-read?
|| rule || re-read ||
| any operator character anywhere | 564 uses (16%) |
| ignoring quotes, {{[...]}} and {{(...)}}, and colon-prefixed functions
({{date:}}, {{bean:}} ...) | 61 uses (1.8%) |
| and requiring whitespace around the operator | *1 use (0.03%)* |
The 61 are all one shape: a dotted name whose last segment has a hyphen -
{{$\{header.Content-Length\}}}, {{$\{exchangeProperty.aws-s3-bucket\}}}. None
has a space around the hyphen. The single remaining use is an existing ternary,
which is meant to be an expression. The bracket form is already safe:
{{$\{header[Content-Type]\}}} and {{$\{header[ce-file]\}}} - 516 of the 564 raw
hits - live inside {{[...]}}, which a top-level scanner never enters.
h3. Proposal
If the inside of {{$\{ \}}} parses as a predicate or an arithmetic expression
*with whitespace-separated operators at the top level*, evaluate it as one;
otherwise it is a function, exactly as today. Simple already requires
whitespace around the ternary's {{?}} and {{:}}, so the rule is not new. This
subsumes the ternary instead of sitting beside it, and CAMEL-24920 disappears
with it.
Before any code:
# a prototype parser with the 3425-expression corpus as a regression suite -
every expression must produce the same value before and after
# a decision on the template case: {{$\{header.n\} > 5}} in a text template
produces {{5 > 5}}, while {{$\{header.n > 5\}}} would produce {{true}}. Both
are useful and they must not collide
# the error message when the inside does not parse, which is where the current
design pays off - it can say what is wrong and where, instead of refusing the
shape
--
This message was sent by Atlassian Jira
(v8.20.10#820010)