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);
