This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch CAMEL-25928-body-type-resolver in repository https://gitbox.apache.org/repos/asf/camel.git
commit 06ce281ebbf3a7f460e69965ce289284e7d1b0d7 Author: Claus Ibsen <[email protected]> AuthorDate: Sun Oct 25 08:58:24 2026 +0100 CAMEL-25928: docs - Message Body Types, a page about the body types: what they are, the tools that use them, how to declare them, and their JSON with the rule to read it Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../modules/ROOT/partials/body-types.adoc | 2 +- docs/user-manual/modules/ROOT/nav.adoc | 1 + .../user-manual/modules/ROOT/pages/body-types.adoc | 329 +++++++++++++++++++++ .../modules/ROOT/pages/camel-catalog.adoc | 106 +------ .../modules/ROOT/pages/camel-jbang-mcp.adoc | 2 +- .../modules/ROOT/pages/camel-jbang-validation.adoc | 2 +- .../modules/ROOT/pages/endpoint-annotations.adoc | 4 +- 7 files changed, 344 insertions(+), 102 deletions(-) diff --git a/docs/components/modules/ROOT/partials/body-types.adoc b/docs/components/modules/ROOT/partials/body-types.adoc index 8df01700d940..a79f7abeeb2b 100644 --- a/docs/components/modules/ROOT/partials/body-types.adoc +++ b/docs/components/modules/ROOT/partials/body-types.adoc @@ -16,6 +16,6 @@ ifeval::[{bodytypecount} != 0] jsonpathTable::{body-types-module}:example$json/{shortname}.json['nodes$.bodyTypes.*','camel.bodySide(path[2])|camel.bodyCarriers(value)|camel.bodyDescription(value)','camel=xref:ROOT:js/camel.js'] The bodies are the ones with the default options. A side that is not listed is not known, and tooling does not guess -it. The carriers are described in the xref:manual::camel-catalog.adoc[Camel Catalog]. +it. The carriers, the sides and the tools that use them are described in xref:manual::body-types.adoc[Message Body Types]. endif::[] // body types: END diff --git a/docs/user-manual/modules/ROOT/nav.adoc b/docs/user-manual/modules/ROOT/nav.adoc index 702ca4ebea49..8440caa8c701 100644 --- a/docs/user-manual/modules/ROOT/nav.adoc +++ b/docs/user-manual/modules/ROOT/nav.adoc @@ -113,6 +113,7 @@ ** xref:jmx.adoc[JMX] ** xref:key-value-repository.adoc[KeyValueRepository] ** xref:lifecycle.adoc[Camel Lifecycle] +** xref:body-types.adoc[Message Body Types] ** xref:message-size.adoc[Message Size] ** xref:oncompletion.adoc[OnCompletion] ** xref:pluggable-class-resolvers.adoc[Pluggable Class Resolvers] diff --git a/docs/user-manual/modules/ROOT/pages/body-types.adoc b/docs/user-manual/modules/ROOT/pages/body-types.adoc new file mode 100644 index 000000000000..608279dffa0d --- /dev/null +++ b/docs/user-manual/modules/ROOT/pages/body-types.adoc @@ -0,0 +1,329 @@ += Message Body Types + +*Available as of Camel 4.24* + +Every step of a route needs some kinds of message body and leaves one. The `file` consumer gives the file it read, +`unmarshal: json` turns text into a `Map` or a `List`, and the `file` producer writes text, bytes, a stream or a file, +but not a `Map`. When the body one step leaves is not a body the next step can take, the route fails, but only when a +message gets there. + +Camel describes these bodies in its catalog, as the _body types_ of each component, data format, language and EIP. +They say what each step needs and what it leaves, with its default options and with the options that change it. Tools +read them to tell before the route runs what the body is at each step, and where it does not fit. + +The body types help you: + +* *Find a route that cannot work before it runs.* The YAML validator follows the body through the steps of each route, + and reports a step that cannot take the body it gets, with a hint of what to add. +* *Know what a step gives without reading its code.* The documentation page of each component, data format, language + and EIP has a _Message Body_ section, and the Camel CLI and its MCP server show the same. +* *Write routes with AI.* An AI assistant that reads the body types writes steps that fit together, such as a + `marshal` before a step that sends text. +* *See what the body was when the routes ran.* With the message history on, Camel records the body each step has been + reached with. A step reached with bodies of more than one kind is a part of the route that needs attention. + +== Carriers: the kinds of body + +A body type names the _carriers_ of the body: the kinds of Java object it can be in. They are coarse on purpose: a +carrier that is right is better than a precise Java type that is wrong. + +[width="100%",cols="1,3,1",options="header"] +|=== +| Carrier | The body is | Kind at runtime +| `null` | No body. | `null` +| `text` | A `String`. | `payload` +| `bytes` | A `byte[]`. | `payload` +| `stream` | An `InputStream`, a `Reader`, or the stream cache of Camel. | `payload` +| `file` | A file: the `GenericFile` of the file consumers, a `java.io.File` or a `Path`. | `payload` +| `value` | A single value: a number, a boolean or an enum. | `payload` +| `map` | A `java.util.Map`, such as a JSON object parsed, or a row of a query. | `data` +| `pojo` | Another Java object, such as a DOM `Document` or a class a payload is unmarshalled into. | `data` +| `list` | A `List`, another `Collection` or an array, such as a JSON array parsed, or the rows of a query. | `collection` +| `iterator` | An `Iterator`, read once, element by element, with no size and no index. | `collection` +|=== + +Three more words have a meaning of their own: + +* `unchanged` -- the body after the step is the body before it, such as after a `log` or a `to: kafka`. +* `any` -- the step takes any body, such as a `setHeader`. Only for the bodies a step needs. +* `unknown` -- the body depends on what the other system sends, or on a class the user configures. Tools must not guess + it. Only for the body after a step. + +The _kinds_ are what Camel records at runtime (see xref:components:eips:message-history.adoc[Message History]): a +step reached with bodies of one kind, such as `String` and `byte[]`, is dynamic but fine; a step reached with a payload +for some messages and data for others needs attention. + +== Sides: what a step needs and what it leaves + +The body types of a model are a set of _sides_. A side that is not listed is not known. + +[width="100%",cols="1,1,3",options="header"] +|=== +| Model | Side | The body +.4+| Component | `consumerOut` | The body of the message the consumer creates: what a `from` gives the route. +| `consumerReply` | The bodies a consumer that answers the caller can reply with: what the route can end with. +| `producerIn` | The bodies the producer can send or write: what a `to` needs. +| `producerOut` | The body after the producer. +.4+| Data format | `marshalIn` | The bodies the data format can marshal. +| `marshalOut` | The body after `marshal`. +| `unmarshalIn` | The bodies the data format can unmarshal. +| `unmarshalOut` | The body after `unmarshal`. +.2+| Language | `expressionIn` | The bodies the expressions of the language can read. +| `expressionOut` | The result of an expression. +.3+| EIP | `eipIn` | The bodies the EIP needs, such as text for `tokenizer`. +| `eipOut` | The body after the EIP. +| `eipSteps` | The body the steps of the EIP start with, such as each part for `split`. +|=== + +== Examples + +=== A step that cannot take the body + +This route reads JSON files, parses them, and writes them to another directory: + +// yaml-validator: skip +[source,yaml] +---- +- route: + from: + uri: file:inbox + steps: + - unmarshal: + json: {} + - to: + uri: file:outbox +---- + +The `file` consumer gives the file (`consumerOut` is `file`), `unmarshal: json` leaves a `Map` or a `List` +(`unmarshalOut`), and the `file` producer needs text, bytes, a stream or a file (`producerIn`). So the validator +reports the `to`: + +[source,text] +---- +to: file needs the body as text, bytes, a stream or a file, but the body here is parsed data (a Map or a List), not +text - unmarshal: json turns the text into data: add marshal: json before this step +---- + +With a `marshal` before it, the body is JSON text again, which the `file` producer writes: + +[source,yaml] +---- +- route: + from: + uri: file:inbox + steps: + - unmarshal: + json: {} + - marshal: + json: {} + - to: + uri: file:outbox +---- + +=== Options change the body + +The body after a step can depend on its options. The `xslt` producer leaves the result as text, unless its `output` +option says otherwise: + +[source,json] +---- +"producerOut": { + "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultHandlerFactory" ], + "byOption": [ + { "option": "output", "value": "bytes", "carriers": [ "bytes" ], "javaType": "byte[]" }, + { "option": "output", "value": "DOM", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document" }, + { "option": "output", "value": "file", "carriers": [ "file" ], "javaType": "java.io.File" } ], + "description": "The result of the transformation" } +---- + +With `output=bytes` the body is a `byte[]`. With a `resultHandlerFactory` the factory decides the body, which the +catalog cannot know, so it is not known. + +=== An option that names the class of the body + +Some options name the class the result is converted to: the `resultType` of a language, the `unmarshalType` of a JSON +data format, the `type` of `convertBodyTo`, or the `outputClass` of `sql` for one row. When such an option is set, the +body is an object of that class, or null: + +[source,yaml] +---- +- route: + from: + uri: direct:order + steps: + - setBody: + simple: + expression: "${header.quantity}" + resultType: java.lang.Integer + - to: + uri: sql:select * from orders where id = :#id + parameters: + outputType: SelectOne + outputClass: com.acme.Order +---- + +`setBody` leaves the result of its expression, and with `resultType` that is an `Integer`, a `value`. The `sql` +producer leaves a `List` of rows by default, and with `outputType=SelectOne` and `outputClass` one `com.acme.Order`, +or null when there is no row. + +=== EIPs + +The body after an EIP is often the body of something else: `marshal` leaves what its data format writes, `to` what +the producer of its endpoint leaves, and `setBody` the result of its expression. The catalog says so with `from`, +instead of copying the body types of every data format, component and language: + +[source,json] +---- +"eipOut": { "from": "marshalOut", "dependsOn": [ "variableReceive" ], + "description": "What the data format writes. With variableReceive the result goes into the variable, and the body stays as it was" } +---- + +An EIP with steps of its own also says what they start with. The steps of a `split` start with each part, and after +it the body is as it was before the split: + +[source,json] +---- +"eipOut": { "carriers": [ "unchanged" ], "dependsOn": [ "aggregationStrategy" ], + "description": "The body as it was before the split, unless an aggregationStrategy is set" }, +"eipSteps": { "carriers": [ "unknown" ], + "description": "Each part of what the expression gives, such as an element of a List or a line of text" } +---- + +== Tooling + +=== Documentation + +The page of each component, data format, language and EIP has a _Message Body_ section with a row per side, which +is generated from the catalog. + +=== Camel CLI and its MCP server + +`camel catalog doc` prints the same table for a component, data format, language or EIP, such as +`camel catalog doc xslt` or `camel catalog doc eip:split`. The `camel_catalog_doc` tool of the +xref:camel-jbang-mcp.adoc[MCP server] gives each side as a line of text, so an AI assistant reads them with the +options: + +[source,text] +---- +text (java.lang.String). The result of the transformation. With output=bytes: bytes (byte[]); output=DOM: pojo +(org.w3c.dom.Document); output=file: file (java.io.File). Not known when resultHandlerFactory is set +---- + +=== YAML validator + +`camel validate source` follows the body through the steps of each route with the body types, and reports a step +that cannot take the body it gets (see xref:camel-jbang-validation.adoc[Validation]). Where the catalog does not +know the body, such as after an HTTP consumer, it says nothing, unless a running integration has shown what the body +is. + +=== At runtime + +With the message history on, such as with `camel run --dev`, Camel records the types and kinds of the bodies each +step has been reached with: + +* xref:components:eips:message-history.adoc[Message History] explains the kinds, the `BodyTypeRegistry`, the + `body-type` dev console and the JMX attributes. +* `camel cmd route-structure` shows them per step (see xref:camel-jbang-diagnostics.adoc[Diagnostics]), as do the + xref:camel-jbang-tui-diagram.adoc#_body_types[diagram] and the + xref:camel-jbang-tui-source-editor.adoc#_body_types[source editor] of the Camel CLI. +* The route coverage report of the xref:camel-report-maven-plugin.adoc[Camel Report Maven Plugin] shows the body types + the tests reached each step with, and can fail the build on a step reached with bodies of more than one kind. + +== Declaring body types + +A component declares its body types with the `@BodyTypes` annotation on its endpoint class, a data format and a +language on their class, and an EIP on its model class in `camel-core-model`. That is also where the EIPs that other +modules implement are declared, such as `circuitBreaker`. A subclass does not have the body types of its superclass, +as it may change the body: + +[source,java] +---- +@BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, description = "The file as read ..."), + producerIn = @BodyType({ Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), + producerOut = @BodyType(Carrier.UNCHANGED)) +@UriEndpoint(firstVersion = "1.0.0", scheme = "file", ...) +public class FileEndpoint extends GenericFileEndpoint<File> { +---- + +The values come from the code that sets the body. The build checks that: + +* each side belongs to the kind of model; a consumer-only component has no producer sides; +* the options a side names exist, and a value of an option is one the option can have; +* `unchanged` and `unknown` are only on the body after a step, and `any` only on what a step needs; +* `from` names a side the body can come from, and a side with `from` has no carriers of its own; +* a `javaTypeOption` is an option of the body after a step that the side does not also depend on. + +The runtime body types the message history records are checked against them in tests, such as for the EIPs of core. + +== Reference: the JSON of the body types + +This section is for the tools, and the AI assistants, that read the catalog. + +The JSON of a component, data format, language or EIP in the catalog has a `bodyTypes` object next to its options, with +an object per side. Each side has these fields; a field that does not apply is left out: + +[width="100%",cols="1,1,4",options="header"] +|=== +| Field | Type | Meaning +| `carriers` | array of strings | The carriers of the body: one, or several when the body can be any of them. Left out +for a side with `from`. +| `javaType` | string | The Java type of the body, when it is always of this type. +| `format` | string | The format of the payload, when it is always the same: `json`, `xml`, `csv`, `yaml`, `text` or +`binary`. +| `dependsOn` | array of strings | The options the body depends on. The side holds while they keep their default values. +When the step sets one, only a `byOption` entry for that value says the body; without one it is not known. +| `byOption` | array of objects | The body for a value of an option: `option`, `value`, `carriers`, and optionally +`javaType` and `javaTypeOption`. +| `javaTypeOption` | string | The option that names the class of the body, such as `resultType`. When the step sets +it, the body is an object of that class, or null. +| `from` | string | For an EIP, the side of another model the body is: `expressionIn`, `expressionOut` (the language +of its expression), `marshalIn`, `marshalOut`, `unmarshalIn`, `unmarshalOut` (its data format), `producerIn`, +`producerOut` (its endpoint as a producer), `consumerOut` (its endpoint as a consumer), or `steps` (what its own +steps end with). +| `description` | string | What to know about the body, in a sentence. +|=== + +=== Reading a side for a step + +To know the body a step leaves, or the bodies it needs, read its side with the options the step sets, in this order: + +. *No side:* not known. +. *A side with `from`:* when the step sets an option of `dependsOn`, not known. Otherwise, read the side `from` names on +the model the step uses (the language of its expression, its data format or its endpoint), with the options of that +model. `steps` is the body the steps of the EIP end with. +. *An option the side names whose value is not known before the route runs* (a `+{{placeholder}}+` or a `+${expression}+`), +or an option the step does not set but that can be set elsewhere, such as on the component: not known. +. *An option of `dependsOn` the step sets:* the `byOption` entry for that value says the body. When it has a +`javaTypeOption` the step sets, the body is an object of that class. Without such an entry: not known. +. *The `javaTypeOption` of the side, when the step sets it:* an object of the class it names, or null. It wins over the +`byOption` entries of other options. +. *The `byOption` entries for the values the step sets:* their carriers (or the class of their `javaTypeOption`). When +two of them say different bodies: not known. +. *Otherwise:* the carriers of the side. `unknown` is not known, and `unchanged` is the body before the step. + +The values of an option compare in any case, and in any style of an enum constant, as Camel takes them: +`convert-to-json`, `convertToJson` and `CONVERT_TO_JSON` are one value. + +The carrier of a class that a `javaTypeOption` names follows the class: `String` is `text`, `byte[]` is `bytes`, an +`InputStream` or a `Reader` is `stream`, a `File` or a `Path` is `file`, a number, a boolean or a character is +`value`, a `Map` is `map`, a `Collection` or an array is `list`, an `Iterator` is `iterator`, `Object` is `unknown`, and +any other class is `pojo`. The short names Camel takes, such as `String` and `int`, count too. + +=== Java API + +The models of `camel-catalog` have the body types, and `BodyTypeResolver` of `camel-tooling-model` reads a side for the +options of a step, by the rule above. The YAML validator uses it: + +[source,java] +---- +CamelCatalog catalog = new DefaultCamelCatalog(); + +BodyTypeModel out = catalog.componentModel("xslt").getBodyType(BodyTypeModel.PRODUCER_OUT); +out.getCarriers(); // [text] +out.getJavaType(); // java.lang.String + +BodyTypeResolver.Resolved bytes = BodyTypeResolver.resolve(out, Map.of("output", "bytes"), Set.of()); +bytes.carriers(); // [bytes] + +BodyTypeModel.carrierOf("java.util.Map"); // map +---- diff --git a/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc b/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc index 2e7cc5513d6b..864526f0844e 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc @@ -129,86 +129,20 @@ question people, IDEs and AI agents ask most when they write the next step of a file it read, the `http` producer leaves the response as a byte array or a stream, and after `unmarshal: json` the body is a `Map` or a `List`. -A component, data format, language or EIP can declare its body types, and the catalog then has a `bodyTypes` section -with one entry per side: - -[width="100%",cols="25%,75%",options="header",] -|=== -|Side |The body -|`consumerOut` |The body of the message the consumer creates. -|`consumerReply` |The bodies a consumer that answers the caller can reply with: the body the route ends with. -|`producerIn` |The bodies the producer can send or write. -|`producerOut` |The body after the producer. -|`marshalIn`, `marshalOut` |The bodies a data format can marshal, and the body after marshal. -|`unmarshalIn`, `unmarshalOut` |The bodies a data format can unmarshal, and the body after unmarshal. -|`expressionIn`, `expressionOut` |The bodies the expressions of a language can read, and their result. -|`eipIn` |The bodies an EIP needs, such as text for `tokenizer`. -|`eipOut` |The body after an EIP. -|`eipSteps` |The body the steps of an EIP start with, such as each part for `split`. -|=== - -Each side has the _carriers_ of the body, the kinds of Java object it is in: `null`, `text`, `bytes`, `stream`, -`file`, `value`, `map`, `list`, `iterator` (read once, with no size and no index) and `pojo`; `unchanged` for a step -that leaves the body as it was, `any` for a step that takes any body, and `unknown` for a body that depends on what -the other system sends or on a class the user configures. A side can also have the Java type when the body is always of that type, the format of the payload (json, -xml, csv, yaml, text or binary), the options the body depends on, the body for other values of an option, and a -description: +A component, data format, language or EIP that declares its body types has a `bodyTypes` section in the catalog, with +an entry per side: what a consumer gives, what a producer needs and leaves, what a data format marshals and unmarshals +to, what an expression reads and gives, and what an EIP needs, leaves and starts its own steps with: [source,json] ---- "bodyTypes": { - "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], - "description": "The XML to transform: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source. ..." }, - "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultHandlerFactory" ], - "byOption": [ { "option": "output", "value": "bytes", "carriers": [ "bytes" ], "javaType": "byte[]" }, ... ], - "description": "The result of the transformation" } + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], + "description": "What converts to an InputStream: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } } ---- -An EIP whose body is the body of another model says which side of it with `from`, instead of carriers of its own: -`marshal` leaves what its data format leaves (`marshalOut`), `to` what the producer of its endpoint leaves -(`producerOut`), `pollEnrich` what the consumer of its endpoint receives (`consumerOut`), `setBody` the result of its -expression (`expressionOut`), and a `filter` what its own steps end with (`steps`): - -[source,json] ----- -"bodyTypes": { - "eipOut": { "from": "steps", "description": "What its steps end with; the body as it was when the predicate does not match" }, - "eipSteps": { "carriers": [ "unchanged" ] } -} ----- - -An option that names the class of the body is the `javaTypeOption` of a side, such as the `resultType` of a language, -whose result is converted to that class, the `unmarshalType` of a JSON data format, and the `type` of `convertBodyTo`. -When the option is set, the body is an object of the class it names, or null when it does not convert. That holds while -the options the side depends on keep their defaults (an option that makes the body a collection of that class, such -as `useList` of `jackson`, is one of them), and it wins over the bodies `byOption` gives for other options. The -carrier follows the class: `String` is `text`, `byte[]` is `bytes`, an `InputStream` or a `Reader` is a `stream`, a -`File` or a `Path` is a `file`, a number, a boolean or a character is a `value`, a `Map` is a `map`, a `Collection` or -an array is a `list`, an `Iterator` is an `iterator`, `Object` is `unknown`, and any other class is a `pojo`. -`BodyTypeModel.carrierOf` gives it for a class name, also for the short names Camel takes, such as `String` and `int`: - -[source,json] ----- -"bodyTypes": { - "expressionOut": { "carriers": [ "unknown" ], "javaTypeOption": "resultType", - "description": "A text with functions gives text. A single function, such as ${body} or ${header.foo}, gives its value as it is" } -} ----- - -A body for an option value can have a `javaTypeOption` too, when the option names the class of the body only for that -value: the `outputClass` of `sql` is the class of the one row with `outputType=SelectOne`, and of each row in the List -otherwise: - -[source,json] ----- -"producerOut": { "carriers": [ "list", "unchanged" ], "dependsOn": [ "outputHeader", "noop" ], - "byOption": [ { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value", "null" ], "javaTypeOption": "outputClass" }, ... ] } ----- - -The sides say what the body is with the default options. A side that is not in the catalog is not known, and tooling -should not guess it. The documentation page of a component, data format, language or EIP shows them in its _Message -Body_ section, and `camel catalog doc` prints them. The Java API gives them on the model: +The Java API gives them on the model: [source,java] ---- @@ -219,30 +153,8 @@ out.getCarriers(); // [text] out.getJavaType(); // java.lang.String ---- -Component developers declare them with the `@BodyTypes` annotation on the endpoint, data format or language class, and -the EIPs on their model class in `camel-core-model`, also when the EIP is implemented in another module, such as -`circuitBreaker`. A subclass does not have the body types of its superclass, as it may change the body: - -[source,java] ----- -@BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, description = "The file as read ..."), - producerIn = @BodyType({ Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), - producerOut = @BodyType(Carrier.UNCHANGED)) -@UriEndpoint(firstVersion = "1.0.0", scheme = "file", ...) -public class FileEndpoint extends GenericFileEndpoint<File> { ----- - -The build checks that each side belongs to the kind (a consumer-only component has no producer sides), that the -options a side names exist, that a value of an option is one the option can have (such as `chat-completion` for the -`operation` of openai), that `unchanged` is only on the body after a step and `any` only on what a step needs, -that `from` names a side the body can come from, and that a `javaTypeOption` is an option of the body after a step -that the side does not also depend on. -The values are read from the code that sets the body, and checked against the body types the message history records -when the routes run. - -The YAML validator of the Camel CLI follows the body through the steps of a route with the body types, and reports a -step that cannot work on it, such as a Map that a `to: file` cannot write (see -xref:camel-jbang-validation.adoc#_what_a_running_integration_saw[Camel CLI validation]). +See xref:body-types.adoc[Message Body Types] for what the body types are, the tools that use them, how components +declare them, and the JSON of each side with the rule to read it for the options of a step. === Documentation in the Catalog diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc index 305f64e8ccd0..15dae476ac2a 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc @@ -318,7 +318,7 @@ project `directory` as an argument, the runtime tools take the integration `name its group of `application.properties` keys, the key first. A component, data format or language that declares its body types has them in `bodyTypes`, a line per side: what a `from:` gives the route (`consumerOut`), what a `to:` can send (`producerIn`) and the body after it (`producerOut`), and so on (see - xref:camel-catalog.adoc#_body_types_in_the_catalog[Body types in the Catalog]). An answer is cut at 18 000 + xref:body-types.adoc[Message Body Types]). An answer is cut at 18 000 characters, with a marker that says what was left out. `includeOptions` picks the options listed: `common` (the default) leaves out the deprecated and advanced ones and says how many with `omittedOptions`, `required` lists the required ones, `all` everything, `false` diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc index 54c39089b805..709da62cf506 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc @@ -76,7 +76,7 @@ A part of a Java route the parser cannot work out (a value computed at runtime) The YAML validator follows the message body through the steps of each route, and reports a step that cannot work on it: a field read such as `+${body.qty}+` on text that was never unmarshalled, or a Map that a `to: file` cannot write. What a component or a data format does with the body comes from the -xref:camel-catalog.adoc#_body_types_in_the_catalog[body types in the catalog]: the file consumer gives the file it +xref:body-types.adoc[body types in the catalog]: the file consumer gives the file it read, the `http` producer leaves the response as bytes or a stream, and `unmarshal: json` makes a Map or a List. The answer of `openai:chat-completion` is text, also when it is asked for JSON with `jsonSchema`, so a field read on it needs `unmarshal: json` first. Where they do not tell what the body is, the validator says nothing: after a `platform-http` consumer the body diff --git a/docs/user-manual/modules/ROOT/pages/endpoint-annotations.adoc b/docs/user-manual/modules/ROOT/pages/endpoint-annotations.adoc index aa9b755a18b8..6bee27e2e912 100644 --- a/docs/user-manual/modules/ROOT/pages/endpoint-annotations.adoc +++ b/docs/user-manual/modules/ROOT/pages/endpoint-annotations.adoc @@ -33,8 +33,8 @@ annotated with one or more `@UriParam` or `@UriParams` annotations |`@Metadata` | Used for special situations to provide additional information. |`@BodyTypes` | The message body the endpoint works with: the body the consumer creates, the bodies the -producer can send, and the body after the producer. See xref:camel-catalog.adoc#_body_types_in_the_catalog[Body types -in the Catalog]. +producer can send, and the body after the producer. See xref:body-types.adoc[Message +Body Types]. |======================================================================= For example see the `TimerEndpoint` from the `camel-timer` component and
