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
The following commit(s) were added to refs/heads/main by this push:
new 3f3f25513695 CAMEL-26154: camel-iggy - send binary bodies as bytes and
give the consumer body as bytes (#28927)
3f3f25513695 is described below
commit 3f3f255136959e61d6c560e38eea36b1a2f0dcc8
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Nov 2 20:48:28 2026 +0100
CAMEL-26154: camel-iggy - send binary bodies as bytes and give the consumer
body as bytes (#28927)
* CAMEL-26154: camel-iggy - send binary bodies as bytes and give the co…
…nsumer body as bytes
The producer converted every body to a String, so a byte[] that is not valid
UTF-8 was corrupted. Bytes, streams and files are now sent as their bytes;
other bodies are still sent as UTF-8 text. The consumer decoded the payload
with the default charset of the JVM; it now sets the payload as a byte[]
body.
No body now fails with an InvalidPayloadException, a List with a null
element
fails with a clear message, and an empty List sends nothing, instead of
failing inside the Iggy client.
* CAMEL-26154: camel-iggy - document the headers on IggyConstants and d…
…rop the hand-written table
The Iggy headers had no @Metadata, so the generated headers partial was
empty
and the component doc kept a hand-written table with wrong types. The header
constants now have descriptions and their real Java types, the hand-written
table is removed, and the catalog and endpoint DSL are regenerated.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Claus Ibsen <[email protected]>
---
.../org/apache/camel/catalog/components/iggy.json | 15 +-
.../apache/camel/catalog/docs/iggy-component.adoc | 24 +-
.../org/apache/camel/component/iggy/iggy.json | 15 +-
.../camel-iggy/src/main/docs/iggy-component.adoc | 24 +-
.../apache/camel/component/iggy/IggyConstants.java | 18 ++
.../apache/camel/component/iggy/IggyEndpoint.java | 16 +-
.../camel/component/iggy/IggyFetchRecords.java | 3 +-
.../apache/camel/component/iggy/IggyProducer.java | 45 +++-
.../camel/component/iggy/IggyConsumerIT.java | 2 +-
.../camel/component/iggy/IggyMessageBodyTest.java | 244 +++++++++++++++++++++
.../apache/camel/component/iggy/IggyTestBase.java | 5 +-
.../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc | 12 +
.../builder/endpoint/EndpointHeaderBuilders.java | 13 ++
.../endpoint/dsl/IggyEndpointBuilderFactory.java | 134 +++++++++++
14 files changed, 518 insertions(+), 52 deletions(-)
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 633921d7a8ce..8c5504363873 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,9 +56,20 @@
"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" }
},
+ "headers": {
+ "CamelIggyMessageId": { "index": 0, "kind": "header", "displayName": "",
"group": "consumer", "label": "consumer", "required": false, "javaType":
"org.apache.iggy.message.MessageId", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The unique identifier
of the message.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_ID" },
+ "CamelIggyMessageOffset": { "index": 1, "kind": "header", "displayName":
"", "group": "consumer", "label": "consumer", "required": false, "javaType":
"java.math.BigInteger", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The offset of the message
in the partition.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_OFFSET" },
+ "CamelIggyMessageTimestamp": { "index": 2, "kind": "header",
"displayName": "", "group": "consumer", "label": "consumer", "required": false,
"javaType": "java.math.BigInteger", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The timestamp of the
message.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_TIMESTAMP" },
+ "CamelIggyMessageOriginTimestamp": { "index": 3, "kind": "header",
"displayName": "", "group": "consumer", "label": "consumer", "required": false,
"javaType": "java.math.BigInteger", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The original timestamp of
the message.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_ORIGIN_TIMESTAMP" },
+ "CamelIggyMessageChecksum": { "index": 4, "kind": "header", "displayName":
"", "group": "consumer", "label": "consumer", "required": false, "javaType":
"java.math.BigInteger", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The checksum of the
message.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_CHECKSUM" },
+ "CamelIggyMessageLength": { "index": 5, "kind": "header", "displayName":
"", "group": "consumer", "label": "consumer", "required": false, "javaType":
"Long", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The length of the payload of the message, in
bytes.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_LENGTH" },
+ "CamelIggyMessageSize": { "index": 6, "kind": "header", "displayName": "",
"group": "consumer", "label": "consumer", "required": false, "javaType": "int",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The size of the message, in bytes.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_SIZE" },
+ "CamelIggyTopicOverride": { "index": 7, "kind": "header", "displayName":
"", "group": "producer", "label": "producer", "required": false, "javaType":
"String", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The name of the topic to send to, instead of
the topic of the endpoint.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#TOPIC_OVERRIDE" },
+ "CamelIggyStreamOverride": { "index": 8, "kind": "header", "displayName":
"", "group": "producer", "label": "producer", "required": false, "javaType":
"String", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The name of the stream to send to, instead of
the streamName of the endpoint.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#STREAM_OVERRIDE" }
+ },
"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" },
+ "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]",
"description": "The payload of the Iggy message as a byte array: convert or
unmarshal it" },
+ "producerIn": { "carriers": [ "any" ], "description": "Bytes, a stream or
a file is sent as its bytes, and any other body is converted to text and sent
as UTF-8, so 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. An empty List sends nothing, and no body or a List with
a null element fails" },
"producerOut": { "carriers": [ "unchanged" ] }
},
"properties": {
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/iggy-component.adoc
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/iggy-component.adoc
index 4a58aacba5f7..48330c75ede1 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/iggy-component.adoc
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/iggy-component.adoc
@@ -69,21 +69,15 @@ include::partial$component-endpoint-headers.adoc[]
// endpoint options: END
-== Iggy Headers
-
-The following headers are set on the exchange when consuming messages from
Iggy:
-
-[width="100%",cols="2m,2m,5",options="header"]
-|===
-| Header | Type | Description
-| `CamelIggyMessageId` | `String` | The unique identifier of the message.
-| `CamelIggyMessageOffset` | `long` | The offset of the message in the
partition.
-| `CamelIggyMessageTimestamp` | `long` | The timestamp of the message.
-| `CamelIggyMessageOriginTimestamp` | `long` | The original timestamp of the
message.
-| `CamelIggyMessageChecksum` | `long` | The checksum of the message.
-| `CamelIggyMessageLength` | `int` | The length of the message.
-| `CamelIggyMessageSize` | `int` | The size of the message.
-|===
+== Message body
+
+The producer sends a `byte[]`, an `InputStream`, a `ByteBuffer` or a file body
as its bytes, unchanged. Any other
+body is converted to text and sent as UTF-8, so marshal a `Map` or a POJO
first, or it is sent as its `toString()`.
+A `List` of `String` or of Iggy `Message` is sent as one message per element,
and an Iggy `Message` as it is.
+An empty `List` sends nothing. No body, or a `List` with a `null` element,
fails the exchange.
+
+The consumer sets the payload of the Iggy message as a `byte[]` body. Convert
it to a `String`
+(for example with `convertBodyTo(String.class)`) or unmarshal it.
== Examples
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 633921d7a8ce..8c5504363873 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,9 +56,20 @@
"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" }
},
+ "headers": {
+ "CamelIggyMessageId": { "index": 0, "kind": "header", "displayName": "",
"group": "consumer", "label": "consumer", "required": false, "javaType":
"org.apache.iggy.message.MessageId", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "The unique identifier
of the message.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_ID" },
+ "CamelIggyMessageOffset": { "index": 1, "kind": "header", "displayName":
"", "group": "consumer", "label": "consumer", "required": false, "javaType":
"java.math.BigInteger", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The offset of the message
in the partition.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_OFFSET" },
+ "CamelIggyMessageTimestamp": { "index": 2, "kind": "header",
"displayName": "", "group": "consumer", "label": "consumer", "required": false,
"javaType": "java.math.BigInteger", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The timestamp of the
message.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_TIMESTAMP" },
+ "CamelIggyMessageOriginTimestamp": { "index": 3, "kind": "header",
"displayName": "", "group": "consumer", "label": "consumer", "required": false,
"javaType": "java.math.BigInteger", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The original timestamp of
the message.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_ORIGIN_TIMESTAMP" },
+ "CamelIggyMessageChecksum": { "index": 4, "kind": "header", "displayName":
"", "group": "consumer", "label": "consumer", "required": false, "javaType":
"java.math.BigInteger", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The checksum of the
message.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_CHECKSUM" },
+ "CamelIggyMessageLength": { "index": 5, "kind": "header", "displayName":
"", "group": "consumer", "label": "consumer", "required": false, "javaType":
"Long", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The length of the payload of the message, in
bytes.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_LENGTH" },
+ "CamelIggyMessageSize": { "index": 6, "kind": "header", "displayName": "",
"group": "consumer", "label": "consumer", "required": false, "javaType": "int",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The size of the message, in bytes.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#MESSAGE_SIZE" },
+ "CamelIggyTopicOverride": { "index": 7, "kind": "header", "displayName":
"", "group": "producer", "label": "producer", "required": false, "javaType":
"String", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The name of the topic to send to, instead of
the topic of the endpoint.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#TOPIC_OVERRIDE" },
+ "CamelIggyStreamOverride": { "index": 8, "kind": "header", "displayName":
"", "group": "producer", "label": "producer", "required": false, "javaType":
"String", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The name of the stream to send to, instead of
the streamName of the endpoint.", "constantName":
"org.apache.camel.component.iggy.IggyConstants#STREAM_OVERRIDE" }
+ },
"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" },
+ "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]",
"description": "The payload of the Iggy message as a byte array: convert or
unmarshal it" },
+ "producerIn": { "carriers": [ "any" ], "description": "Bytes, a stream or
a file is sent as its bytes, and any other body is converted to text and sent
as UTF-8, so 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. An empty List sends nothing, and no body or a List with
a null element fails" },
"producerOut": { "carriers": [ "unchanged" ] }
},
"properties": {
diff --git a/components/camel-iggy/src/main/docs/iggy-component.adoc
b/components/camel-iggy/src/main/docs/iggy-component.adoc
index 4a58aacba5f7..48330c75ede1 100644
--- a/components/camel-iggy/src/main/docs/iggy-component.adoc
+++ b/components/camel-iggy/src/main/docs/iggy-component.adoc
@@ -69,21 +69,15 @@ include::partial$component-endpoint-headers.adoc[]
// endpoint options: END
-== Iggy Headers
-
-The following headers are set on the exchange when consuming messages from
Iggy:
-
-[width="100%",cols="2m,2m,5",options="header"]
-|===
-| Header | Type | Description
-| `CamelIggyMessageId` | `String` | The unique identifier of the message.
-| `CamelIggyMessageOffset` | `long` | The offset of the message in the
partition.
-| `CamelIggyMessageTimestamp` | `long` | The timestamp of the message.
-| `CamelIggyMessageOriginTimestamp` | `long` | The original timestamp of the
message.
-| `CamelIggyMessageChecksum` | `long` | The checksum of the message.
-| `CamelIggyMessageLength` | `int` | The length of the message.
-| `CamelIggyMessageSize` | `int` | The size of the message.
-|===
+== Message body
+
+The producer sends a `byte[]`, an `InputStream`, a `ByteBuffer` or a file body
as its bytes, unchanged. Any other
+body is converted to text and sent as UTF-8, so marshal a `Map` or a POJO
first, or it is sent as its `toString()`.
+A `List` of `String` or of Iggy `Message` is sent as one message per element,
and an Iggy `Message` as it is.
+An empty `List` sends nothing. No body, or a `List` with a `null` element,
fails the exchange.
+
+The consumer sets the payload of the Iggy message as a `byte[]` body. Convert
it to a `String`
+(for example with `convertBodyTo(String.class)`) or unmarshal it.
== Examples
diff --git
a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConstants.java
b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConstants.java
index 421c28913c69..1d8fd115d468 100644
---
a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConstants.java
+++
b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConstants.java
@@ -16,16 +16,34 @@
*/
package org.apache.camel.component.iggy;
+import org.apache.camel.spi.Metadata;
+
public final class IggyConstants {
+ @Metadata(label = "consumer", description = "The unique identifier of the
message.",
+ javaType = "org.apache.iggy.message.MessageId")
public static final String MESSAGE_ID = "CamelIggyMessageId";
+ @Metadata(label = "consumer", description = "The offset of the message in
the partition.",
+ javaType = "java.math.BigInteger")
public static final String MESSAGE_OFFSET = "CamelIggyMessageOffset";
+ @Metadata(label = "consumer", description = "The timestamp of the
message.",
+ javaType = "java.math.BigInteger")
public static final String MESSAGE_TIMESTAMP = "CamelIggyMessageTimestamp";
+ @Metadata(label = "consumer", description = "The original timestamp of the
message.",
+ javaType = "java.math.BigInteger")
public static final String MESSAGE_ORIGIN_TIMESTAMP =
"CamelIggyMessageOriginTimestamp";
+ @Metadata(label = "consumer", description = "The checksum of the
message.", javaType = "java.math.BigInteger")
public static final String MESSAGE_CHECKSUM = "CamelIggyMessageChecksum";
+ @Metadata(label = "consumer", description = "The length of the payload of
the message, in bytes.", javaType = "Long")
public static final String MESSAGE_LENGTH = "CamelIggyMessageLength";
+ @Metadata(label = "consumer", description = "The size of the message, in
bytes.", javaType = "int")
public static final String MESSAGE_SIZE = "CamelIggyMessageSize";
+ @Metadata(label = "producer", description = "The name of the topic to send
to, instead of the topic of the endpoint.",
+ javaType = "String")
public static final String TOPIC_OVERRIDE = "CamelIggyTopicOverride";
+ @Metadata(label = "producer",
+ description = "The name of the stream to send to, instead of the
streamName of the endpoint.",
+ javaType = "String")
public static final String STREAM_OVERRIDE = "CamelIggyStreamOverride";
private IggyConstants() {
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 8e4bc05660f3..5e8b10e5b2b1 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
@@ -53,15 +53,15 @@ 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"),
+@BodyTypes(consumerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]",
+ description = "The payload of the Iggy
message as a byte array: convert or unmarshal it"),
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"),
+ description = "Bytes, a stream or a file is
sent as its bytes, and any other body is"
+ + " converted to text and sent
as UTF-8, so 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. An"
+ + " empty List sends nothing,
and no body or a List with a null element"
+ + " fails"),
producerOut = @BodyType(Carrier.UNCHANGED))
public class IggyEndpoint extends DefaultEndpoint implements
HeaderFilterStrategyAware {
diff --git
a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyFetchRecords.java
b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyFetchRecords.java
index 5dd67287e722..a91013d461f8 100644
---
a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyFetchRecords.java
+++
b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyFetchRecords.java
@@ -188,7 +188,8 @@ public class IggyFetchRecords implements Runnable {
private Exchange createExchange(Message message) {
Exchange exchange = iggyConsumer.createExchange(true);
- exchange.getIn().setBody(new String(message.payload())); // TODO is it
ok?
+ // the payload as it was sent: decoding it as text would corrupt a
binary payload
+ exchange.getIn().setBody(message.payload());
exchange.getIn().setHeader(IggyConstants.MESSAGE_ID,
message.header().id());
exchange.getIn().setHeader(IggyConstants.MESSAGE_OFFSET,
message.header().offset());
exchange.getIn().setHeader(IggyConstants.MESSAGE_ORIGIN_TIMESTAMP,
message.header().originTimestamp());
diff --git
a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyProducer.java
b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyProducer.java
index becae90f49bf..f9dbadb15066 100644
---
a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyProducer.java
+++
b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyProducer.java
@@ -16,20 +16,29 @@
*/
package org.apache.camel.component.iggy;
+import java.io.File;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.camel.AsyncCallback;
import org.apache.camel.Exchange;
import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.WrappedFile;
import org.apache.camel.component.iggy.client.IggyClientConnectionPool;
import org.apache.camel.support.DefaultAsyncProducer;
import org.apache.iggy.client.blocking.IggyBaseClient;
import org.apache.iggy.identifier.StreamId;
import org.apache.iggy.identifier.TopicId;
import org.apache.iggy.message.Message;
+import org.apache.iggy.message.MessageHeader;
+import org.apache.iggy.message.MessageId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -79,10 +88,18 @@ public class IggyProducer extends DefaultAsyncProducer {
IggyConfiguration iggyConfiguration = endpoint.getConfiguration();
try {
- Object body = exchange.getIn().getBody();
+ Object body = exchange.getIn().getMandatoryBody();
List<Message> messages;
if (body instanceof List bodyAsList) {
+ if (bodyAsList.isEmpty()) {
+ LOG.debug("The body is an empty List: no message to send");
+ callback.done(true);
+ return true;
+ }
+ if (bodyAsList.stream().anyMatch(Objects::isNull)) {
+ throw new RuntimeCamelException("The List body must not
contain null elements");
+ }
if (isListOfStrings(bodyAsList)) {
messages = (List<Message>) bodyAsList.stream()
.map(s -> Message.of((String) s))
@@ -97,9 +114,14 @@ public class IggyProducer extends DefaultAsyncProducer {
}
} else if (body instanceof Message bodyAsMessage) {
messages = Collections.singletonList(bodyAsMessage);
+ } else if (isBinary(body)) {
+ // bytes, streams and files are sent as they are: decoding
them as text corrupts a binary payload
+ messages = Collections.singletonList(binaryMessage(
+
exchange.getContext().getTypeConverter().mandatoryConvertTo(byte[].class,
exchange, body)));
} else {
messages = Collections
-
.singletonList(Message.of(exchange.getContext().getTypeConverter().convertTo(String.class,
body)));
+ .singletonList(Message.of(
+
exchange.getContext().getTypeConverter().mandatoryConvertTo(String.class,
exchange, body)));
}
// TODO Handle user header when they are implemented in the java
client
@@ -154,13 +176,24 @@ public class IggyProducer extends DefaultAsyncProducer {
}
private boolean isListOfStrings(List<?> list) {
- return list != null &&
- list.stream().allMatch(item -> item == null || item instanceof
String);
+ return list.stream().allMatch(String.class::isInstance);
}
private boolean isListOfMessages(List<?> list) {
- return list != null &&
- list.stream().allMatch(item -> item == null || item instanceof
Message);
+ return list.stream().allMatch(Message.class::isInstance);
+ }
+
+ private static boolean isBinary(Object body) {
+ return body instanceof byte[] || body instanceof InputStream || body
instanceof ByteBuffer
+ || body instanceof File || body instanceof Path || body
instanceof WrappedFile;
+ }
+
+ private static Message binaryMessage(byte[] payload) {
+ // the same header as Message.of(String) builds for its UTF-8 bytes
+ MessageHeader header = new MessageHeader(
+ BigInteger.ZERO, MessageId.serverGenerated(), BigInteger.ZERO,
BigInteger.ZERO, BigInteger.ZERO,
+ 0L, (long) payload.length, BigInteger.ZERO);
+ return Message.of(header, payload, Collections.emptyList());
}
}
diff --git
a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerIT.java
b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerIT.java
index b48cd6836d1d..ef3ad07431d0 100644
---
a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerIT.java
+++
b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerIT.java
@@ -39,7 +39,7 @@ public class IggyConsumerIT extends IggyTestBase {
mockEndpoint.assertIsSatisfied();
- Assertions.assertEquals(message,
mockEndpoint.getExchanges().get(0).getMessage().getBody());
+ Assertions.assertEquals(message,
mockEndpoint.getExchanges().get(0).getMessage().getBody(String.class));
}
@Test
diff --git
a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyMessageBodyTest.java
b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyMessageBodyTest.java
new file mode 100644
index 000000000000..95e5b53aeb86
--- /dev/null
+++
b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyMessageBodyTest.java
@@ -0,0 +1,244 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.iggy;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Consumer;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.Producer;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.iggy.client.IggyClientFactory;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.iggy.client.blocking.IggyBaseClient;
+import org.apache.iggy.identifier.StreamId;
+import org.apache.iggy.identifier.TopicId;
+import org.apache.iggy.message.Message;
+import org.apache.iggy.message.MessageHeader;
+import org.apache.iggy.message.MessageId;
+import org.apache.iggy.message.Partitioning;
+import org.apache.iggy.message.PolledMessages;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockedConstruction;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
+
+/**
+ * The producer sends bytes, streams and files as they are and text as UTF-8,
and the consumer gives the payload as
+ * bytes, so a binary payload survives the round trip. No body, an empty List
and a List with a null element are handled
+ * before the Iggy client is called. The Iggy client is a mock, no Iggy server
is needed.
+ */
+public class IggyMessageBodyTest {
+
+ private static final String URI
+ =
"iggy:topic?streamName=stream&autoCreateStream=false&autoCreateTopic=false&consumerGroupName=group";
+
+ // not valid UTF-8: decoding it as text replaces ff and fe with the
replacement character
+ private static final byte[] BINARY = { (byte) 0xff, (byte) 0xfe, 0x00,
0x41 };
+
+ @Test
+ void testByteArrayBodyIsSentAsItsBytes() throws Exception {
+ Message message = sendOne(BINARY.clone());
+
+ assertArrayEquals(BINARY, message.payload());
+ assertEquals(BINARY.length, message.header().payloadLength());
+ assertEquals(0L, message.header().userHeadersLength());
+ }
+
+ @Test
+ void testStreamBodyIsSentAsItsBytes() throws Exception {
+ Message message = sendOne(new ByteArrayInputStream(BINARY.clone()));
+
+ assertArrayEquals(BINARY, message.payload());
+ assertEquals(BINARY.length, message.header().payloadLength());
+ }
+
+ @Test
+ void testTextBodyIsSentAsUtf8() throws Exception {
+ Message message = sendOne("Grüße");
+
+ assertArrayEquals("Grüße".getBytes(StandardCharsets.UTF_8),
message.payload());
+ }
+
+ @Test
+ void testNoBodyFailsBeforeSending() throws Exception {
+ IggyBaseClient client = newClient();
+
+ try (MockedConstruction<IggyClientFactory> factories =
mockFactories(client);
+ CamelContext context = new DefaultCamelContext()) {
+ context.start();
+ Endpoint endpoint = context.getEndpoint(URI);
+ Producer producer = endpoint.createProducer();
+ producer.start();
+
+ Exchange exchange = endpoint.createExchange();
+ producer.process(exchange);
+
+ assertInstanceOf(InvalidPayloadException.class,
exchange.getException());
+ verify(client.messages(),
never()).sendMessages(any(StreamId.class), any(TopicId.class),
any(Partitioning.class),
+ anyList());
+
+ producer.stop();
+ }
+ }
+
+ @Test
+ void testEmptyListSendsNothing() throws Exception {
+ IggyBaseClient client = newClient();
+
+ try (MockedConstruction<IggyClientFactory> factories =
mockFactories(client);
+ CamelContext context = new DefaultCamelContext()) {
+ context.start();
+ Endpoint endpoint = context.getEndpoint(URI);
+ Producer producer = endpoint.createProducer();
+ producer.start();
+
+ Exchange exchange = endpoint.createExchange();
+ exchange.getIn().setBody(Collections.emptyList());
+ producer.process(exchange);
+
+ assertNull(exchange.getException());
+ verify(client.messages(),
never()).sendMessages(any(StreamId.class), any(TopicId.class),
any(Partitioning.class),
+ anyList());
+
+ producer.stop();
+ }
+ }
+
+ @Test
+ void testListWithNullElementFailsBeforeSending() throws Exception {
+ IggyBaseClient client = newClient();
+
+ try (MockedConstruction<IggyClientFactory> factories =
mockFactories(client);
+ CamelContext context = new DefaultCamelContext()) {
+ context.start();
+ Endpoint endpoint = context.getEndpoint(URI);
+ Producer producer = endpoint.createProducer();
+ producer.start();
+
+ Exchange exchange = endpoint.createExchange();
+ exchange.getIn().setBody(Arrays.asList("Hello", null));
+ producer.process(exchange);
+
+ RuntimeCamelException e =
assertInstanceOf(RuntimeCamelException.class, exchange.getException());
+ assertEquals("The List body must not contain null elements",
e.getMessage());
+ verify(client.messages(),
never()).sendMessages(any(StreamId.class), any(TopicId.class),
any(Partitioning.class),
+ anyList());
+
+ producer.stop();
+ }
+ }
+
+ @Test
+ void testConsumerGivesThePayloadAsBytes() throws Exception {
+ IggyBaseClient client = newClient();
+ MessageHeader header = new MessageHeader(
+ BigInteger.ZERO, MessageId.from(BigInteger.ONE),
BigInteger.ZERO, BigInteger.ZERO, BigInteger.ZERO,
+ 0L, (long) BINARY.length, BigInteger.ZERO);
+ Message message = Message.of(header, BINARY.clone(),
Collections.emptyList());
+ AtomicInteger polls = new AtomicInteger();
+ when(client.messages().pollMessages(any(StreamId.class),
any(TopicId.class), any(), any(), any(), any(),
+ anyBoolean())).thenAnswer(
+ invocation -> polls.incrementAndGet() == 1
+ ? new PolledMessages(0L, BigInteger.ZERO, 1L,
List.of(message))
+ : new PolledMessages(0L, BigInteger.ZERO, 0L,
List.of()));
+
+ AtomicReference<Object> body = new AtomicReference<>();
+ CountDownLatch received = new CountDownLatch(1);
+ try (MockedConstruction<IggyClientFactory> factories =
mockFactories(client);
+ CamelContext context = new DefaultCamelContext()) {
+ context.start();
+ Consumer consumer =
context.getEndpoint(URI).createConsumer(exchange -> {
+ body.set(exchange.getIn().getBody());
+ received.countDown();
+ });
+ consumer.start();
+
+ assertTrue(received.await(30, TimeUnit.SECONDS));
+ byte[] payload = assertInstanceOf(byte[].class, body.get());
+ assertArrayEquals(BINARY, payload);
+
+ consumer.stop();
+ }
+ }
+
+ private Message sendOne(Object body) throws Exception {
+ IggyBaseClient client = newClient();
+ List<Message> sent = new ArrayList<>();
+ ArgumentCaptor<List<Message>> captor = ArgumentCaptor.captor();
+
+ try (MockedConstruction<IggyClientFactory> factories =
mockFactories(client);
+ CamelContext context = new DefaultCamelContext()) {
+ context.start();
+ Endpoint endpoint = context.getEndpoint(URI);
+ Producer producer = endpoint.createProducer();
+ producer.start();
+
+ Exchange exchange = endpoint.createExchange();
+ exchange.getIn().setBody(body);
+ producer.process(exchange);
+
+ assertNull(exchange.getException());
+ verify(client.messages()).sendMessages(any(StreamId.class),
any(TopicId.class), any(Partitioning.class),
+ captor.capture());
+ sent.addAll(captor.getValue());
+
+ producer.stop();
+ }
+ assertEquals(1, sent.size());
+ return sent.get(0);
+ }
+
+ private static IggyBaseClient newClient() {
+ return mock(IggyBaseClient.class,
withSettings().defaultAnswer(RETURNS_DEEP_STUBS));
+ }
+
+ private static MockedConstruction<IggyClientFactory>
mockFactories(IggyBaseClient client) {
+ return mockConstruction(IggyClientFactory.class,
withSettings().defaultAnswer(CALLS_REAL_METHODS),
+ (factory, context) -> doReturn(client).when(factory).create());
+ }
+}
diff --git
a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyTestBase.java
b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyTestBase.java
index e7b0e456f520..e6c3775a2f10 100644
---
a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyTestBase.java
+++
b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyTestBase.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.component.iggy;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@@ -82,11 +83,11 @@ public abstract class IggyTestBase {
}
protected Stream<String>
pollMessagesPayloadsAsStringFromCustomStreamTopic(String stream, String topic) {
- return pollMessages(stream, topic).stream().map(message -> new
String(message.payload()));
+ return pollMessages(stream, topic).stream().map(message -> new
String(message.payload(), StandardCharsets.UTF_8));
}
protected Stream<String> pollMessagesPayloadsAsString() {
- return pollMessages(null, null).stream().map(message -> new
String(message.payload()));
+ return pollMessages(null, null).stream().map(message -> new
String(message.payload(), StandardCharsets.UTF_8));
}
protected List<Message> pollMessages(String stream, String topic) {
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index 793cc1657bd6..14d5cfb179a9 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -1861,6 +1861,18 @@ too early (`messageExpiry=3600` gave 3.6 ms instead of
one hour). The value is n
created before keep their expiry: change it on the Iggy server. If you set
`messageExpiry` in microseconds to work
around this, set it in seconds now, or newly created topics keep their
messages a million times longer than intended.
+=== camel-iggy - binary payloads, and the body of the consumer
+
+The `iggy` producer now sends a `byte[]`, `InputStream`, `ByteBuffer` or file
body as its bytes. Previously it
+converted it to text first, which corrupted a payload that is not valid UTF-8.
Other bodies are still sent as UTF-8
+text. A `null` body now fails with an `InvalidPayloadException`, a `List` body
with a `null` element fails with a clear
+message, and an empty `List` body sends nothing (all three failed inside the
Iggy client before).
+
+The `iggy` consumer now sets the payload as a `byte[]` body. Previously it was
a `String` decoded with the default
+charset of the JVM, which corrupted binary payloads. Camel converts the
`byte[]` to a `String` where a `String` is
+needed, with the charset of the exchange (`CamelCharsetName`) if set, but code
that reads the body with `getBody()`
+and expects a `String` must now use `getBody(String.class)` or add
`convertBodyTo(String.class)` to the route.
+
=== camel-jira - the newIssues consumer reads every new issue
A poll of the `newIssues` consumer read only the newest `maxResults` (default
50) of the issues created since the
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java
index 00a87d5a1b14..39b5b4c8ae5b 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java
@@ -2056,6 +2056,19 @@ public class EndpointHeaderBuilders {
public static
WatsonxDataEndpointBuilderFactory.WatsonxDataHeaderNameBuilder ibmWatsonxData()
{
return
WatsonxDataEndpointBuilderFactory.WatsonxDataHeaderNameBuilder.INSTANCE;
}
+ /**
+ * Iggy (camel-iggy)
+ * Send and receive message to Apache Iggy streaming platform.
+ *
+ * Category: messaging
+ * Since: 4.17
+ * Maven coordinates: org.apache.camel:camel-iggy
+ *
+ * @return the dsl builder for the headers' name.
+ */
+ public static IggyEndpointBuilderFactory.IggyHeaderNameBuilder iggy() {
+ return IggyEndpointBuilderFactory.IggyHeaderNameBuilder.INSTANCE;
+ }
/**
* Ignite Cache (camel-ignite)
* Perform cache operations on an Ignite cache or consume changes from a
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/IggyEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/IggyEndpointBuilderFactory.java
index 6b9a7a2bb1a8..ab2db9544e42 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/IggyEndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/IggyEndpointBuilderFactory.java
@@ -1885,6 +1885,19 @@ public interface IggyEndpointBuilderFactory {
}
public interface IggyBuilders {
+ /**
+ * Iggy (camel-iggy)
+ * Send and receive message to Apache Iggy streaming platform.
+ *
+ * Category: messaging
+ * Since: 4.17
+ * Maven coordinates: org.apache.camel:camel-iggy
+ *
+ * @return the dsl builder for the headers' name.
+ */
+ default IggyHeaderNameBuilder iggy() {
+ return IggyHeaderNameBuilder.INSTANCE;
+ }
/**
* Iggy (camel-iggy)
* Send and receive message to Apache Iggy streaming platform.
@@ -1927,6 +1940,127 @@ public interface IggyEndpointBuilderFactory {
}
}
+ /**
+ * The builder of headers' name for the Iggy component.
+ */
+ public static class IggyHeaderNameBuilder {
+ /**
+ * The internal instance of the builder used to access to all the
+ * methods representing the name of headers.
+ */
+ public static final IggyHeaderNameBuilder INSTANCE = new
IggyHeaderNameBuilder();
+
+ /**
+ * The unique identifier of the message.
+ *
+ * The option is a: {@code org.apache.iggy.message.MessageId} type.
+ *
+ * Group: consumer
+ *
+ * @return the name of the header {@code IggyMessageId}.
+ */
+ public String iggyMessageId() {
+ return "CamelIggyMessageId";
+ }
+ /**
+ * The offset of the message in the partition.
+ *
+ * The option is a: {@code java.math.BigInteger} type.
+ *
+ * Group: consumer
+ *
+ * @return the name of the header {@code IggyMessageOffset}.
+ */
+ public String iggyMessageOffset() {
+ return "CamelIggyMessageOffset";
+ }
+ /**
+ * The timestamp of the message.
+ *
+ * The option is a: {@code java.math.BigInteger} type.
+ *
+ * Group: consumer
+ *
+ * @return the name of the header {@code IggyMessageTimestamp}.
+ */
+ public String iggyMessageTimestamp() {
+ return "CamelIggyMessageTimestamp";
+ }
+ /**
+ * The original timestamp of the message.
+ *
+ * The option is a: {@code java.math.BigInteger} type.
+ *
+ * Group: consumer
+ *
+ * @return the name of the header {@code IggyMessageOriginTimestamp}.
+ */
+ public String iggyMessageOriginTimestamp() {
+ return "CamelIggyMessageOriginTimestamp";
+ }
+ /**
+ * The checksum of the message.
+ *
+ * The option is a: {@code java.math.BigInteger} type.
+ *
+ * Group: consumer
+ *
+ * @return the name of the header {@code IggyMessageChecksum}.
+ */
+ public String iggyMessageChecksum() {
+ return "CamelIggyMessageChecksum";
+ }
+ /**
+ * The length of the payload of the message, in bytes.
+ *
+ * The option is a: {@code Long} type.
+ *
+ * Group: consumer
+ *
+ * @return the name of the header {@code IggyMessageLength}.
+ */
+ public String iggyMessageLength() {
+ return "CamelIggyMessageLength";
+ }
+ /**
+ * The size of the message, in bytes.
+ *
+ * The option is a: {@code int} type.
+ *
+ * Group: consumer
+ *
+ * @return the name of the header {@code IggyMessageSize}.
+ */
+ public String iggyMessageSize() {
+ return "CamelIggyMessageSize";
+ }
+ /**
+ * The name of the topic to send to, instead of the topic of the
+ * endpoint.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code IggyTopicOverride}.
+ */
+ public String iggyTopicOverride() {
+ return "CamelIggyTopicOverride";
+ }
+ /**
+ * The name of the stream to send to, instead of the streamName of the
+ * endpoint.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code IggyStreamOverride}.
+ */
+ public String iggyStreamOverride() {
+ return "CamelIggyStreamOverride";
+ }
+ }
static IggyEndpointBuilder endpointBuilder(String componentName, String
path) {
class IggyEndpointBuilderImpl extends AbstractEndpointBuilder
implements IggyEndpointBuilder, AdvancedIggyEndpointBuilder {
public IggyEndpointBuilderImpl(String path) {