davsclaus opened a new pull request, #28059:
URL: https://github.com/apache/camel/pull/28059

   ## What
   
   [CAMEL-25749](https://issues.apache.org/jira/browse/CAMEL-25749), step 1 of 
the plan on [CAMEL-24844](https://issues.apache.org/jira/browse/CAMEL-24844), 
as agreed on the issue.
   
   A new helper in camel-support, `org.apache.camel.support.BodyFacts`. It says 
what a message body is, which step made it so, and what to write so that a step 
that failed on it gets the body it needs: the facts a person, or a model in a 
dev loop, otherwise gets from a debugger.
   
   ```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 static String dataFormatOf(String contentType);                  // 
json, jacksonXml, csv, yaml or null
   public enum Need { DATA, BYTES, A_BODY }
   ```
   
   - **`describe`** names the body in plain words: text, bytes, a stream, the 
file as read, a Map, a List, an iterator, an object. From the message history 
it adds the step that set it. That is the last node reached with a body of 
another type, so "set by unmarshal at orders.yaml:9". When every node saw the 
same type: "unchanged since from: file://orders". With the message history off, 
the step is left out. URIs are sanitized.
   - **`hint`** says what to write for what the failing step needed. Each 
`Need` constant, and the class Javadoc's table of hints by need and by body, 
document it:
     - `DATA`: the step reads fields. Unmarshal, in the data format the 
Content-Type, the file name or the text names (with xpath for XML, rows for 
CSV). For a Map, its keys. For an iterator, split it.
     - `BYTES`: the step writes or sends the payload. Marshal, in the data 
format the target's Content-Type or file name names, or set the body to the 
text.
     - `A_BODY`: the step needs a body at all. Read the data first: setBody 
with constant: resource:file:..., poll:, pollEnrich or a from: consumer.
     - When nothing names a data format, it lists the usual ones. A hint is 
null when the body is not why the step failed.
   - **No camel-api change.** Callers pass the sentence to the hint argument 
`InvalidPayloadException` already has, and to the message of 
`NoTypeConversionAvailableException`.
   
   ## The sentences that existed move onto it
   
   | where | JIRA | the new sentence (example) |
   |---|---|---|
   | http producer request | CAMEL-25309 | `the body is a Map (LinkedHashMap), 
which is not an HTTP request body: marshal it first (marshal: jacksonXml, for 
the Content-Type application/xml), or set the body to the text` |
   | platform-http reply | CAMEL-25751 | `... which is not an HTTP response 
body: marshal it first (...), or set the body to the text, as the last step of 
the route; or let the REST binding write it (bindingMode: json)` |
   | file write | CAMEL-25751 | `... which is not file content: marshal it 
first (marshal: csv, for the file name lines.csv), or set the body to the text` 
|
   | Groovy on text | CAMEL-25330 | `the body is bytes (a byte[]), not parsed 
data: unmarshal it first (unmarshal: json) to read its fields` |
   | unmarshal on a null body | CAMEL-25285 | `Cannot unmarshal using jackson: 
the body is null, so there is nothing to unmarshal: read the data first - 
setBody with constant: ...; or set allowNullBody=true to skip a null body.` |
   | jsonpath, jq on a null body | CAMEL-24838 | `The jsonpath expression got 
no message body to evaluate: the body is null: read the data first - ...` |
   | a missing key of the body Map | CAMEL-25322 | `(the Map has no key status; 
the body is a Map (LinkedHashMap), set by split (...): its keys are: sku, qty)` 
|
   
   With the message history on (the dev profile), each sentence also names the 
step that set the body. That is what a missing key inside a split over an 
order's lines needs: the body there is a line, not the order. The three copies 
of the Content-Type to data format mapping that #28048 added are gone.
   
   Behaviour changes worth noting:
   - A writing failure on an object, or on an iterator, now gets a hint too, 
not only a Map or a List.
   - "unmarshal on the variable X" keeps its own sentence: it is not about the 
message body.
   
   ## Tests
   
   - **`BodyFactsTest` (camel-core):** the plain words, each hint per need with 
the data format signals, `dataFormatOf`, and the message history in a route 
("set by setBody", "unchanged since from: direct://unchanged").
   - **The tests of the moved sentences**, updated to the one wording: 
`GroovyMissingPropertyHintTest`, `JsonPathNullBodyHintTest`, 
`JqNullBodyHintTest`, `HttpProducerMapBodyTest`, 
`VertxPlatformHttpMapResponseTest`, `FileProducerMapBodyTest`, 
`UnmarshalProcessorTest`, `SimpleSyntaxHintsTest`.
   - **Local runs**, against camel-support and camel-bean from this branch 
through a scratch local repository, 0 failures:
   
   | module | tests |
   |---|---|
   | camel-support | 139 |
   | camel-bean | 9 |
   | camel-groovy | 119 |
   | camel-jsonpath | 133 |
   | camel-jq | 45 |
   | camel-file | 28 |
   | camel-platform-http-vertx | 160 |
   | camel-http | 297 |
   | camel-core (targeted classes) | 41 |
   
   ## Next
   
   The second PR gives a sentence to the failures that have none today: 
`${body.qty}` on the stream cache of an HTTP request, and `${body.size()}` on 
sql's StreamList iterator.
   
   _Claude Code on behalf of davsclaus_
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to