[ 
https://issues.apache.org/jira/browse/CAMEL-25749?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18128443#comment-18128443
 ] 

Claus Ibsen commented on CAMEL-25749:
-------------------------------------

h3. Design, as agreed with Claus (2026-10-18)

{{org.apache.camel.support.BodyFacts}}, in camel-support:

{code:java}
public static String describe(Exchange exchange);                       // what 
the body is, and the step that set it
public static String hint(Exchange exchange, Need need);                // what 
to write: DATA, A_BODY
public static String hint(Exchange exchange, Need need, String target); // 
BYTES: the Content-Type or the file name written
public enum Need { DATA, BYTES, A_BODY }
{code}

* *hint*, not fix: it says what to write, it repairs nothing; the sentence goes 
into the hint argument {{InvalidPayloadException}} already has.
* *Need* is what the failing step needed the body to be, each constant 
documented with its callers as examples:
** *DATA*: the step reads fields ({{$\{body\[sku\]\}}}, {{$\{body.sku\}}}, 
Groovy {{body.sku}}, bean OGNL), so the body must be data: a Map (keys), a List 
(elements) or an object (properties, by getter or field). Not jsonpath, which 
reads JSON text as well.
** *BYTES*: the step writes or sends the payload (an HTTP request or reply, a 
file), so the body must be in its serialized form: text, a byte[], a stream or 
a file; binary counts.
** *A_BODY*: the step needs a body at all (unmarshal, marshal, jsonpath, jq, 
xslt): not null, not empty.
* The class Javadoc carries the table of hints, by need and by what the body is:

||Need||The body is||The hint||
|DATA|text, bytes, a stream, the file as read|unmarshal it first, in the data 
format the file name, the Content-Type or the text names|
|DATA|null|as for A_BODY|
|DATA|a Map without the key|the keys of the Map|
|DATA|an iterator|split it, or have the producer give a List|
|DATA|an object without the property|none: the name is wrong, not the body|
|BYTES|parsed data (a Map, a List) or an object|marshal it first, in the data 
format the Content-Type or the file name being written names|
|BYTES|an iterator|split it, or convert it first|
|BYTES|null, or already text or bytes|none: that is not this failure|
|A_BODY|null, or empty text or bytes|set it first (setBody), or read the data 
with pollEnrich; the step that left it so, when the message history knows|

When nothing names a data format, the hint lists the usual ones (json, 
jacksonXml, csv). The small Content-Type to data format mapping that PR 28048 
put in three classes moves here.

*First PR:* the helper, and the sentences that exist moved onto it: CAMEL-25309 
and CAMEL-25751 (http producer, platform-http reply, file write), CAMEL-25330 
(Groovy), CAMEL-25285 (unmarshal on null), CAMEL-24838 (jsonpath, jq), 
CAMEL-25322 (missing Map key). *Second PR:* the failures that have no sentence 
today ({{$\{body.qty\}}} on a stream cache, {{$\{body.size()\}}} on an 
iterator, ...).

_Claude Code on behalf of davsclaus_

> camel-support - one helper for errors about the message body: what the body 
> is, which step set it, and the step that fixes it
> -----------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25749
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25749
>             Project: Camel
>          Issue Type: Improvement
>          Components: camel-bean, camel-groovy, camel-jq, camel-jsonpath, 
> camel-support
>            Reporter: Claus Ibsen
>            Priority: Major
>             Fix For: 4.24.0
>
>
> Step 1 of the design note of 2026-10-05 on CAMEL-24844 (runtime errors).
> When a step fails because of the Java type of the body, the reader of the 
> error (a person, or a model in a dev loop) needs three facts: what the body 
> is, which step made it so, and the step that fixes it. For example:
> bq. {{$\{body\[amount\]\}}} failed: the body is a GenericFile (the file as 
> read), unchanged since {{from: file:inbox}} (invoices.yaml:30). Unmarshal it 
> first ({{unmarshal: json}}) to read its fields.
> The facts are recorded already: the message history has the body type of 
> every step ({{MessageHistory.getBodyType()}}, 4.23) and the source location 
> of each step (CAMEL-24972). What is missing is one place that says them. 
> Today each failure writes its own partial hint, in its own words:
> * camel-groovy {{GroovyExpression}}: a property read on a body that is still 
> text (CAMEL-25330)
> * camel-support {{UnmarshalProcessor}}: unmarshal on a null body (CAMEL-25285)
> * camel-jsonpath {{JsonPathEngine}} and camel-jq {{JqExpression}}: a null 
> body (CAMEL-24838)
> * camel-bean {{BeanExpression}}: a missing Map key lists the keys of the Map 
> (CAMEL-25322)
> * {{InvalidPayloadException}} and {{NoTypeConversionAvailableException}} name 
> the type of the body, and take a hint from a caller that knows more
> h3. Proposal
> * One helper in camel-support that builds the sentence from the exchange:
> ** the body in plain words: text, bytes, a cached stream, the file as read, 
> parsed data (a Map or a List), an object of a named class, or null;
> ** the step that set it, from the message history: route, node and source 
> location;
> ** the step that fixes it: unmarshal with the data format of the payload, 
> convertBodyTo String, or setBody.
> * With message history off, it still names the body; only the step that set 
> it is left out.
> * The hints above move onto it, so the wording is the same everywhere.
> * Only failures about the body use it: an expression that reads the body 
> (simple and bean OGNL, Groovy, jsonpath, jq), a conversion of the body, 
> {{InvalidPayloadException}}. An error about a header or an exchange property 
> gets no body sentence, as agreed on CAMEL-24844 on 2026-09-20.
> h3. Measure
> The body type collisions per series of the local-model benchmark (19 of 156 
> attempts in the round-2 series), before and after.
> h3. Not in scope
> The static checks of the validator, the observed types (step 2, CAMEL-25750), 
> the catalog metadata (CAMEL-24961).
> _Filed by Claude Code on behalf of davsclaus_



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

Reply via email to