This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 8793871fda1eed1b35709dfacbff684d798ee02e
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Oct 24 19:57:01 2026 +0200

    CAMEL-24961: Catalog body types for sjms, sjms2, rocketmq, hivemq, iggy, 
kafka-share, xmpp, pubnub, disruptor, vertx and two more (#28394)
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../camel/catalog/components/disruptor-vm.json     |  5 +++
 .../apache/camel/catalog/components/disruptor.json |  5 +++
 .../apache/camel/catalog/components/hivemq.json    |  5 +++
 .../org/apache/camel/catalog/components/iggy.json  |  5 +++
 .../camel/catalog/components/kafka-share.json      |  3 ++
 .../apache/camel/catalog/components/pubnub.json    |  5 +++
 .../camel/catalog/components/reactive-streams.json |  6 +++
 .../apache/camel/catalog/components/rocketmq.json  |  5 +++
 .../org/apache/camel/catalog/components/sjms.json  |  6 +++
 .../org/apache/camel/catalog/components/sjms2.json |  6 +++
 .../org/apache/camel/catalog/components/vertx.json |  6 +++
 .../org/apache/camel/catalog/components/xmpp.json  |  5 +++
 .../apache/camel/catalog/docs/sjms-component.adoc  | 22 ++++++++--
 .../apache/camel/catalog/docs/sjms2-component.adoc | 22 ++++++++--
 .../apache/camel/catalog/docs/vertx-component.adoc | 10 ++++-
 .../camel/component/disruptor/disruptor-vm.json    |  5 +++
 .../camel/component/disruptor/disruptor.json       |  5 +++
 .../component/disruptor/DisruptorEndpoint.java     | 12 ++++++
 .../org/apache/camel/component/hivemq/hivemq.json  |  5 +++
 .../camel/component/hivemq/HiveMQEndpoint.java     | 12 ++++++
 .../org/apache/camel/component/iggy/iggy.json      |  5 +++
 .../apache/camel/component/iggy/IggyEndpoint.java  | 13 ++++++
 .../camel/component/kafka/share/kafka-share.json   |  3 ++
 .../component/kafka/share/KafkaShareEndpoint.java  | 10 +++++
 .../org/apache/camel/component/pubnub/pubnub.json  |  5 +++
 .../camel/component/pubnub/PubNubEndpoint.java     | 38 +++++++++++++++++
 .../reactive/streams/reactive-streams.json         |  6 +++
 .../reactive/streams/ReactiveStreamsEndpoint.java  | 15 +++++++
 .../apache/camel/component/rocketmq/rocketmq.json  |  5 +++
 .../camel/component/rocketmq/RocketMQEndpoint.java | 14 +++++++
 .../org/apache/camel/component/sjms/sjms.json      |  6 +++
 .../camel-sjms/src/main/docs/sjms-component.adoc   | 22 ++++++++--
 .../apache/camel/component/sjms/SjmsEndpoint.java  | 48 ++++++++++++++++++++++
 .../org/apache/camel/component/sjms2/sjms2.json    |  6 +++
 .../camel-sjms2/src/main/docs/sjms2-component.adoc | 22 ++++++++--
 .../camel/component/sjms2/Sjms2Endpoint.java       | 48 ++++++++++++++++++++++
 .../org/apache/camel/component/vertx/vertx.json    |  6 +++
 .../camel-vertx/src/main/docs/vertx-component.adoc | 10 ++++-
 .../camel/component/vertx/VertxEndpoint.java       | 27 ++++++++++++
 .../org/apache/camel/component/xmpp/xmpp.json      |  5 +++
 .../apache/camel/component/xmpp/XmppEndpoint.java  | 19 +++++++++
 41 files changed, 470 insertions(+), 18 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/disruptor-vm.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/disruptor-vm.json
index 45e142d7b31f..2e92d4bb4844 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/disruptor-vm.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/disruptor-vm.json
@@ -36,6 +36,11 @@
     "lazyStartProducer": { "index": 7, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Whether the producer should be started lazy (on the first message). By 
starting lazy you can use this to allow CamelContext and routes to startup in 
situations where a producer may otherwise fail [...]
     "autowiredEnabled": { "index": 8, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the 
producer sent" },
+    "producerIn": { "carriers": [ "any" ] },
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"waitForTaskToComplete", "value": "Never", "carriers": [ "unchanged" ] } ], 
"description": "Unchanged for a message that expects no reply (InOnly). A 
message that expects one (InOut), or waitForTaskToComplete=Always, waits for 
the body the disruptor route ends with; with more than one consumer route 
(multipleConsumers) the body stays unchanged" }
+  },
   "properties": {
     "name": { "index": 0, "kind": "path", "displayName": "Name", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Name of queue" },
     "size": { "index": 1, "kind": "parameter", "displayName": "Size", "group": 
"common", "label": "", "required": false, "type": "integer", "javaType": "int", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 1024, 
"description": "The maximum capacity of the Disruptors ringbuffer Will be 
effectively increased to the nearest power of two. Notice: Mind if you use this 
option, then it's the first endpoint being created with the queue name that 
determines the size. To [...]
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/disruptor.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/disruptor.json
index 0a7a8eb9d1b1..9aded081b87b 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/disruptor.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/disruptor.json
@@ -36,6 +36,11 @@
     "lazyStartProducer": { "index": 7, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Whether the producer should be started lazy (on the first message). By 
starting lazy you can use this to allow CamelContext and routes to startup in 
situations where a producer may otherwise fail [...]
     "autowiredEnabled": { "index": 8, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the 
producer sent" },
+    "producerIn": { "carriers": [ "any" ] },
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"waitForTaskToComplete", "value": "Never", "carriers": [ "unchanged" ] } ], 
"description": "Unchanged for a message that expects no reply (InOnly). A 
message that expects one (InOut), or waitForTaskToComplete=Always, waits for 
the body the disruptor route ends with; with more than one consumer route 
(multipleConsumers) the body stays unchanged" }
+  },
   "properties": {
     "name": { "index": 0, "kind": "path", "displayName": "Name", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Name of queue" },
     "size": { "index": 1, "kind": "parameter", "displayName": "Size", "group": 
"common", "label": "", "required": false, "type": "integer", "javaType": "int", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 1024, 
"description": "The maximum capacity of the Disruptors ringbuffer Will be 
effectively increased to the nearest power of two. Notice: Mind if you use this 
option, then it's the first endpoint being created with the queue name that 
determines the size. To [...]
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/hivemq.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/hivemq.json
index 5949527c4f7b..c7984eddd189 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/hivemq.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/hivemq.json
@@ -45,6 +45,11 @@
     "CamelHiveMQRetained": { "index": 2, "kind": "header", "displayName": "", 
"group": "common", "label": "", "required": false, "javaType": "Boolean", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Whether the message should be retained.", 
"constantName": 
"org.apache.camel.component.hivemq.HiveMQConstants#MQTT_RETAINED" },
     "CamelHiveMQOverrideTopic": { "index": 3, "kind": "header", "displayName": 
"", "group": "common", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Header to dynamically override the target topic for 
publishing.", "constantName": 
"org.apache.camel.component.hivemq.HiveMQConstants#OVERRIDE_TOPIC" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", 
"description": "The payload of the MQTT message, an empty byte array for an 
empty payload. The topic is in the CamelHiveMQTopic header" },
+    "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "null" ], 
"description": "What converts to a byte array: text, bytes, a stream or a file, 
sent as the payload; no body is sent as an empty payload. A Map, a POJO or a 
number does not convert and is sent as an empty payload too, without an error: 
marshal it first" },
+    "producerOut": { "carriers": [ "unchanged" ] }
+  },
   "properties": {
     "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The MQTT topic name or pattern to 
subscribe to or publish on." },
     "cleanStart": { "index": 1, "kind": "parameter", "displayName": "Clean 
Start", "group": "common", "label": "", "required": false, "type": "boolean", 
"javaType": "boolean", "deprecated": false, "autowired": false, "secret": 
false, "defaultValue": true, "configurationClass": 
"org.apache.camel.component.hivemq.HiveMQConfiguration", "configurationField": 
"configuration", "description": "Whether to initiate a clean session upon 
connecting to the broker (called clean session in MQTT 3.1.1  [...]
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/iggy.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/iggy.json
index b386cbb2a524..633921d7a8ce 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/iggy.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/iggy.json
@@ -56,6 +56,11 @@
     "useGlobalSslContextParameters": { "index": 29, "kind": "property", 
"displayName": "Use Global Ssl Context Parameters", "group": "security", 
"label": "security", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Enable usage of global SSL context 
parameters." },
     "username": { "index": 30, "kind": "property", "displayName": "Username", 
"group": "security", "label": "security", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": true, "security": "secret", "configurationClass": 
"org.apache.camel.component.iggy.IggyConfiguration", "configurationField": 
"configuration", "description": "Iggy username" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", 
"description": "The payload of the Iggy message, decoded as text with the 
default charset of the JVM: a binary payload does not survive" },
+    "producerIn": { "carriers": [ "any" ], "description": "The body is 
converted to text and sent as one message, so bytes are decoded as text (a 
binary payload is corrupted) and a Map or a POJO is sent as its toString(): 
marshal it first. A List of String or of Iggy Message is sent as one message 
per element, and an Iggy Message as it is. No body or an empty List fails" },
+    "producerOut": { "carriers": [ "unchanged" ] }
+  },
   "properties": {
     "topicName": { "index": 0, "kind": "path", "displayName": "Topic Name", 
"group": "common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Name of the topic" },
     "autoCreateStream": { "index": 1, "kind": "parameter", "displayName": 
"Auto Create Stream", "group": "common", "label": "", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": true, "configurationClass": 
"org.apache.camel.component.iggy.IggyConfiguration", "configurationField": 
"configuration", "description": "Whether to automatically create stream if it 
does not exist" },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kafka-share.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kafka-share.json
index bda5110b0b41..b3b29cceedcb 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kafka-share.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kafka-share.json
@@ -114,6 +114,9 @@
     "CamelKafkaShareDeliveryCount": { "index": 6, "kind": "header", 
"displayName": "", "group": "consumer", "label": "", "required": false, 
"javaType": "Short", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "important": true, "description": "How many times the 
record has been delivered, this delivery included. The header is not set when 
the broker does not count the deliveries.", "constantName": 
"org.apache.camel.component.kafka.share.KafkaShareConstant [...]
     "CamelKafkaShareAcknowledge": { "index": 7, "kind": "header", 
"displayName": "", "group": "consumer", "label": "", "required": false, 
"javaType": "String", "enum": [ "ACCEPT", "RELEASE", "REJECT" ], "deprecated": 
false, "deprecationNote": "", "autowired": false, "secret": false, 
"description": "How to acknowledge the record (ACCEPT, RELEASE or REJECT), 
instead of deriving it from the outcome of the exchange. Set it in the route, 
for example to REJECT a record that was delivered too m [...]
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "text", "null" ], "dependsOn": [ 
"valueDeserializer" ], "byOption": [ { "option": "valueDeserializer", "value": 
"org.apache.kafka.common.serialization.ByteArrayDeserializer", "carriers": [ 
"bytes", "null" ], "javaType": "byte[]" } ], "description": "The value of the 
record: a String with the default valueDeserializer (StringDeserializer), null 
for a tombstone. The key of the record, when it has one, is in the 
CamelKafkaKey header" }
+  },
   "properties": {
     "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": 
"common", "label": "common", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.kafka.share.KafkaShareConfiguration", 
"configurationField": "configuration", "description": "Name of the topic to 
consume from. Use comma to separate multiple topics. Topic patterns are no [...]
     "additionalProperties": { "index": 1, "kind": "parameter", "displayName": 
"Additional Properties", "group": "common", "label": "common", "required": 
false, "type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.Object>", "prefix": "additionalProperties.", "multiValue": true, 
"deprecated": false, "autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.kafka.share.KafkaShareConfiguration", 
"configurationField": "configuration", "descript [...]
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pubnub.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pubnub.json
index dd9a6e85c213..e4d1181ad220 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pubnub.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pubnub.json
@@ -44,6 +44,11 @@
     "CamelPubNubOverrideChannel": { "index": 3, "kind": "header", 
"displayName": "", "group": "producer", "label": "producer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The channel to use instead of the 
channel configured on the endpoint.", "constantName": 
"org.apache.camel.component.pubnub.PubNubConstants#OVERRIDE_CHANNEL" },
     "CamelPubNubUUID": { "index": 4, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "UUID to be used as a device identifier.", 
"constantName": "org.apache.camel.component.pubnub.PubNubConstants#UUID" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "pojo" ], "javaType": 
"com.pubnub.api.models.consumer.pubsub.PNMessageResult", "byOption": [ { 
"option": "withPresence", "value": "true", "carriers": [ "pojo" ] } ], 
"description": "The PubNub PNMessageResult; its getMessage() is the payload as 
a Gson JsonElement, and it does not convert to the payload text. With 
withPresence, a presence event comes as a PNPresenceEventResult. The channel 
and timetoken are in the CamelPubNubChannel and CamelPubNubTimeTo [...]
+    "producerIn": { "carriers": [ "text", "value", "map", "list", "pojo" ], 
"byOption": [ { "option": "operation", "value": "SETSTATE", "carriers": [ 
"map", "pojo" ] }, { "option": "operation", "value": "GETHISTORY", "carriers": 
[ "any" ] }, { "option": "operation", "value": "GETSTATE", "carriers": [ "any" 
] }, { "option": "operation", "value": "HERENOW", "carriers": [ "any" ] } ], 
"description": "The message to publish or fire, serialized to JSON by the 
PubNub client: text is sent as a  [...]
+    "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": 
"operation", "value": "GETHISTORY", "carriers": [ "list", "unchanged" ] }, { 
"option": "operation", "value": "GETSTATE", "carriers": [ "pojo" ], "javaType": 
"com.pubnub.api.models.consumer.presence.PNGetStateResult" }, { "option": 
"operation", "value": "HERENOW", "carriers": [ "pojo" ], "javaType": 
"com.pubnub.api.models.consumer.presence.PNHereNowResult" }, { "option": 
"operation", "value": "SETSTATE", "carriers [...]
+  },
   "properties": {
     "channel": { "index": 0, "kind": "path", "displayName": "Channel", 
"group": "common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.pubnub.PubNubConfiguration", "configurationField": 
"configuration", "description": "The channel used for subscribing\/publishing 
events" },
     "uuid": { "index": 1, "kind": "parameter", "displayName": "Uuid", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.pubnub.PubNubConfiguration", "configurationField": 
"configuration", "description": "UUID to be used as a device identifier, a 
default UUID is generated if not passed." },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/reactive-streams.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/reactive-streams.json
index 6b6717714773..cf604936c855 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/reactive-streams.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/reactive-streams.json
@@ -38,6 +38,12 @@
     "CamelReactiveStreamsEventType": { "index": 0, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Every exchange consumed by Camel has 
this header set to indicate if the exchange contains an item (value=onNext), an 
error (value=onError) or a completion event (value=onComplete). Errors and 
completion notification are not  [...]
     "CamelReactiveStreamsCallback": { "index": 1, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "org.apache.camel.component.reactive.streams.api.DispatchCallback", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The callback.", "constantName": 
"org.apache.camel.component.reactive.streams.ReactiveStreamsConstants#REACTIVE_STREAMS_CALLBACK"
 }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "unknown" ], "description": "The item the 
publisher emits, as it is (an Exchange it emits is routed as it is). With 
forwardOnComplete, the end of the stream comes as an exchange without a body; 
with forwardOnError, the error as a Throwable body. The 
CamelReactiveStreamsEventType header says which" },
+    "consumerReply": { "carriers": [ "any" ], "description": "A caller of 
toStream or to() gets the exchange the route ends with, or its body converted 
to the type it asks for" },
+    "producerIn": { "carriers": [ "any" ], "description": "The exchange is 
handed to the subscribers of the stream as it is; a subscriber that asks for a 
type gets the body converted to it" },
+    "producerOut": { "carriers": [ "unchanged" ] }
+  },
   "properties": {
     "stream": { "index": 0, "kind": "path", "displayName": "Stream", "group": 
"common", "label": "", "required": false, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"description": "Name of the stream channel used by the endpoint to exchange 
messages." },
     "concurrentConsumers": { "index": 1, "kind": "parameter", "displayName": 
"Concurrent Consumers", "group": "consumer", "label": "consumer", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 1, "description": "Number of threads 
used to process exchanges in the Camel route." },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rocketmq.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rocketmq.json
index 2f2db0763137..746bbd41a7b6 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rocketmq.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rocketmq.json
@@ -67,6 +67,11 @@
     "CamelRockerMQReconsumeTimes": { "index": 18, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Reconsume times", "constantName": 
"org.apache.camel.component.rocketmq.RocketMQConstants#RECONSUME_TIMES" },
     "CamelRockerMQPreparedTransactionOffset": { "index": 19, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Prepard transaction offset", 
"constantName": 
"org.apache.camel.component.rocketmq.RocketMQConstants#PREPARED_TRANSACTION_OFFSET"
 }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", 
"description": "The body of the RocketMQ message. The consumer does not reply: 
the body the route ends with is not sent back" },
+    "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], 
"description": "What converts to a byte array: text, bytes, a stream or a file, 
sent as the body of the message. A Map, a POJO, a number or no body fails, and 
the broker rejects an empty body: marshal it first" },
+    "producerOut": { "carriers": [ "unchanged" ], "dependsOn": [ 
"replyToTopic" ], "description": "The body is left as it was. With the InOut 
pattern and a replyToTopic, the producer waits for the reply and the body is 
the reply as a byte array" }
+  },
   "properties": {
     "topicName": { "index": 0, "kind": "path", "displayName": "Topic Name", 
"group": "common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Topic name of this endpoint." },
     "accessChannel": { "index": 1, "kind": "parameter", "displayName": "Access 
Channel", "group": "common", "label": "common", "required": false, "type": 
"enum", "javaType": "java.lang.String", "enum": [ "LOCAL", "CLOUD" ], 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 
"LOCAL", "description": "Access channel of RocketMQ cluster. LOCAL or CLOUD, 
LOCAL by default" },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms.json
index 48aa9f58d2d8..93bb9b0f8276 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms.json
@@ -47,6 +47,12 @@
     "JMSReplyTo": { "index": 3, "kind": "header", "displayName": "", "group": 
"producer", "label": "producer", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Provides an explicit ReplyTo destination (overrides any 
incoming value of Message.getJMSReplyTo() in consumer)", "constantName": 
"org.apache.camel.component.sjms.SjmsConstants#JMS_REPLY_TO" },
     "CamelSjmsBatchSize": { "index": 4, "kind": "header", "displayName": "", 
"group": "batch", "label": "consumer,batch", "required": false, "javaType": 
"int", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The size of the batch when using the batching 
consumer option.", "constantName": 
"org.apache.camel.component.sjms.SjmsConstants#SJMS_BATCH_SIZE_HEADER" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "text", "bytes", "map", "pojo", "null" ], 
"byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ 
"pojo" ], "javaType": "jakarta.jms.Message" }, { "option": 
"objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", 
"value", "list", "pojo", "null" ] } ], "description": "By the JMS message 
received: a String for a TextMessage, a byte array for a BytesMessage, a Map 
for a MapMessage, the jakarta.jms.StreamMessage its [...]
+    "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map", 
"null" ], "dependsOn": [ "jmsMessageType" ], "byOption": [ { "option": 
"objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", 
"stream", "file", "map", "value", "list", "pojo", "null" ] } ], "description": 
"The reply, sent as the producer sends a message. A reply that cannot be sent, 
such as a number or a List without objectMessageEnabled, is dropped and the 
caller times out" },
+    "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map", 
"null" ], "dependsOn": [ "jmsMessageType", "allowNullBody" ], "byOption": [ { 
"option": "objectMessageEnabled", "value": "true", "carriers": [ "text", 
"bytes", "stream", "file", "map", "value", "list", "pojo", "null" ] } ], 
"description": "Text is sent as a TextMessage; bytes, a stream or a file as a 
BytesMessage; a Map of simple values as a MapMessage; null as an empty Message. 
A number, a List or another Serial [...]
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { 
"option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], 
"description": "Unchanged for a message that expects no reply (InOnly). A 
message that expects one (InOut) gets the body of the reply, as the consumer 
gives it" }
+  },
   "properties": {
     "destinationType": { "index": 0, "kind": "path", "displayName": 
"Destination Type", "group": "common", "label": "", "required": false, "type": 
"enum", "javaType": "java.lang.String", "enum": [ "queue", "topic" ], 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 
"queue", "description": "The kind of destination to use" },
     "destinationName": { "index": 1, "kind": "path", "displayName": 
"Destination Name", "group": "common", "label": "", "required": true, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"DestinationName is a JMS queue or topic name. By default, the destinationName 
is interpreted as a queue name." },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms2.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms2.json
index 2d57158e40a8..5d9f44532261 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms2.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sjms2.json
@@ -47,6 +47,12 @@
     "JMSReplyTo": { "index": 3, "kind": "header", "displayName": "", "group": 
"producer", "label": "producer", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Provides an explicit ReplyTo destination (overrides any 
incoming value of Message.getJMSReplyTo() in consumer)", "constantName": 
"org.apache.camel.component.sjms.SjmsConstants#JMS_REPLY_TO" },
     "CamelSjmsBatchSize": { "index": 4, "kind": "header", "displayName": "", 
"group": "batch", "label": "consumer,batch", "required": false, "javaType": 
"int", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The size of the batch when using the batching 
consumer option.", "constantName": 
"org.apache.camel.component.sjms.SjmsConstants#SJMS_BATCH_SIZE_HEADER" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "text", "bytes", "map", "pojo", "null" ], 
"byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ 
"pojo" ], "javaType": "jakarta.jms.Message" }, { "option": 
"objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", 
"value", "list", "pojo", "null" ] } ], "description": "By the JMS message 
received: a String for a TextMessage, a byte array for a BytesMessage, a Map 
for a MapMessage, the jakarta.jms.StreamMessage its [...]
+    "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map", 
"null" ], "dependsOn": [ "jmsMessageType" ], "byOption": [ { "option": 
"objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", 
"stream", "file", "map", "value", "list", "pojo", "null" ] } ], "description": 
"The reply, sent as the producer sends a message. A reply that cannot be sent, 
such as a number or a List without objectMessageEnabled, is dropped and the 
caller times out" },
+    "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map", 
"null" ], "dependsOn": [ "jmsMessageType", "allowNullBody" ], "byOption": [ { 
"option": "objectMessageEnabled", "value": "true", "carriers": [ "text", 
"bytes", "stream", "file", "map", "value", "list", "pojo", "null" ] } ], 
"description": "Text is sent as a TextMessage; bytes, a stream or a file as a 
BytesMessage; a Map of simple values as a MapMessage; null as an empty Message. 
A number, a List or another Serial [...]
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { 
"option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], 
"description": "Unchanged for a message that expects no reply (InOnly). A 
message that expects one (InOut) gets the body of the reply, as the consumer 
gives it" }
+  },
   "properties": {
     "destinationType": { "index": 0, "kind": "path", "displayName": 
"Destination Type", "group": "common", "label": "", "required": false, "type": 
"enum", "javaType": "java.lang.String", "enum": [ "queue", "topic" ], 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 
"queue", "description": "The kind of destination to use" },
     "destinationName": { "index": 1, "kind": "path", "displayName": 
"Destination Name", "group": "common", "label": "", "required": true, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"DestinationName is a JMS queue or topic name. By default, the destinationName 
is interpreted as a queue name." },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/vertx.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/vertx.json
index 099f9afdb652..33549d87d679 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/vertx.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/vertx.json
@@ -34,6 +34,12 @@
     "autowiredEnabled": { "index": 7, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
     "vertxFactory": { "index": 8, "kind": "property", "displayName": "Vertx 
Factory", "group": "advanced", "label": "advanced", "required": false, "type": 
"object", "javaType": "io.vertx.core.VertxBuilder", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use a custom 
VertxFactory implementation" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "unknown" ], "description": "The body of 
the event bus message, as the sender sent it: a String, a byte array, a number 
or a boolean, a JsonObject or a JsonArray, or a Serializable object such as a 
HashMap. A Buffer becomes a stream with stream caching enabled" },
+    "consumerReply": { "carriers": [ "text", "bytes", "value", "map", "list", 
"pojo", "null" ], "description": "A message with a reply address is answered 
with the body the route ends with, as the producer sends it. A stream, such as 
a received Buffer the route did not change, or a POJO that is not Serializable 
sends no reply, and the requester times out" },
+    "producerIn": { "carriers": [ "text", "bytes", "value", "map", "list", 
"pojo" ], "description": "Sent as is, with the event bus codec of its type: a 
String, a byte array, a number or a boolean, a JsonObject, a JsonArray or a 
Buffer, or a Serializable object such as a HashMap. A stream, a POJO that is 
not Serializable (without a codec registered for it) or no body fails: convert 
it first" },
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] } ], 
"description": "Unchanged for a message that expects no reply (InOnly). A 
message that expects one (InOut) is sent as a request, also with pubSub, and 
gets the body of the reply" }
+  },
   "properties": {
     "address": { "index": 0, "kind": "path", "displayName": "Address", 
"group": "common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Sets the event bus address used to 
communicate" },
     "pubSub": { "index": 1, "kind": "parameter", "displayName": "Pub Sub", 
"group": "common", "label": "", "required": false, "type": "boolean", 
"javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": false, "description": "Whether to use 
publish\/subscribe instead of point to point when sending to a vertx endpoint." 
},
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xmpp.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xmpp.json
index 27ca8b6c40f8..4137ca97a77c 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xmpp.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xmpp.json
@@ -32,6 +32,11 @@
   "headers": {
     "CamelXmppDoc": { "index": 0, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"org.jivesoftware.smack.packet.Message", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
XMPP message", "constantName": 
"org.apache.camel.component.xmpp.XmppConstants#DOC_HEADER" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "text", "pojo" ], "byOption": [ { "option": 
"doc", "value": "true", "carriers": [ "pojo" ], "javaType": 
"org.jivesoftware.smack.packet.Message" } ], "description": "The text of the 
chat message; the Smack Message when it has no body text, such as a pubsub 
notification. With doc, the Smack Message. The subject, thread and sender are 
in the CamelXmpp* headers" },
+    "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "doc", 
"value": "true", "carriers": [ "pojo" ] }, { "option": "pubsub", "value": 
"true", "carriers": [ "pojo" ], "javaType": 
"org.jivesoftware.smackx.pubsub.packet.PubSub" } ], "description": "The body is 
converted to text and sent as the chat message (a Map or a POJO as its 
toString); the headers become message properties. Without a room, doc sends a 
Smack Stanza (or an array of them) and pubsub a Smack PubSub packet a [...]
+    "producerOut": { "carriers": [ "unchanged" ] }
+  },
   "properties": {
     "host": { "index": 0, "kind": "path", "displayName": "Host", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Hostname for the chat server" },
     "port": { "index": 1, "kind": "path", "displayName": "Port", "group": 
"common", "label": "", "required": false, "type": "integer", "javaType": "int", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 5222, 
"description": "Port number for the chat server" },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms-component.adoc
index ed0b6f9c9a2e..c779d4ded2d8 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms-component.adoc
@@ -288,14 +288,28 @@ which allows use of your own custom strategy for 
formatting keys.
 
 === Message Content
 
-To deliver content over the wire, we must ensure that the body of the
-message that is being delivered adheres to the JMS Message
-Specification. Therefore, all that are produced must either be
+The values of the headers sent as JMS properties must either be
 primitives or their counter-objects (such as `Integer`, `Long`, `Character`).
 The types, `String`, `CharSequence`, `Date`, `BigDecimal` and `BigInteger` are 
all
-converted to their `toString()` representation. All other types are
+converted to their `toString()` representation. All other header values are
 dropped.
 
+The body is mapped to and from a JMS message as follows (unless the option 
`jmsMessageType` forces a type):
+
+[width="100%",cols="1,1,2",options="header"]
+|===
+| Camel body | JMS message | Body when consumed
+| `String` or XML `Node` | `TextMessage` | `String`
+| `byte[]`, `InputStream`, `Reader`, `ByteBuffer`, `File`, `Path` or 
`StreamCache` | `BytesMessage` | `byte[]`
+| `Map` (of simple values) | `MapMessage` | `Map`
+| `null` | `Message` | `null`
+| Other `Serializable` object (such as a number or a `List`) | `ObjectMessage` 
(only with `objectMessageEnabled=true`, fails otherwise) | the object
+| Any other object | `Message` without a body (a WARN is logged) | `null`
+|===
+
+A received `StreamMessage` is not mapped: the body is the 
`jakarta.jms.StreamMessage` itself.
+With `mapJmsMessage=false` the body is always the received 
`jakarta.jms.Message`.
+
 === Clustering
 
 When using _InOut_ with SJMS in a clustered environment, you must either
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms2-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms2-component.adoc
index e54ff5fd4519..e24128751a3f 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms2-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/sjms2-component.adoc
@@ -292,14 +292,28 @@ which allows use of your own custom strategy for 
formatting keys.
 
 === Message Content
 
-To deliver content over the wire, we must ensure that the body of the
-message that is being delivered adheres to the JMS Message
-Specification. Therefore, all that are produced must either be
+The values of the headers sent as JMS properties must either be
 primitives or their counter-objects (such as `Integer`, `Long`, `Character`).
 The types, `String`, `CharSequence`, `Date`, `BigDecimal` and `BigInteger` are 
all
-converted to their `toString()` representation. All other types are
+converted to their `toString()` representation. All other header values are
 dropped.
 
+The body is mapped to and from a JMS message as follows (unless the option 
`jmsMessageType` forces a type):
+
+[width="100%",cols="1,1,2",options="header"]
+|===
+| Camel body | JMS message | Body when consumed
+| `String` or XML `Node` | `TextMessage` | `String`
+| `byte[]`, `InputStream`, `Reader`, `ByteBuffer`, `File`, `Path` or 
`StreamCache` | `BytesMessage` | `byte[]`
+| `Map` (of simple values) | `MapMessage` | `Map`
+| `null` | `Message` | `null`
+| Other `Serializable` object (such as a number or a `List`) | `ObjectMessage` 
(only with `objectMessageEnabled=true`, fails otherwise) | the object
+| Any other object | `Message` without a body (a WARN is logged) | `null`
+|===
+
+A received `StreamMessage` is not mapped: the body is the 
`jakarta.jms.StreamMessage` itself.
+With `mapJmsMessage=false` the body is always the received 
`jakarta.jms.Message`.
+
 === Clustering
 
 When using _InOut_ with SJMS2 in a clustered environment, you must either
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-component.adoc
index 931f2c7f10db..d097b8eb6a6b 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-component.adoc
@@ -16,7 +16,8 @@ The Vert.x component is for working with the 
http://vertx.io/[Vertx]
 https://vertx.io/docs/vertx-core/java/#event_bus[EventBus].
 
 The vertx https://vertx.io/docs/vertx-core/java/#event_bus[EventBus]
-sends and receives JSON events.
+sends and receives Java objects that it has a message codec for: a `String`, a 
byte array, a number or a boolean,
+a `JsonObject`, a `JsonArray`, a `Buffer`, or a `Serializable` object.
 
 Maven users will need to add the following dependency to their `pom.xml`
 for this component:
@@ -73,6 +74,10 @@ A message goes to one consumer, or to all consumers with 
`pubSub`:
             message: "Received order ${body}"
 ----
 
+The body is sent as is, without type conversion: a stream, or a POJO that is 
not `Serializable` and has no codec
+registered on the event bus, fails with `No message codec for type`, so 
convert it to a `String` or a byte array
+first. A message without a body fails as well.
+
 When the exchange is InOut, the producer sends a request and the reply of the 
consumer becomes the message body:
 
 [source,yaml]
@@ -96,6 +101,9 @@ When the exchange is InOut, the producer sends a request and 
the reply of the co
                 expression: "Hello ${body}"
 ----
 
+The consumer replies with the body the route ends with, which needs a codec 
too. A `Buffer` the consumer receives is
+a stream when stream caching is enabled (the default), so convert a stream 
body before the route ends.
+
 == Connecting to the existing Vert.x instance
 
 If you would like to connect to the Vert.x instance already existing in
diff --git 
a/components/camel-disruptor/src/generated/resources/META-INF/org/apache/camel/component/disruptor/disruptor-vm.json
 
b/components/camel-disruptor/src/generated/resources/META-INF/org/apache/camel/component/disruptor/disruptor-vm.json
index 45e142d7b31f..2e92d4bb4844 100644
--- 
a/components/camel-disruptor/src/generated/resources/META-INF/org/apache/camel/component/disruptor/disruptor-vm.json
+++ 
b/components/camel-disruptor/src/generated/resources/META-INF/org/apache/camel/component/disruptor/disruptor-vm.json
@@ -36,6 +36,11 @@
     "lazyStartProducer": { "index": 7, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Whether the producer should be started lazy (on the first message). By 
starting lazy you can use this to allow CamelContext and routes to startup in 
situations where a producer may otherwise fail [...]
     "autowiredEnabled": { "index": 8, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the 
producer sent" },
+    "producerIn": { "carriers": [ "any" ] },
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"waitForTaskToComplete", "value": "Never", "carriers": [ "unchanged" ] } ], 
"description": "Unchanged for a message that expects no reply (InOnly). A 
message that expects one (InOut), or waitForTaskToComplete=Always, waits for 
the body the disruptor route ends with; with more than one consumer route 
(multipleConsumers) the body stays unchanged" }
+  },
   "properties": {
     "name": { "index": 0, "kind": "path", "displayName": "Name", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Name of queue" },
     "size": { "index": 1, "kind": "parameter", "displayName": "Size", "group": 
"common", "label": "", "required": false, "type": "integer", "javaType": "int", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 1024, 
"description": "The maximum capacity of the Disruptors ringbuffer Will be 
effectively increased to the nearest power of two. Notice: Mind if you use this 
option, then it's the first endpoint being created with the queue name that 
determines the size. To [...]
diff --git 
a/components/camel-disruptor/src/generated/resources/META-INF/org/apache/camel/component/disruptor/disruptor.json
 
b/components/camel-disruptor/src/generated/resources/META-INF/org/apache/camel/component/disruptor/disruptor.json
index 0a7a8eb9d1b1..9aded081b87b 100644
--- 
a/components/camel-disruptor/src/generated/resources/META-INF/org/apache/camel/component/disruptor/disruptor.json
+++ 
b/components/camel-disruptor/src/generated/resources/META-INF/org/apache/camel/component/disruptor/disruptor.json
@@ -36,6 +36,11 @@
     "lazyStartProducer": { "index": 7, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Whether the producer should be started lazy (on the first message). By 
starting lazy you can use this to allow CamelContext and routes to startup in 
situations where a producer may otherwise fail [...]
     "autowiredEnabled": { "index": 8, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the 
producer sent" },
+    "producerIn": { "carriers": [ "any" ] },
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"waitForTaskToComplete", "value": "Never", "carriers": [ "unchanged" ] } ], 
"description": "Unchanged for a message that expects no reply (InOnly). A 
message that expects one (InOut), or waitForTaskToComplete=Always, waits for 
the body the disruptor route ends with; with more than one consumer route 
(multipleConsumers) the body stays unchanged" }
+  },
   "properties": {
     "name": { "index": 0, "kind": "path", "displayName": "Name", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Name of queue" },
     "size": { "index": 1, "kind": "parameter", "displayName": "Size", "group": 
"common", "label": "", "required": false, "type": "integer", "javaType": "int", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 1024, 
"description": "The maximum capacity of the Disruptors ringbuffer Will be 
effectively increased to the nearest power of two. Notice: Mind if you use this 
option, then it's the first endpoint being created with the queue name that 
determines the size. To [...]
diff --git 
a/components/camel-disruptor/src/main/java/org/apache/camel/component/disruptor/DisruptorEndpoint.java
 
b/components/camel-disruptor/src/main/java/org/apache/camel/component/disruptor/DisruptorEndpoint.java
index aa236f9be717..511a49a3c79b 100644
--- 
a/components/camel-disruptor/src/main/java/org/apache/camel/component/disruptor/DisruptorEndpoint.java
+++ 
b/components/camel-disruptor/src/main/java/org/apache/camel/component/disruptor/DisruptorEndpoint.java
@@ -36,6 +36,9 @@ import org.apache.camel.Producer;
 import org.apache.camel.WaitForTaskToComplete;
 import org.apache.camel.api.management.ManagedAttribute;
 import org.apache.camel.api.management.ManagedResource;
+import org.apache.camel.spi.BodyType;
+import org.apache.camel.spi.BodyType.Carrier;
+import org.apache.camel.spi.BodyTypes;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.UriEndpoint;
 import org.apache.camel.spi.UriParam;
@@ -53,6 +56,15 @@ import org.slf4j.LoggerFactory;
 @ManagedResource(description = "Managed Disruptor Endpoint")
 @UriEndpoint(firstVersion = "2.12.0", scheme = "disruptor,disruptor-vm", title 
= "Disruptor,Disruptor VM",
              remote = false, internal = true, syntax = "disruptor:name", 
category = { Category.MESSAGING })
+@BodyTypes(consumerOut = @BodyType(value = Carrier.UNCHANGED, description = 
"The body the producer sent"),
+           producerIn = @BodyType(Carrier.ANY),
+           producerOut = @BodyType(value = Carrier.UNKNOWN,
+                                   byOption = @BodyType.When(option = 
"waitForTaskToComplete", value = "Never",
+                                                             carriers = 
Carrier.UNCHANGED),
+                                   description = "Unchanged for a message that 
expects no reply (InOnly). A message that"
+                                                 + " expects one (InOut), or 
waitForTaskToComplete=Always, waits for the"
+                                                 + " body the disruptor route 
ends with; with more than one consumer route"
+                                                 + " (multipleConsumers) the 
body stays unchanged"))
 public class DisruptorEndpoint extends DefaultEndpoint implements 
AsyncEndpoint, MultipleConsumersSupport {
     /**
      * Property on the exchange published by a producer that waits for the 
reply. Its value is set to true when the
diff --git 
a/components/camel-hivemq/src/generated/resources/META-INF/org/apache/camel/component/hivemq/hivemq.json
 
b/components/camel-hivemq/src/generated/resources/META-INF/org/apache/camel/component/hivemq/hivemq.json
index 5949527c4f7b..c7984eddd189 100644
--- 
a/components/camel-hivemq/src/generated/resources/META-INF/org/apache/camel/component/hivemq/hivemq.json
+++ 
b/components/camel-hivemq/src/generated/resources/META-INF/org/apache/camel/component/hivemq/hivemq.json
@@ -45,6 +45,11 @@
     "CamelHiveMQRetained": { "index": 2, "kind": "header", "displayName": "", 
"group": "common", "label": "", "required": false, "javaType": "Boolean", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Whether the message should be retained.", 
"constantName": 
"org.apache.camel.component.hivemq.HiveMQConstants#MQTT_RETAINED" },
     "CamelHiveMQOverrideTopic": { "index": 3, "kind": "header", "displayName": 
"", "group": "common", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Header to dynamically override the target topic for 
publishing.", "constantName": 
"org.apache.camel.component.hivemq.HiveMQConstants#OVERRIDE_TOPIC" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", 
"description": "The payload of the MQTT message, an empty byte array for an 
empty payload. The topic is in the CamelHiveMQTopic header" },
+    "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "null" ], 
"description": "What converts to a byte array: text, bytes, a stream or a file, 
sent as the payload; no body is sent as an empty payload. A Map, a POJO or a 
number does not convert and is sent as an empty payload too, without an error: 
marshal it first" },
+    "producerOut": { "carriers": [ "unchanged" ] }
+  },
   "properties": {
     "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The MQTT topic name or pattern to 
subscribe to or publish on." },
     "cleanStart": { "index": 1, "kind": "parameter", "displayName": "Clean 
Start", "group": "common", "label": "", "required": false, "type": "boolean", 
"javaType": "boolean", "deprecated": false, "autowired": false, "secret": 
false, "defaultValue": true, "configurationClass": 
"org.apache.camel.component.hivemq.HiveMQConfiguration", "configurationField": 
"configuration", "description": "Whether to initiate a clean session upon 
connecting to the broker (called clean session in MQTT 3.1.1  [...]
diff --git 
a/components/camel-hivemq/src/main/java/org/apache/camel/component/hivemq/HiveMQEndpoint.java
 
b/components/camel-hivemq/src/main/java/org/apache/camel/component/hivemq/HiveMQEndpoint.java
index 9ec1f0bf5f1f..d93321f93ca7 100644
--- 
a/components/camel-hivemq/src/main/java/org/apache/camel/component/hivemq/HiveMQEndpoint.java
+++ 
b/components/camel-hivemq/src/main/java/org/apache/camel/component/hivemq/HiveMQEndpoint.java
@@ -25,6 +25,9 @@ import org.apache.camel.Consumer;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
 import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.BodyType;
+import org.apache.camel.spi.BodyType.Carrier;
+import org.apache.camel.spi.BodyTypes;
 import org.apache.camel.spi.EndpointServiceLocation;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.UriEndpoint;
@@ -34,6 +37,15 @@ import org.apache.camel.support.DefaultEndpoint;
 
 @UriEndpoint(firstVersion = "4.23.0", scheme = "hivemq", title = "HiveMQ", 
syntax = "hivemq:topic",
              category = { Category.MESSAGING, Category.IOT }, headersClass = 
HiveMQConstants.class)
+@BodyTypes(consumerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]",
+                                   description = "The payload of the MQTT 
message, an empty byte array for an empty"
+                                                 + " payload. The topic is in 
the CamelHiveMQTopic header"),
+           producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.NULL },
+                                  description = "What converts to a byte 
array: text, bytes, a stream or a file, sent as"
+                                                + " the payload; no body is 
sent as an empty payload. A Map, a POJO or a"
+                                                + " number does not convert 
and is sent as an empty payload too, without"
+                                                + " an error: marshal it 
first"),
+           producerOut = @BodyType(Carrier.UNCHANGED))
 public class HiveMQEndpoint extends DefaultEndpoint implements 
EndpointServiceLocation {
 
     /**
diff --git 
a/components/camel-iggy/src/generated/resources/META-INF/org/apache/camel/component/iggy/iggy.json
 
b/components/camel-iggy/src/generated/resources/META-INF/org/apache/camel/component/iggy/iggy.json
index b386cbb2a524..633921d7a8ce 100644
--- 
a/components/camel-iggy/src/generated/resources/META-INF/org/apache/camel/component/iggy/iggy.json
+++ 
b/components/camel-iggy/src/generated/resources/META-INF/org/apache/camel/component/iggy/iggy.json
@@ -56,6 +56,11 @@
     "useGlobalSslContextParameters": { "index": 29, "kind": "property", 
"displayName": "Use Global Ssl Context Parameters", "group": "security", 
"label": "security", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Enable usage of global SSL context 
parameters." },
     "username": { "index": 30, "kind": "property", "displayName": "Username", 
"group": "security", "label": "security", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": true, "security": "secret", "configurationClass": 
"org.apache.camel.component.iggy.IggyConfiguration", "configurationField": 
"configuration", "description": "Iggy username" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", 
"description": "The payload of the Iggy message, decoded as text with the 
default charset of the JVM: a binary payload does not survive" },
+    "producerIn": { "carriers": [ "any" ], "description": "The body is 
converted to text and sent as one message, so bytes are decoded as text (a 
binary payload is corrupted) and a Map or a POJO is sent as its toString(): 
marshal it first. A List of String or of Iggy Message is sent as one message 
per element, and an Iggy Message as it is. No body or an empty List fails" },
+    "producerOut": { "carriers": [ "unchanged" ] }
+  },
   "properties": {
     "topicName": { "index": 0, "kind": "path", "displayName": "Topic Name", 
"group": "common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Name of the topic" },
     "autoCreateStream": { "index": 1, "kind": "parameter", "displayName": 
"Auto Create Stream", "group": "common", "label": "", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": true, "configurationClass": 
"org.apache.camel.component.iggy.IggyConfiguration", "configurationField": 
"configuration", "description": "Whether to automatically create stream if it 
does not exist" },
diff --git 
a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyEndpoint.java
 
b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyEndpoint.java
index b9d340db7061..8e4bc05660f3 100644
--- 
a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyEndpoint.java
+++ 
b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyEndpoint.java
@@ -26,6 +26,9 @@ import org.apache.camel.Category;
 import org.apache.camel.Consumer;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
+import org.apache.camel.spi.BodyType;
+import org.apache.camel.spi.BodyType.Carrier;
+import org.apache.camel.spi.BodyTypes;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.spi.HeaderFilterStrategyAware;
 import org.apache.camel.spi.Metadata;
@@ -50,6 +53,16 @@ import org.slf4j.LoggerFactory;
  */
 @UriEndpoint(firstVersion = "4.17.0", scheme = "iggy", title = "Iggy", syntax 
= "iggy:topicName",
              category = { Category.MESSAGING }, headersClass = 
IggyConstants.class)
+@BodyTypes(consumerOut = @BodyType(value = Carrier.TEXT, javaType = 
"java.lang.String",
+                                   description = "The payload of the Iggy 
message, decoded as text with the default charset"
+                                                 + " of the JVM: a binary 
payload does not survive"),
+           producerIn = @BodyType(value = Carrier.ANY,
+                                  description = "The body is converted to text 
and sent as one message, so bytes are"
+                                                + " decoded as text (a binary 
payload is corrupted) and a Map or a POJO is"
+                                                + " sent as its toString(): 
marshal it first. A List of String or of Iggy"
+                                                + " Message is sent as one 
message per element, and an Iggy Message as it"
+                                                + " is. No body or an empty 
List fails"),
+           producerOut = @BodyType(Carrier.UNCHANGED))
 public class IggyEndpoint extends DefaultEndpoint implements 
HeaderFilterStrategyAware {
 
     private static final BigInteger MICROS_PER_SECOND = 
BigInteger.valueOf(1_000_000L);
diff --git 
a/components/camel-kafka-share/src/generated/resources/META-INF/org/apache/camel/component/kafka/share/kafka-share.json
 
b/components/camel-kafka-share/src/generated/resources/META-INF/org/apache/camel/component/kafka/share/kafka-share.json
index bda5110b0b41..b3b29cceedcb 100644
--- 
a/components/camel-kafka-share/src/generated/resources/META-INF/org/apache/camel/component/kafka/share/kafka-share.json
+++ 
b/components/camel-kafka-share/src/generated/resources/META-INF/org/apache/camel/component/kafka/share/kafka-share.json
@@ -114,6 +114,9 @@
     "CamelKafkaShareDeliveryCount": { "index": 6, "kind": "header", 
"displayName": "", "group": "consumer", "label": "", "required": false, 
"javaType": "Short", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "important": true, "description": "How many times the 
record has been delivered, this delivery included. The header is not set when 
the broker does not count the deliveries.", "constantName": 
"org.apache.camel.component.kafka.share.KafkaShareConstant [...]
     "CamelKafkaShareAcknowledge": { "index": 7, "kind": "header", 
"displayName": "", "group": "consumer", "label": "", "required": false, 
"javaType": "String", "enum": [ "ACCEPT", "RELEASE", "REJECT" ], "deprecated": 
false, "deprecationNote": "", "autowired": false, "secret": false, 
"description": "How to acknowledge the record (ACCEPT, RELEASE or REJECT), 
instead of deriving it from the outcome of the exchange. Set it in the route, 
for example to REJECT a record that was delivered too m [...]
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "text", "null" ], "dependsOn": [ 
"valueDeserializer" ], "byOption": [ { "option": "valueDeserializer", "value": 
"org.apache.kafka.common.serialization.ByteArrayDeserializer", "carriers": [ 
"bytes", "null" ], "javaType": "byte[]" } ], "description": "The value of the 
record: a String with the default valueDeserializer (StringDeserializer), null 
for a tombstone. The key of the record, when it has one, is in the 
CamelKafkaKey header" }
+  },
   "properties": {
     "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": 
"common", "label": "common", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.kafka.share.KafkaShareConfiguration", 
"configurationField": "configuration", "description": "Name of the topic to 
consume from. Use comma to separate multiple topics. Topic patterns are no [...]
     "additionalProperties": { "index": 1, "kind": "parameter", "displayName": 
"Additional Properties", "group": "common", "label": "common", "required": 
false, "type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.Object>", "prefix": "additionalProperties.", "multiValue": true, 
"deprecated": false, "autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.kafka.share.KafkaShareConfiguration", 
"configurationField": "configuration", "descript [...]
diff --git 
a/components/camel-kafka-share/src/main/java/org/apache/camel/component/kafka/share/KafkaShareEndpoint.java
 
b/components/camel-kafka-share/src/main/java/org/apache/camel/component/kafka/share/KafkaShareEndpoint.java
index dcec846fccdd..30093f15cf05 100644
--- 
a/components/camel-kafka-share/src/main/java/org/apache/camel/component/kafka/share/KafkaShareEndpoint.java
+++ 
b/components/camel-kafka-share/src/main/java/org/apache/camel/component/kafka/share/KafkaShareEndpoint.java
@@ -25,6 +25,9 @@ import org.apache.camel.Consumer;
 import org.apache.camel.MultipleConsumersSupport;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
+import org.apache.camel.spi.BodyType;
+import org.apache.camel.spi.BodyType.Carrier;
+import org.apache.camel.spi.BodyTypes;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.EndpointServiceLocation;
 import org.apache.camel.spi.UriEndpoint;
@@ -41,6 +44,13 @@ import org.slf4j.LoggerFactory;
  */
 @UriEndpoint(firstVersion = "4.23.0", scheme = "kafka-share", title = "Kafka 
Share", syntax = "kafka-share:topic",
              consumerOnly = true, category = { Category.MESSAGING }, 
headersClass = KafkaShareConstants.class)
+@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.NULL }, 
dependsOn = "valueDeserializer",
+                                   byOption = @BodyType.When(option = 
"valueDeserializer",
+                                                             value = 
"org.apache.kafka.common.serialization.ByteArrayDeserializer",
+                                                             carriers = { 
Carrier.BYTES, Carrier.NULL }, javaType = "byte[]"),
+                                   description = "The value of the record: a 
String with the default valueDeserializer"
+                                                 + " (StringDeserializer), 
null for a tombstone. The key of the"
+                                                 + " record, when it has one, 
is in the CamelKafkaKey header"))
 public class KafkaShareEndpoint extends DefaultEndpoint implements 
MultipleConsumersSupport, EndpointServiceLocation {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(KafkaShareEndpoint.class);
diff --git 
a/components/camel-pubnub/src/generated/resources/META-INF/org/apache/camel/component/pubnub/pubnub.json
 
b/components/camel-pubnub/src/generated/resources/META-INF/org/apache/camel/component/pubnub/pubnub.json
index dd9a6e85c213..e4d1181ad220 100644
--- 
a/components/camel-pubnub/src/generated/resources/META-INF/org/apache/camel/component/pubnub/pubnub.json
+++ 
b/components/camel-pubnub/src/generated/resources/META-INF/org/apache/camel/component/pubnub/pubnub.json
@@ -44,6 +44,11 @@
     "CamelPubNubOverrideChannel": { "index": 3, "kind": "header", 
"displayName": "", "group": "producer", "label": "producer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The channel to use instead of the 
channel configured on the endpoint.", "constantName": 
"org.apache.camel.component.pubnub.PubNubConstants#OVERRIDE_CHANNEL" },
     "CamelPubNubUUID": { "index": 4, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "UUID to be used as a device identifier.", 
"constantName": "org.apache.camel.component.pubnub.PubNubConstants#UUID" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "pojo" ], "javaType": 
"com.pubnub.api.models.consumer.pubsub.PNMessageResult", "byOption": [ { 
"option": "withPresence", "value": "true", "carriers": [ "pojo" ] } ], 
"description": "The PubNub PNMessageResult; its getMessage() is the payload as 
a Gson JsonElement, and it does not convert to the payload text. With 
withPresence, a presence event comes as a PNPresenceEventResult. The channel 
and timetoken are in the CamelPubNubChannel and CamelPubNubTimeTo [...]
+    "producerIn": { "carriers": [ "text", "value", "map", "list", "pojo" ], 
"byOption": [ { "option": "operation", "value": "SETSTATE", "carriers": [ 
"map", "pojo" ] }, { "option": "operation", "value": "GETHISTORY", "carriers": 
[ "any" ] }, { "option": "operation", "value": "GETSTATE", "carriers": [ "any" 
] }, { "option": "operation", "value": "HERENOW", "carriers": [ "any" ] } ], 
"description": "The message to publish or fire, serialized to JSON by the 
PubNub client: text is sent as a  [...]
+    "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": 
"operation", "value": "GETHISTORY", "carriers": [ "list", "unchanged" ] }, { 
"option": "operation", "value": "GETSTATE", "carriers": [ "pojo" ], "javaType": 
"com.pubnub.api.models.consumer.presence.PNGetStateResult" }, { "option": 
"operation", "value": "HERENOW", "carriers": [ "pojo" ], "javaType": 
"com.pubnub.api.models.consumer.presence.PNHereNowResult" }, { "option": 
"operation", "value": "SETSTATE", "carriers [...]
+  },
   "properties": {
     "channel": { "index": 0, "kind": "path", "displayName": "Channel", 
"group": "common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.pubnub.PubNubConfiguration", "configurationField": 
"configuration", "description": "The channel used for subscribing\/publishing 
events" },
     "uuid": { "index": 1, "kind": "parameter", "displayName": "Uuid", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.pubnub.PubNubConfiguration", "configurationField": 
"configuration", "description": "UUID to be used as a device identifier, a 
default UUID is generated if not passed." },
diff --git 
a/components/camel-pubnub/src/main/java/org/apache/camel/component/pubnub/PubNubEndpoint.java
 
b/components/camel-pubnub/src/main/java/org/apache/camel/component/pubnub/PubNubEndpoint.java
index 64d9038a55c7..24e56b3438ad 100644
--- 
a/components/camel-pubnub/src/main/java/org/apache/camel/component/pubnub/PubNubEndpoint.java
+++ 
b/components/camel-pubnub/src/main/java/org/apache/camel/component/pubnub/PubNubEndpoint.java
@@ -24,6 +24,9 @@ import org.apache.camel.Category;
 import org.apache.camel.Consumer;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
+import org.apache.camel.spi.BodyType;
+import org.apache.camel.spi.BodyType.Carrier;
+import org.apache.camel.spi.BodyTypes;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.UriEndpoint;
 import org.apache.camel.spi.UriParam;
@@ -34,6 +37,41 @@ import org.apache.camel.support.DefaultEndpoint;
  */
 @UriEndpoint(firstVersion = "2.19.0", scheme = "pubnub", title = "PubNub", 
syntax = "pubnub:channel",
              category = { Category.CLOUD, Category.IOT, Category.MESSAGING }, 
headersClass = PubNubConstants.class)
+@BodyTypes(consumerOut = @BodyType(value = Carrier.POJO,
+                                   javaType = 
"com.pubnub.api.models.consumer.pubsub.PNMessageResult",
+                                   byOption = @BodyType.When(option = 
"withPresence", value = "true",
+                                                             carriers = 
Carrier.POJO),
+                                   description = "The PubNub PNMessageResult; 
its getMessage() is the payload as a Gson"
+                                                 + " JsonElement, and it does 
not convert to the payload text. With"
+                                                 + " withPresence, a presence 
event comes as a PNPresenceEventResult. The"
+                                                 + " channel and timetoken are 
in the CamelPubNubChannel and"
+                                                 + " CamelPubNubTimeToken 
headers"),
+           producerIn = @BodyType(value = { Carrier.TEXT, Carrier.VALUE, 
Carrier.MAP, Carrier.LIST, Carrier.POJO },
+                                  byOption = {
+                                          @BodyType.When(option = "operation", 
value = "SETSTATE",
+                                                         carriers = { 
Carrier.MAP, Carrier.POJO }),
+                                          @BodyType.When(option = "operation", 
value = "GETHISTORY", carriers = Carrier.ANY),
+                                          @BodyType.When(option = "operation", 
value = "GETSTATE", carriers = Carrier.ANY),
+                                          @BodyType.When(option = "operation", 
value = "HERENOW", carriers = Carrier.ANY) },
+                                  description = "The message to publish or 
fire, serialized to JSON by the PubNub client:"
+                                                + " text is sent as a JSON 
string (not parsed), a Map or a POJO as a JSON"
+                                                + " object, bytes as an array 
of numbers; a stream or a file fails, and an"
+                                                + " empty body fails. SETSTATE 
needs a Map or a POJO (a JSON object); the"
+                                                + " other operations do not 
read the body"),
+           producerOut = @BodyType(value = Carrier.UNCHANGED,
+                                   byOption = {
+                                           @BodyType.When(option = 
"operation", value = "GETHISTORY",
+                                                          carriers = { 
Carrier.LIST, Carrier.UNCHANGED }),
+                                           @BodyType.When(option = 
"operation", value = "GETSTATE", carriers = Carrier.POJO,
+                                                          javaType = 
"com.pubnub.api.models.consumer.presence.PNGetStateResult"),
+                                           @BodyType.When(option = 
"operation", value = "HERENOW", carriers = Carrier.POJO,
+                                                          javaType = 
"com.pubnub.api.models.consumer.presence.PNHereNowResult"),
+                                           @BodyType.When(option = 
"operation", value = "SETSTATE", carriers = Carrier.POJO,
+                                                          javaType = 
"com.pubnub.api.models.consumer.presence.PNSetStateResult") },
+                                   description = "PUBLISH and FIRE leave the 
body unchanged, with the timetoken in the"
+                                                 + " CamelPubNubTimeToken 
header. GETHISTORY gives a List of"
+                                                 + " PNHistoryItemResult; 
GETSTATE, HERENOW and SETSTATE the result object"
+                                                 + " of the PubNub client"))
 public class PubNubEndpoint extends DefaultEndpoint {
 
     @UriParam(label = "advanced")
diff --git 
a/components/camel-reactive-streams/src/generated/resources/META-INF/org/apache/camel/component/reactive/streams/reactive-streams.json
 
b/components/camel-reactive-streams/src/generated/resources/META-INF/org/apache/camel/component/reactive/streams/reactive-streams.json
index 6b6717714773..cf604936c855 100644
--- 
a/components/camel-reactive-streams/src/generated/resources/META-INF/org/apache/camel/component/reactive/streams/reactive-streams.json
+++ 
b/components/camel-reactive-streams/src/generated/resources/META-INF/org/apache/camel/component/reactive/streams/reactive-streams.json
@@ -38,6 +38,12 @@
     "CamelReactiveStreamsEventType": { "index": 0, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Every exchange consumed by Camel has 
this header set to indicate if the exchange contains an item (value=onNext), an 
error (value=onError) or a completion event (value=onComplete). Errors and 
completion notification are not  [...]
     "CamelReactiveStreamsCallback": { "index": 1, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "org.apache.camel.component.reactive.streams.api.DispatchCallback", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The callback.", "constantName": 
"org.apache.camel.component.reactive.streams.ReactiveStreamsConstants#REACTIVE_STREAMS_CALLBACK"
 }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "unknown" ], "description": "The item the 
publisher emits, as it is (an Exchange it emits is routed as it is). With 
forwardOnComplete, the end of the stream comes as an exchange without a body; 
with forwardOnError, the error as a Throwable body. The 
CamelReactiveStreamsEventType header says which" },
+    "consumerReply": { "carriers": [ "any" ], "description": "A caller of 
toStream or to() gets the exchange the route ends with, or its body converted 
to the type it asks for" },
+    "producerIn": { "carriers": [ "any" ], "description": "The exchange is 
handed to the subscribers of the stream as it is; a subscriber that asks for a 
type gets the body converted to it" },
+    "producerOut": { "carriers": [ "unchanged" ] }
+  },
   "properties": {
     "stream": { "index": 0, "kind": "path", "displayName": "Stream", "group": 
"common", "label": "", "required": false, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"description": "Name of the stream channel used by the endpoint to exchange 
messages." },
     "concurrentConsumers": { "index": 1, "kind": "parameter", "displayName": 
"Concurrent Consumers", "group": "consumer", "label": "consumer", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 1, "description": "Number of threads 
used to process exchanges in the Camel route." },
diff --git 
a/components/camel-reactive-streams/src/main/java/org/apache/camel/component/reactive/streams/ReactiveStreamsEndpoint.java
 
b/components/camel-reactive-streams/src/main/java/org/apache/camel/component/reactive/streams/ReactiveStreamsEndpoint.java
index b46b599252e8..c0eae8140c47 100644
--- 
a/components/camel-reactive-streams/src/main/java/org/apache/camel/component/reactive/streams/ReactiveStreamsEndpoint.java
+++ 
b/components/camel-reactive-streams/src/main/java/org/apache/camel/component/reactive/streams/ReactiveStreamsEndpoint.java
@@ -23,6 +23,9 @@ import org.apache.camel.Producer;
 import org.apache.camel.api.management.ManagedAttribute;
 import org.apache.camel.api.management.ManagedResource;
 import 
org.apache.camel.component.reactive.streams.api.CamelReactiveStreamsService;
+import org.apache.camel.spi.BodyType;
+import org.apache.camel.spi.BodyType.Carrier;
+import org.apache.camel.spi.BodyTypes;
 import org.apache.camel.spi.UriEndpoint;
 import org.apache.camel.spi.UriParam;
 import org.apache.camel.spi.UriPath;
@@ -34,6 +37,18 @@ import org.apache.camel.support.DefaultEndpoint;
 @UriEndpoint(firstVersion = "2.19.0", scheme = "reactive-streams", title = 
"Reactive Streams",
              syntax = "reactive-streams:stream",
              remote = false, category = { Category.MESSAGING }, headersClass = 
ReactiveStreamsConstants.class)
+@BodyTypes(consumerOut = @BodyType(value = Carrier.UNKNOWN,
+                                   description = "The item the publisher 
emits, as it is (an Exchange it emits is routed"
+                                                 + " as it is). With 
forwardOnComplete, the end of the stream comes as an"
+                                                 + " exchange without a body; 
with forwardOnError, the error as a"
+                                                 + " Throwable body. The 
CamelReactiveStreamsEventType header says which"),
+           consumerReply = @BodyType(value = Carrier.ANY,
+                                     description = "A caller of toStream or 
to() gets the exchange the route ends with,"
+                                                   + " or its body converted 
to the type it asks for"),
+           producerIn = @BodyType(value = Carrier.ANY,
+                                  description = "The exchange is handed to the 
subscribers of the stream as it is; a"
+                                                + " subscriber that asks for a 
type gets the body converted to it"),
+           producerOut = @BodyType(value = Carrier.UNCHANGED))
 @ManagedResource(description = "Managed ReactiveStreamsEndpoint")
 public class ReactiveStreamsEndpoint extends DefaultEndpoint {
 
diff --git 
a/components/camel-rocketmq/src/generated/resources/META-INF/org/apache/camel/component/rocketmq/rocketmq.json
 
b/components/camel-rocketmq/src/generated/resources/META-INF/org/apache/camel/component/rocketmq/rocketmq.json
index 2f2db0763137..746bbd41a7b6 100644
--- 
a/components/camel-rocketmq/src/generated/resources/META-INF/org/apache/camel/component/rocketmq/rocketmq.json
+++ 
b/components/camel-rocketmq/src/generated/resources/META-INF/org/apache/camel/component/rocketmq/rocketmq.json
@@ -67,6 +67,11 @@
     "CamelRockerMQReconsumeTimes": { "index": 18, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Reconsume times", "constantName": 
"org.apache.camel.component.rocketmq.RocketMQConstants#RECONSUME_TIMES" },
     "CamelRockerMQPreparedTransactionOffset": { "index": 19, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Prepard transaction offset", 
"constantName": 
"org.apache.camel.component.rocketmq.RocketMQConstants#PREPARED_TRANSACTION_OFFSET"
 }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", 
"description": "The body of the RocketMQ message. The consumer does not reply: 
the body the route ends with is not sent back" },
+    "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], 
"description": "What converts to a byte array: text, bytes, a stream or a file, 
sent as the body of the message. A Map, a POJO, a number or no body fails, and 
the broker rejects an empty body: marshal it first" },
+    "producerOut": { "carriers": [ "unchanged" ], "dependsOn": [ 
"replyToTopic" ], "description": "The body is left as it was. With the InOut 
pattern and a replyToTopic, the producer waits for the reply and the body is 
the reply as a byte array" }
+  },
   "properties": {
     "topicName": { "index": 0, "kind": "path", "displayName": "Topic Name", 
"group": "common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Topic name of this endpoint." },
     "accessChannel": { "index": 1, "kind": "parameter", "displayName": "Access 
Channel", "group": "common", "label": "common", "required": false, "type": 
"enum", "javaType": "java.lang.String", "enum": [ "LOCAL", "CLOUD" ], 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 
"LOCAL", "description": "Access channel of RocketMQ cluster. LOCAL or CLOUD, 
LOCAL by default" },
diff --git 
a/components/camel-rocketmq/src/main/java/org/apache/camel/component/rocketmq/RocketMQEndpoint.java
 
b/components/camel-rocketmq/src/main/java/org/apache/camel/component/rocketmq/RocketMQEndpoint.java
index fe6f040a73dd..032e4673c6e5 100644
--- 
a/components/camel-rocketmq/src/main/java/org/apache/camel/component/rocketmq/RocketMQEndpoint.java
+++ 
b/components/camel-rocketmq/src/main/java/org/apache/camel/component/rocketmq/RocketMQEndpoint.java
@@ -23,6 +23,9 @@ import org.apache.camel.Consumer;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
+import org.apache.camel.spi.BodyType;
+import org.apache.camel.spi.BodyType.Carrier;
+import org.apache.camel.spi.BodyTypes;
 import org.apache.camel.spi.EndpointServiceLocation;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.UriEndpoint;
@@ -36,6 +39,17 @@ import org.apache.camel.support.DefaultMessage;
  */
 @UriEndpoint(firstVersion = "3.20.0", scheme = "rocketmq", syntax = 
"rocketmq:topicName", title = "RocketMQ",
              category = Category.MESSAGING, headersClass = 
RocketMQConstants.class)
+@BodyTypes(consumerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]",
+                                   description = "The body of the RocketMQ 
message. The consumer does not reply: the body"
+                                                 + " the route ends with is 
not sent back"),
+           producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE },
+                                  description = "What converts to a byte 
array: text, bytes, a stream or a file, sent as"
+                                                + " the body of the message. A 
Map, a POJO, a number or no body fails, and"
+                                                + " the broker rejects an 
empty body: marshal it first"),
+           producerOut = @BodyType(value = Carrier.UNCHANGED, dependsOn = 
"replyToTopic",
+                                   description = "The body is left as it was. 
With the InOut pattern and a replyToTopic,"
+                                                 + " the producer waits for 
the reply and the body is the reply as a byte"
+                                                 + " array"))
 public class RocketMQEndpoint extends DefaultEndpoint implements 
AsyncEndpoint, EndpointServiceLocation {
 
     @UriPath
diff --git 
a/components/camel-sjms/src/generated/resources/META-INF/org/apache/camel/component/sjms/sjms.json
 
b/components/camel-sjms/src/generated/resources/META-INF/org/apache/camel/component/sjms/sjms.json
index 48aa9f58d2d8..93bb9b0f8276 100644
--- 
a/components/camel-sjms/src/generated/resources/META-INF/org/apache/camel/component/sjms/sjms.json
+++ 
b/components/camel-sjms/src/generated/resources/META-INF/org/apache/camel/component/sjms/sjms.json
@@ -47,6 +47,12 @@
     "JMSReplyTo": { "index": 3, "kind": "header", "displayName": "", "group": 
"producer", "label": "producer", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Provides an explicit ReplyTo destination (overrides any 
incoming value of Message.getJMSReplyTo() in consumer)", "constantName": 
"org.apache.camel.component.sjms.SjmsConstants#JMS_REPLY_TO" },
     "CamelSjmsBatchSize": { "index": 4, "kind": "header", "displayName": "", 
"group": "batch", "label": "consumer,batch", "required": false, "javaType": 
"int", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The size of the batch when using the batching 
consumer option.", "constantName": 
"org.apache.camel.component.sjms.SjmsConstants#SJMS_BATCH_SIZE_HEADER" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "text", "bytes", "map", "pojo", "null" ], 
"byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ 
"pojo" ], "javaType": "jakarta.jms.Message" }, { "option": 
"objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", 
"value", "list", "pojo", "null" ] } ], "description": "By the JMS message 
received: a String for a TextMessage, a byte array for a BytesMessage, a Map 
for a MapMessage, the jakarta.jms.StreamMessage its [...]
+    "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map", 
"null" ], "dependsOn": [ "jmsMessageType" ], "byOption": [ { "option": 
"objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", 
"stream", "file", "map", "value", "list", "pojo", "null" ] } ], "description": 
"The reply, sent as the producer sends a message. A reply that cannot be sent, 
such as a number or a List without objectMessageEnabled, is dropped and the 
caller times out" },
+    "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map", 
"null" ], "dependsOn": [ "jmsMessageType", "allowNullBody" ], "byOption": [ { 
"option": "objectMessageEnabled", "value": "true", "carriers": [ "text", 
"bytes", "stream", "file", "map", "value", "list", "pojo", "null" ] } ], 
"description": "Text is sent as a TextMessage; bytes, a stream or a file as a 
BytesMessage; a Map of simple values as a MapMessage; null as an empty Message. 
A number, a List or another Serial [...]
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { 
"option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], 
"description": "Unchanged for a message that expects no reply (InOnly). A 
message that expects one (InOut) gets the body of the reply, as the consumer 
gives it" }
+  },
   "properties": {
     "destinationType": { "index": 0, "kind": "path", "displayName": 
"Destination Type", "group": "common", "label": "", "required": false, "type": 
"enum", "javaType": "java.lang.String", "enum": [ "queue", "topic" ], 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 
"queue", "description": "The kind of destination to use" },
     "destinationName": { "index": 1, "kind": "path", "displayName": 
"Destination Name", "group": "common", "label": "", "required": true, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"DestinationName is a JMS queue or topic name. By default, the destinationName 
is interpreted as a queue name." },
diff --git a/components/camel-sjms/src/main/docs/sjms-component.adoc 
b/components/camel-sjms/src/main/docs/sjms-component.adoc
index ed0b6f9c9a2e..c779d4ded2d8 100644
--- a/components/camel-sjms/src/main/docs/sjms-component.adoc
+++ b/components/camel-sjms/src/main/docs/sjms-component.adoc
@@ -288,14 +288,28 @@ which allows use of your own custom strategy for 
formatting keys.
 
 === Message Content
 
-To deliver content over the wire, we must ensure that the body of the
-message that is being delivered adheres to the JMS Message
-Specification. Therefore, all that are produced must either be
+The values of the headers sent as JMS properties must either be
 primitives or their counter-objects (such as `Integer`, `Long`, `Character`).
 The types, `String`, `CharSequence`, `Date`, `BigDecimal` and `BigInteger` are 
all
-converted to their `toString()` representation. All other types are
+converted to their `toString()` representation. All other header values are
 dropped.
 
+The body is mapped to and from a JMS message as follows (unless the option 
`jmsMessageType` forces a type):
+
+[width="100%",cols="1,1,2",options="header"]
+|===
+| Camel body | JMS message | Body when consumed
+| `String` or XML `Node` | `TextMessage` | `String`
+| `byte[]`, `InputStream`, `Reader`, `ByteBuffer`, `File`, `Path` or 
`StreamCache` | `BytesMessage` | `byte[]`
+| `Map` (of simple values) | `MapMessage` | `Map`
+| `null` | `Message` | `null`
+| Other `Serializable` object (such as a number or a `List`) | `ObjectMessage` 
(only with `objectMessageEnabled=true`, fails otherwise) | the object
+| Any other object | `Message` without a body (a WARN is logged) | `null`
+|===
+
+A received `StreamMessage` is not mapped: the body is the 
`jakarta.jms.StreamMessage` itself.
+With `mapJmsMessage=false` the body is always the received 
`jakarta.jms.Message`.
+
 === Clustering
 
 When using _InOut_ with SJMS in a clustered environment, you must either
diff --git 
a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsEndpoint.java
 
b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsEndpoint.java
index bbac34f65675..22f989acab0f 100644
--- 
a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsEndpoint.java
+++ 
b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsEndpoint.java
@@ -50,6 +50,9 @@ import org.apache.camel.component.sjms.jms.JmsMessageType;
 import org.apache.camel.component.sjms.jms.JmsObjectFactory;
 import org.apache.camel.component.sjms.jms.MessageCreatedStrategy;
 import org.apache.camel.component.sjms.jms.SessionAcknowledgementType;
+import org.apache.camel.spi.BodyType;
+import org.apache.camel.spi.BodyType.Carrier;
+import org.apache.camel.spi.BodyTypes;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.spi.HeaderFilterStrategyAware;
 import org.apache.camel.spi.Metadata;
@@ -69,6 +72,51 @@ import org.slf4j.LoggerFactory;
  */
 @UriEndpoint(firstVersion = "2.11.0", scheme = "sjms", title = "Simple JMS", 
syntax = "sjms:destinationType:destinationName",
              category = { Category.MESSAGING }, headersClass = 
SjmsConstants.class)
+@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, 
Carrier.MAP, Carrier.POJO, Carrier.NULL },
+                                   byOption = {
+                                           @BodyType.When(option = 
"mapJmsMessage", value = "false", carriers = Carrier.POJO,
+                                                          javaType = 
"jakarta.jms.Message"),
+                                           @BodyType.When(option = 
"objectMessageEnabled", value = "true",
+                                                          carriers = {
+                                                                  
Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.VALUE,
+                                                                  
Carrier.LIST, Carrier.POJO, Carrier.NULL }) },
+                                   description = "By the JMS message received: 
a String for a TextMessage, a byte array for a"
+                                                 + " BytesMessage, a Map for a 
MapMessage, the jakarta.jms.StreamMessage itself"
+                                                 + " for a StreamMessage, and 
null for a plain Message. An ObjectMessage fails"
+                                                 + " unless 
objectMessageEnabled"),
+           consumerReply = @BodyType(value = {
+                   Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, 
Carrier.MAP,
+                   Carrier.NULL },
+                                     dependsOn = "jmsMessageType",
+                                     byOption = @BodyType.When(option = 
"objectMessageEnabled", value = "true",
+                                                               carriers = {
+                                                                       
Carrier.TEXT, Carrier.BYTES, Carrier.STREAM,
+                                                                       
Carrier.FILE, Carrier.MAP, Carrier.VALUE, Carrier.LIST,
+                                                                       
Carrier.POJO, Carrier.NULL }),
+                                     description = "The reply, sent as the 
producer sends a message. A reply that cannot be"
+                                                   + " sent, such as a number 
or a List without objectMessageEnabled, is"
+                                                   + " dropped and the caller 
times out"),
+           producerIn = @BodyType(value = {
+                   Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, 
Carrier.MAP,
+                   Carrier.NULL },
+                                  dependsOn = { "jmsMessageType", 
"allowNullBody" },
+                                  byOption = @BodyType.When(option = 
"objectMessageEnabled", value = "true",
+                                                            carriers = {
+                                                                    
Carrier.TEXT, Carrier.BYTES, Carrier.STREAM,
+                                                                    
Carrier.FILE, Carrier.MAP, Carrier.VALUE, Carrier.LIST,
+                                                                    
Carrier.POJO, Carrier.NULL }),
+                                  description = "Text is sent as a 
TextMessage; bytes, a stream or a file as a BytesMessage;"
+                                                + " a Map of simple values as 
a MapMessage; null as an empty Message. A number,"
+                                                + " a List or another 
Serializable object fails unless objectMessageEnabled;"
+                                                + " a body that is not 
Serializable is sent as an empty Message"),
+           producerOut = @BodyType(value = Carrier.UNKNOWN,
+                                   byOption = {
+                                           @BodyType.When(option = 
"exchangePattern", value = "InOnly",
+                                                          carriers = 
Carrier.UNCHANGED),
+                                           @BodyType.When(option = 
"disableReplyTo", value = "true",
+                                                          carriers = 
Carrier.UNCHANGED) },
+                                   description = "Unchanged for a message that 
expects no reply (InOnly). A message that"
+                                                 + " expects one (InOut) gets 
the body of the reply, as the consumer gives it"))
 public class SjmsEndpoint extends DefaultEndpoint
         implements AsyncEndpoint, MultipleConsumersSupport, 
HeaderFilterStrategyAware {
 
diff --git 
a/components/camel-sjms2/src/generated/resources/META-INF/org/apache/camel/component/sjms2/sjms2.json
 
b/components/camel-sjms2/src/generated/resources/META-INF/org/apache/camel/component/sjms2/sjms2.json
index 2d57158e40a8..5d9f44532261 100644
--- 
a/components/camel-sjms2/src/generated/resources/META-INF/org/apache/camel/component/sjms2/sjms2.json
+++ 
b/components/camel-sjms2/src/generated/resources/META-INF/org/apache/camel/component/sjms2/sjms2.json
@@ -47,6 +47,12 @@
     "JMSReplyTo": { "index": 3, "kind": "header", "displayName": "", "group": 
"producer", "label": "producer", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Provides an explicit ReplyTo destination (overrides any 
incoming value of Message.getJMSReplyTo() in consumer)", "constantName": 
"org.apache.camel.component.sjms.SjmsConstants#JMS_REPLY_TO" },
     "CamelSjmsBatchSize": { "index": 4, "kind": "header", "displayName": "", 
"group": "batch", "label": "consumer,batch", "required": false, "javaType": 
"int", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The size of the batch when using the batching 
consumer option.", "constantName": 
"org.apache.camel.component.sjms.SjmsConstants#SJMS_BATCH_SIZE_HEADER" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "text", "bytes", "map", "pojo", "null" ], 
"byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ 
"pojo" ], "javaType": "jakarta.jms.Message" }, { "option": 
"objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", 
"value", "list", "pojo", "null" ] } ], "description": "By the JMS message 
received: a String for a TextMessage, a byte array for a BytesMessage, a Map 
for a MapMessage, the jakarta.jms.StreamMessage its [...]
+    "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map", 
"null" ], "dependsOn": [ "jmsMessageType" ], "byOption": [ { "option": 
"objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", 
"stream", "file", "map", "value", "list", "pojo", "null" ] } ], "description": 
"The reply, sent as the producer sends a message. A reply that cannot be sent, 
such as a number or a List without objectMessageEnabled, is dropped and the 
caller times out" },
+    "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map", 
"null" ], "dependsOn": [ "jmsMessageType", "allowNullBody" ], "byOption": [ { 
"option": "objectMessageEnabled", "value": "true", "carriers": [ "text", 
"bytes", "stream", "file", "map", "value", "list", "pojo", "null" ] } ], 
"description": "Text is sent as a TextMessage; bytes, a stream or a file as a 
BytesMessage; a Map of simple values as a MapMessage; null as an empty Message. 
A number, a List or another Serial [...]
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { 
"option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], 
"description": "Unchanged for a message that expects no reply (InOnly). A 
message that expects one (InOut) gets the body of the reply, as the consumer 
gives it" }
+  },
   "properties": {
     "destinationType": { "index": 0, "kind": "path", "displayName": 
"Destination Type", "group": "common", "label": "", "required": false, "type": 
"enum", "javaType": "java.lang.String", "enum": [ "queue", "topic" ], 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 
"queue", "description": "The kind of destination to use" },
     "destinationName": { "index": 1, "kind": "path", "displayName": 
"Destination Name", "group": "common", "label": "", "required": true, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"DestinationName is a JMS queue or topic name. By default, the destinationName 
is interpreted as a queue name." },
diff --git a/components/camel-sjms2/src/main/docs/sjms2-component.adoc 
b/components/camel-sjms2/src/main/docs/sjms2-component.adoc
index e54ff5fd4519..e24128751a3f 100644
--- a/components/camel-sjms2/src/main/docs/sjms2-component.adoc
+++ b/components/camel-sjms2/src/main/docs/sjms2-component.adoc
@@ -292,14 +292,28 @@ which allows use of your own custom strategy for 
formatting keys.
 
 === Message Content
 
-To deliver content over the wire, we must ensure that the body of the
-message that is being delivered adheres to the JMS Message
-Specification. Therefore, all that are produced must either be
+The values of the headers sent as JMS properties must either be
 primitives or their counter-objects (such as `Integer`, `Long`, `Character`).
 The types, `String`, `CharSequence`, `Date`, `BigDecimal` and `BigInteger` are 
all
-converted to their `toString()` representation. All other types are
+converted to their `toString()` representation. All other header values are
 dropped.
 
+The body is mapped to and from a JMS message as follows (unless the option 
`jmsMessageType` forces a type):
+
+[width="100%",cols="1,1,2",options="header"]
+|===
+| Camel body | JMS message | Body when consumed
+| `String` or XML `Node` | `TextMessage` | `String`
+| `byte[]`, `InputStream`, `Reader`, `ByteBuffer`, `File`, `Path` or 
`StreamCache` | `BytesMessage` | `byte[]`
+| `Map` (of simple values) | `MapMessage` | `Map`
+| `null` | `Message` | `null`
+| Other `Serializable` object (such as a number or a `List`) | `ObjectMessage` 
(only with `objectMessageEnabled=true`, fails otherwise) | the object
+| Any other object | `Message` without a body (a WARN is logged) | `null`
+|===
+
+A received `StreamMessage` is not mapped: the body is the 
`jakarta.jms.StreamMessage` itself.
+With `mapJmsMessage=false` the body is always the received 
`jakarta.jms.Message`.
+
 === Clustering
 
 When using _InOut_ with SJMS2 in a clustered environment, you must either
diff --git 
a/components/camel-sjms2/src/main/java/org/apache/camel/component/sjms2/Sjms2Endpoint.java
 
b/components/camel-sjms2/src/main/java/org/apache/camel/component/sjms2/Sjms2Endpoint.java
index f526a7c83549..d2216108a235 100644
--- 
a/components/camel-sjms2/src/main/java/org/apache/camel/component/sjms2/Sjms2Endpoint.java
+++ 
b/components/camel-sjms2/src/main/java/org/apache/camel/component/sjms2/Sjms2Endpoint.java
@@ -22,6 +22,9 @@ import org.apache.camel.Component;
 import org.apache.camel.component.sjms.SjmsConstants;
 import org.apache.camel.component.sjms.SjmsEndpoint;
 import org.apache.camel.component.sjms2.jms.Jms2ObjectFactory;
+import org.apache.camel.spi.BodyType;
+import org.apache.camel.spi.BodyType.Carrier;
+import org.apache.camel.spi.BodyTypes;
 import org.apache.camel.spi.UriEndpoint;
 import org.apache.camel.spi.UriParam;
 
@@ -33,6 +36,51 @@ import org.apache.camel.spi.UriParam;
 @UriEndpoint(firstVersion = "2.19.0", scheme = "sjms2", extendsScheme = 
"sjms", title = "Simple JMS2",
              syntax = "sjms2:destinationType:destinationName", category = { 
Category.MESSAGING },
              headersClass = SjmsConstants.class)
+@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, 
Carrier.MAP, Carrier.POJO, Carrier.NULL },
+                                   byOption = {
+                                           @BodyType.When(option = 
"mapJmsMessage", value = "false", carriers = Carrier.POJO,
+                                                          javaType = 
"jakarta.jms.Message"),
+                                           @BodyType.When(option = 
"objectMessageEnabled", value = "true",
+                                                          carriers = {
+                                                                  
Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.VALUE,
+                                                                  
Carrier.LIST, Carrier.POJO, Carrier.NULL }) },
+                                   description = "By the JMS message received: 
a String for a TextMessage, a byte array for a"
+                                                 + " BytesMessage, a Map for a 
MapMessage, the jakarta.jms.StreamMessage itself"
+                                                 + " for a StreamMessage, and 
null for a plain Message. An ObjectMessage fails"
+                                                 + " unless 
objectMessageEnabled"),
+           consumerReply = @BodyType(value = {
+                   Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, 
Carrier.MAP,
+                   Carrier.NULL },
+                                     dependsOn = "jmsMessageType",
+                                     byOption = @BodyType.When(option = 
"objectMessageEnabled", value = "true",
+                                                               carriers = {
+                                                                       
Carrier.TEXT, Carrier.BYTES, Carrier.STREAM,
+                                                                       
Carrier.FILE, Carrier.MAP, Carrier.VALUE, Carrier.LIST,
+                                                                       
Carrier.POJO, Carrier.NULL }),
+                                     description = "The reply, sent as the 
producer sends a message. A reply that cannot be"
+                                                   + " sent, such as a number 
or a List without objectMessageEnabled, is"
+                                                   + " dropped and the caller 
times out"),
+           producerIn = @BodyType(value = {
+                   Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, 
Carrier.MAP,
+                   Carrier.NULL },
+                                  dependsOn = { "jmsMessageType", 
"allowNullBody" },
+                                  byOption = @BodyType.When(option = 
"objectMessageEnabled", value = "true",
+                                                            carriers = {
+                                                                    
Carrier.TEXT, Carrier.BYTES, Carrier.STREAM,
+                                                                    
Carrier.FILE, Carrier.MAP, Carrier.VALUE, Carrier.LIST,
+                                                                    
Carrier.POJO, Carrier.NULL }),
+                                  description = "Text is sent as a 
TextMessage; bytes, a stream or a file as a BytesMessage;"
+                                                + " a Map of simple values as 
a MapMessage; null as an empty Message. A number,"
+                                                + " a List or another 
Serializable object fails unless objectMessageEnabled;"
+                                                + " a body that is not 
Serializable is sent as an empty Message"),
+           producerOut = @BodyType(value = Carrier.UNKNOWN,
+                                   byOption = {
+                                           @BodyType.When(option = 
"exchangePattern", value = "InOnly",
+                                                          carriers = 
Carrier.UNCHANGED),
+                                           @BodyType.When(option = 
"disableReplyTo", value = "true",
+                                                          carriers = 
Carrier.UNCHANGED) },
+                                   description = "Unchanged for a message that 
expects no reply (InOnly). A message that"
+                                                 + " expects one (InOut) gets 
the body of the reply, as the consumer gives it"))
 public class Sjms2Endpoint extends SjmsEndpoint implements AsyncEndpoint {
 
     @UriParam(label = "consumer", description = "Sets the topic subscription 
id, required for durable or shared topics.")
diff --git 
a/components/camel-vertx/camel-vertx/src/generated/resources/META-INF/org/apache/camel/component/vertx/vertx.json
 
b/components/camel-vertx/camel-vertx/src/generated/resources/META-INF/org/apache/camel/component/vertx/vertx.json
index 099f9afdb652..33549d87d679 100644
--- 
a/components/camel-vertx/camel-vertx/src/generated/resources/META-INF/org/apache/camel/component/vertx/vertx.json
+++ 
b/components/camel-vertx/camel-vertx/src/generated/resources/META-INF/org/apache/camel/component/vertx/vertx.json
@@ -34,6 +34,12 @@
     "autowiredEnabled": { "index": 7, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
     "vertxFactory": { "index": 8, "kind": "property", "displayName": "Vertx 
Factory", "group": "advanced", "label": "advanced", "required": false, "type": 
"object", "javaType": "io.vertx.core.VertxBuilder", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use a custom 
VertxFactory implementation" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "unknown" ], "description": "The body of 
the event bus message, as the sender sent it: a String, a byte array, a number 
or a boolean, a JsonObject or a JsonArray, or a Serializable object such as a 
HashMap. A Buffer becomes a stream with stream caching enabled" },
+    "consumerReply": { "carriers": [ "text", "bytes", "value", "map", "list", 
"pojo", "null" ], "description": "A message with a reply address is answered 
with the body the route ends with, as the producer sends it. A stream, such as 
a received Buffer the route did not change, or a POJO that is not Serializable 
sends no reply, and the requester times out" },
+    "producerIn": { "carriers": [ "text", "bytes", "value", "map", "list", 
"pojo" ], "description": "Sent as is, with the event bus codec of its type: a 
String, a byte array, a number or a boolean, a JsonObject, a JsonArray or a 
Buffer, or a Serializable object such as a HashMap. A stream, a POJO that is 
not Serializable (without a codec registered for it) or no body fails: convert 
it first" },
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] } ], 
"description": "Unchanged for a message that expects no reply (InOnly). A 
message that expects one (InOut) is sent as a request, also with pubSub, and 
gets the body of the reply" }
+  },
   "properties": {
     "address": { "index": 0, "kind": "path", "displayName": "Address", 
"group": "common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Sets the event bus address used to 
communicate" },
     "pubSub": { "index": 1, "kind": "parameter", "displayName": "Pub Sub", 
"group": "common", "label": "", "required": false, "type": "boolean", 
"javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": false, "description": "Whether to use 
publish\/subscribe instead of point to point when sending to a vertx endpoint." 
},
diff --git 
a/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc 
b/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc
index 931f2c7f10db..d097b8eb6a6b 100644
--- a/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc
+++ b/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc
@@ -16,7 +16,8 @@ The Vert.x component is for working with the 
http://vertx.io/[Vertx]
 https://vertx.io/docs/vertx-core/java/#event_bus[EventBus].
 
 The vertx https://vertx.io/docs/vertx-core/java/#event_bus[EventBus]
-sends and receives JSON events.
+sends and receives Java objects that it has a message codec for: a `String`, a 
byte array, a number or a boolean,
+a `JsonObject`, a `JsonArray`, a `Buffer`, or a `Serializable` object.
 
 Maven users will need to add the following dependency to their `pom.xml`
 for this component:
@@ -73,6 +74,10 @@ A message goes to one consumer, or to all consumers with 
`pubSub`:
             message: "Received order ${body}"
 ----
 
+The body is sent as is, without type conversion: a stream, or a POJO that is 
not `Serializable` and has no codec
+registered on the event bus, fails with `No message codec for type`, so 
convert it to a `String` or a byte array
+first. A message without a body fails as well.
+
 When the exchange is InOut, the producer sends a request and the reply of the 
consumer becomes the message body:
 
 [source,yaml]
@@ -96,6 +101,9 @@ When the exchange is InOut, the producer sends a request and 
the reply of the co
                 expression: "Hello ${body}"
 ----
 
+The consumer replies with the body the route ends with, which needs a codec 
too. A `Buffer` the consumer receives is
+a stream when stream caching is enabled (the default), so convert a stream 
body before the route ends.
+
 == Connecting to the existing Vert.x instance
 
 If you would like to connect to the Vert.x instance already existing in
diff --git 
a/components/camel-vertx/camel-vertx/src/main/java/org/apache/camel/component/vertx/VertxEndpoint.java
 
b/components/camel-vertx/camel-vertx/src/main/java/org/apache/camel/component/vertx/VertxEndpoint.java
index 772d6862350c..2ccba990ee1c 100644
--- 
a/components/camel-vertx/camel-vertx/src/main/java/org/apache/camel/component/vertx/VertxEndpoint.java
+++ 
b/components/camel-vertx/camel-vertx/src/main/java/org/apache/camel/component/vertx/VertxEndpoint.java
@@ -24,6 +24,9 @@ import org.apache.camel.Consumer;
 import org.apache.camel.MultipleConsumersSupport;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
+import org.apache.camel.spi.BodyType;
+import org.apache.camel.spi.BodyType.Carrier;
+import org.apache.camel.spi.BodyTypes;
 import org.apache.camel.spi.EndpointServiceLocation;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.UriEndpoint;
@@ -36,6 +39,30 @@ import org.apache.camel.support.DefaultEndpoint;
  */
 @UriEndpoint(firstVersion = "2.12.0", scheme = "vertx", title = "Vert.x", 
syntax = "vertx:address",
              category = { Category.MESSAGING })
+@BodyTypes(consumerOut = @BodyType(value = Carrier.UNKNOWN,
+                                   description = "The body of the event bus 
message, as the sender sent it: a String, a byte"
+                                                 + " array, a number or a 
boolean, a JsonObject or a JsonArray, or a"
+                                                 + " Serializable object such 
as a HashMap. A Buffer becomes a stream with"
+                                                 + " stream caching enabled"),
+           consumerReply = @BodyType(value = {
+                   Carrier.TEXT, Carrier.BYTES, Carrier.VALUE, Carrier.MAP, 
Carrier.LIST, Carrier.POJO, Carrier.NULL },
+                                     description = "A message with a reply 
address is answered with the body the route ends"
+                                                   + " with, as the producer 
sends it. A stream, such as a received Buffer the"
+                                                   + " route did not change, 
or a POJO that is not Serializable sends no reply,"
+                                                   + " and the requester times 
out"),
+           producerIn = @BodyType(value = {
+                   Carrier.TEXT, Carrier.BYTES, Carrier.VALUE, Carrier.MAP, 
Carrier.LIST, Carrier.POJO },
+                                  description = "Sent as is, with the event 
bus codec of its type: a String, a byte array, a"
+                                                + " number or a boolean, a 
JsonObject, a JsonArray or a Buffer, or a"
+                                                + " Serializable object such 
as a HashMap. A stream, a POJO that is not"
+                                                + " Serializable (without a 
codec registered for it) or no body fails:"
+                                                + " convert it first"),
+           producerOut = @BodyType(value = Carrier.UNKNOWN,
+                                   byOption = @BodyType.When(option = 
"exchangePattern", value = "InOnly",
+                                                             carriers = 
Carrier.UNCHANGED),
+                                   description = "Unchanged for a message that 
expects no reply (InOnly). A message that"
+                                                 + " expects one (InOut) is 
sent as a request, also with pubSub, and gets"
+                                                 + " the body of the reply"))
 public class VertxEndpoint extends DefaultEndpoint implements AsyncEndpoint, 
MultipleConsumersSupport, EndpointServiceLocation {
 
     @UriPath
diff --git 
a/components/camel-xmpp/src/generated/resources/META-INF/org/apache/camel/component/xmpp/xmpp.json
 
b/components/camel-xmpp/src/generated/resources/META-INF/org/apache/camel/component/xmpp/xmpp.json
index 27ca8b6c40f8..4137ca97a77c 100644
--- 
a/components/camel-xmpp/src/generated/resources/META-INF/org/apache/camel/component/xmpp/xmpp.json
+++ 
b/components/camel-xmpp/src/generated/resources/META-INF/org/apache/camel/component/xmpp/xmpp.json
@@ -32,6 +32,11 @@
   "headers": {
     "CamelXmppDoc": { "index": 0, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"org.jivesoftware.smack.packet.Message", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
XMPP message", "constantName": 
"org.apache.camel.component.xmpp.XmppConstants#DOC_HEADER" }
   },
+  "bodyTypes": {
+    "consumerOut": { "carriers": [ "text", "pojo" ], "byOption": [ { "option": 
"doc", "value": "true", "carriers": [ "pojo" ], "javaType": 
"org.jivesoftware.smack.packet.Message" } ], "description": "The text of the 
chat message; the Smack Message when it has no body text, such as a pubsub 
notification. With doc, the Smack Message. The subject, thread and sender are 
in the CamelXmpp* headers" },
+    "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "doc", 
"value": "true", "carriers": [ "pojo" ] }, { "option": "pubsub", "value": 
"true", "carriers": [ "pojo" ], "javaType": 
"org.jivesoftware.smackx.pubsub.packet.PubSub" } ], "description": "The body is 
converted to text and sent as the chat message (a Map or a POJO as its 
toString); the headers become message properties. Without a room, doc sends a 
Smack Stanza (or an array of them) and pubsub a Smack PubSub packet a [...]
+    "producerOut": { "carriers": [ "unchanged" ] }
+  },
   "properties": {
     "host": { "index": 0, "kind": "path", "displayName": "Host", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Hostname for the chat server" },
     "port": { "index": 1, "kind": "path", "displayName": "Port", "group": 
"common", "label": "", "required": false, "type": "integer", "javaType": "int", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": 5222, 
"description": "Port number for the chat server" },
diff --git 
a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppEndpoint.java
 
b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppEndpoint.java
index 7572ef029d01..d2c7f8772dd0 100644
--- 
a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppEndpoint.java
+++ 
b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppEndpoint.java
@@ -27,6 +27,9 @@ import org.apache.camel.Category;
 import org.apache.camel.Consumer;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
+import org.apache.camel.spi.BodyType;
+import org.apache.camel.spi.BodyType.Carrier;
+import org.apache.camel.spi.BodyTypes;
 import org.apache.camel.spi.EndpointServiceLocation;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.spi.HeaderFilterStrategyAware;
@@ -62,6 +65,22 @@ import org.slf4j.LoggerFactory;
 @UriEndpoint(firstVersion = "1.0", scheme = "xmpp", title = "XMPP", syntax = 
"xmpp:host:port/participant",
              alternativeSyntax = "xmpp:user:password@host:port/participant",
              category = { Category.CHAT, Category.MESSAGING }, headersClass = 
XmppConstants.class)
+@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.POJO },
+                                   byOption = @BodyType.When(option = "doc", 
value = "true", carriers = Carrier.POJO,
+                                                             javaType = 
"org.jivesoftware.smack.packet.Message"),
+                                   description = "The text of the chat 
message; the Smack Message when it has no body"
+                                                 + " text, such as a pubsub 
notification. With doc, the Smack Message. The"
+                                                 + " subject, thread and 
sender are in the CamelXmpp* headers"),
+           producerIn = @BodyType(value = Carrier.ANY,
+                                  byOption = {
+                                          @BodyType.When(option = "doc", value 
= "true", carriers = Carrier.POJO),
+                                          @BodyType.When(option = "pubsub", 
value = "true", carriers = Carrier.POJO,
+                                                         javaType = 
"org.jivesoftware.smackx.pubsub.packet.PubSub") },
+                                  description = "The body is converted to text 
and sent as the chat message (a Map or a"
+                                                + " POJO as its toString); the 
headers become message properties. Without a"
+                                                + " room, doc sends a Smack 
Stanza (or an array of them) and pubsub a Smack"
+                                                + " PubSub packet as they are; 
another body fails"),
+           producerOut = @BodyType(value = Carrier.UNCHANGED))
 public class XmppEndpoint extends DefaultEndpoint implements 
HeaderFilterStrategyAware, EndpointServiceLocation {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(XmppEndpoint.class);

Reply via email to