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 af23d08150fd CAMEL-26278: camel-hazelcast - the hazelcast-seda
consumer restores a transferred exchange only with transferExchange=true and
otherwise takes its body (#29310)
af23d08150fd is described below
commit af23d08150fdf60c73d50151e607519e50a54223
Author: Andrea Cosentino <[email protected]>
AuthorDate: Fri Nov 6 10:29:34 2026 +0100
CAMEL-26278: camel-hazelcast - the hazelcast-seda consumer restores a
transferred exchange only with transferExchange=true and otherwise takes its
body (#29310)
Signed-off-by: Andrea Cosentino <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
---
.../camel/catalog/components/hazelcast-seda.json | 4 +-
.../catalog/docs/hazelcast-seda-component.adoc | 27 ++++++++
.../component/hazelcast/seda/hazelcast-seda.json | 4 +-
.../src/main/docs/hazelcast-seda-component.adoc | 27 ++++++++
.../hazelcast/seda/HazelcastSedaConfiguration.java | 3 +-
.../hazelcast/seda/HazelcastSedaConsumer.java | 27 +++++++-
.../hazelcast/seda/HazelcastSedaEndpoint.java | 5 +-
.../HazelcastSedaTransferExchangeTest.java | 80 ++++++++++++++++++++--
.../ROOT/pages/camel-4x-upgrade-guide-4_18.adoc | 11 +++
.../ROOT/pages/camel-4x-upgrade-guide-4_22.adoc | 11 +++
.../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc | 11 +++
.../dsl/HazelcastSedaEndpointBuilderFactory.java | 30 ++++++--
12 files changed, 220 insertions(+), 20 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/hazelcast-seda.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/hazelcast-seda.json
index 7f0eba6c65c0..98b00a8ba165 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/hazelcast-seda.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/hazelcast-seda.json
@@ -31,7 +31,7 @@
"hazelcastMode": { "index": 4, "kind": "property", "displayName":
"Hazelcast Mode", "group": "advanced", "label": "advanced", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": "node", "description":
"The hazelcast mode reference which kind of instance should be used. If you
don't specify the mode, then the node mode will be the default." }
},
"bodyTypes": {
- "consumerOut": { "carriers": [ "text", "bytes", "file", "value", "map",
"list", "pojo" ], "description": "The body the producer put on the Hazelcast
queue, as Hazelcast deserializes it: a body that is not Serializable, such as a
stream, arrives as bytes. With transferExchange=true on the producer the
headers and exchange properties come along" },
+ "consumerOut": { "carriers": [ "text", "bytes", "file", "value", "map",
"list", "pojo" ], "description": "The body the producer put on the Hazelcast
queue, as Hazelcast deserializes it: a body that is not Serializable, such as a
stream, arrives as bytes. With transferExchange=true on both the producer and
the consumer the headers and exchange properties come along: a consumer without
it takes only the body" },
"producerIn": { "carriers": [ "text", "bytes", "stream", "file", "value",
"map", "list", "pojo" ], "description": "A Serializable body goes on the queue
as is, and another one converted to bytes, so a stream works, but a POJO that
does not convert to bytes fails, as does no body" },
"producerOut": { "carriers": [ "unchanged" ], "description": "The producer
puts the message on the queue and does not wait for the consumer, also for a
message that expects a reply (InOut)" }
},
@@ -49,6 +49,6 @@
"onErrorDelay": { "index": 10, "kind": "parameter", "displayName": "On
Error Delay", "group": "seda", "label": "seda", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 1000, "configurationClass":
"org.apache.camel.component.hazelcast.seda.HazelcastSedaConfiguration",
"configurationField": "configuration", "description": "Milliseconds before
consumer continues polling after an error has occurred." },
"pollTimeout": { "index": 11, "kind": "parameter", "displayName": "Poll
Timeout", "group": "seda", "label": "seda", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 1000, "configurationClass":
"org.apache.camel.component.hazelcast.seda.HazelcastSedaConfiguration",
"configurationField": "configuration", "description": "The timeout used when
consuming from the SEDA queue. When a timeout occurs, the consum [...]
"transacted": { "index": 12, "kind": "parameter", "displayName":
"Transacted", "group": "seda", "label": "seda", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.hazelcast.seda.HazelcastSedaConfiguration",
"configurationField": "configuration", "description": "If set to true then the
consumer runs in transaction mode, where the messages in the [...]
- "transferExchange": { "index": 13, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "seda", "label": "seda", "required": false,
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired":
false, "secret": false, "security": "insecure:serialization", "defaultValue":
false, "configurationClass":
"org.apache.camel.component.hazelcast.seda.HazelcastSedaConfiguration",
"configurationField": "configuration", "description": "If set to true the whole
Exchange [...]
+ "transferExchange": { "index": 13, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "seda", "label": "seda", "required": false,
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired":
false, "secret": false, "security": "insecure:serialization", "defaultValue":
false, "configurationClass":
"org.apache.camel.component.hazelcast.seda.HazelcastSedaConfiguration",
"configurationField": "configuration", "description": "If set to true the whole
Exchange [...]
}
}
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/hazelcast-seda-component.adoc
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/hazelcast-seda-component.adoc
index 550d5c0c922f..a84eb7946866 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/hazelcast-seda-component.adoc
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/hazelcast-seda-component.adoc
@@ -101,3 +101,30 @@ YAML::
----
====
+== Transferring the whole exchange
+
+By default only the message body goes on the queue. With
`transferExchange=true` the producer puts the whole exchange
+on the queue: the body, and the headers and exchange properties whose values
are text, numbers, booleans or dates. A
+consumer with `transferExchange=true` restores them. A consumer without the
option takes only the body of such an
+exchange: set `transferExchange=true` on both endpoints to keep the headers
and exchange properties.
+
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:foo
+ steps:
+ - to:
+ uri: hazelcast-seda:foo
+ parameters:
+ transferExchange: true
+- route:
+ from:
+ uri: hazelcast-seda:foo
+ parameters:
+ transferExchange: true
+ steps:
+ - to:
+ uri: mock:result
+----
+
diff --git
a/components/camel-hazelcast/src/generated/resources/META-INF/org/apache/camel/component/hazelcast/seda/hazelcast-seda.json
b/components/camel-hazelcast/src/generated/resources/META-INF/org/apache/camel/component/hazelcast/seda/hazelcast-seda.json
index 7f0eba6c65c0..98b00a8ba165 100644
---
a/components/camel-hazelcast/src/generated/resources/META-INF/org/apache/camel/component/hazelcast/seda/hazelcast-seda.json
+++
b/components/camel-hazelcast/src/generated/resources/META-INF/org/apache/camel/component/hazelcast/seda/hazelcast-seda.json
@@ -31,7 +31,7 @@
"hazelcastMode": { "index": 4, "kind": "property", "displayName":
"Hazelcast Mode", "group": "advanced", "label": "advanced", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": "node", "description":
"The hazelcast mode reference which kind of instance should be used. If you
don't specify the mode, then the node mode will be the default." }
},
"bodyTypes": {
- "consumerOut": { "carriers": [ "text", "bytes", "file", "value", "map",
"list", "pojo" ], "description": "The body the producer put on the Hazelcast
queue, as Hazelcast deserializes it: a body that is not Serializable, such as a
stream, arrives as bytes. With transferExchange=true on the producer the
headers and exchange properties come along" },
+ "consumerOut": { "carriers": [ "text", "bytes", "file", "value", "map",
"list", "pojo" ], "description": "The body the producer put on the Hazelcast
queue, as Hazelcast deserializes it: a body that is not Serializable, such as a
stream, arrives as bytes. With transferExchange=true on both the producer and
the consumer the headers and exchange properties come along: a consumer without
it takes only the body" },
"producerIn": { "carriers": [ "text", "bytes", "stream", "file", "value",
"map", "list", "pojo" ], "description": "A Serializable body goes on the queue
as is, and another one converted to bytes, so a stream works, but a POJO that
does not convert to bytes fails, as does no body" },
"producerOut": { "carriers": [ "unchanged" ], "description": "The producer
puts the message on the queue and does not wait for the consumer, also for a
message that expects a reply (InOut)" }
},
@@ -49,6 +49,6 @@
"onErrorDelay": { "index": 10, "kind": "parameter", "displayName": "On
Error Delay", "group": "seda", "label": "seda", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 1000, "configurationClass":
"org.apache.camel.component.hazelcast.seda.HazelcastSedaConfiguration",
"configurationField": "configuration", "description": "Milliseconds before
consumer continues polling after an error has occurred." },
"pollTimeout": { "index": 11, "kind": "parameter", "displayName": "Poll
Timeout", "group": "seda", "label": "seda", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 1000, "configurationClass":
"org.apache.camel.component.hazelcast.seda.HazelcastSedaConfiguration",
"configurationField": "configuration", "description": "The timeout used when
consuming from the SEDA queue. When a timeout occurs, the consum [...]
"transacted": { "index": 12, "kind": "parameter", "displayName":
"Transacted", "group": "seda", "label": "seda", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.hazelcast.seda.HazelcastSedaConfiguration",
"configurationField": "configuration", "description": "If set to true then the
consumer runs in transaction mode, where the messages in the [...]
- "transferExchange": { "index": 13, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "seda", "label": "seda", "required": false,
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired":
false, "secret": false, "security": "insecure:serialization", "defaultValue":
false, "configurationClass":
"org.apache.camel.component.hazelcast.seda.HazelcastSedaConfiguration",
"configurationField": "configuration", "description": "If set to true the whole
Exchange [...]
+ "transferExchange": { "index": 13, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "seda", "label": "seda", "required": false,
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired":
false, "secret": false, "security": "insecure:serialization", "defaultValue":
false, "configurationClass":
"org.apache.camel.component.hazelcast.seda.HazelcastSedaConfiguration",
"configurationField": "configuration", "description": "If set to true the whole
Exchange [...]
}
}
diff --git
a/components/camel-hazelcast/src/main/docs/hazelcast-seda-component.adoc
b/components/camel-hazelcast/src/main/docs/hazelcast-seda-component.adoc
index 550d5c0c922f..a84eb7946866 100644
--- a/components/camel-hazelcast/src/main/docs/hazelcast-seda-component.adoc
+++ b/components/camel-hazelcast/src/main/docs/hazelcast-seda-component.adoc
@@ -101,3 +101,30 @@ YAML::
----
====
+== Transferring the whole exchange
+
+By default only the message body goes on the queue. With
`transferExchange=true` the producer puts the whole exchange
+on the queue: the body, and the headers and exchange properties whose values
are text, numbers, booleans or dates. A
+consumer with `transferExchange=true` restores them. A consumer without the
option takes only the body of such an
+exchange: set `transferExchange=true` on both endpoints to keep the headers
and exchange properties.
+
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:foo
+ steps:
+ - to:
+ uri: hazelcast-seda:foo
+ parameters:
+ transferExchange: true
+- route:
+ from:
+ uri: hazelcast-seda:foo
+ parameters:
+ transferExchange: true
+ steps:
+ - to:
+ uri: mock:result
+----
+
diff --git
a/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaConfiguration.java
b/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaConfiguration.java
index 9c5be6dcd05d..53cef537ba1d 100644
---
a/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaConfiguration.java
+++
b/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaConfiguration.java
@@ -109,7 +109,8 @@ public class HazelcastSedaConfiguration {
/**
* If set to true the whole Exchange will be transfered. If header or body
contains not serializable objects, they
- * will be skipped.
+ * will be skipped. Set it on both the producer and the consumer: the
producer puts the whole Exchange on the queue,
+ * and the consumer restores its headers and exchange properties. A
consumer without it takes only the body.
*/
public void setTransferExchange(boolean transferExchange) {
this.transferExchange = transferExchange;
diff --git
a/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaConsumer.java
b/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaConsumer.java
index 27e733e1be96..61f504fc936f 100644
---
a/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaConsumer.java
+++
b/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaConsumer.java
@@ -31,6 +31,7 @@ import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.support.AsyncProcessorConverterHelper;
import org.apache.camel.support.DefaultConsumer;
+import org.apache.camel.support.DefaultExchange;
import org.apache.camel.support.DefaultExchangeHolder;
import org.apache.camel.support.task.Tasks;
import org.apache.camel.support.task.budget.Budgets;
@@ -51,6 +52,7 @@ public class HazelcastSedaConsumer extends DefaultConsumer
implements Runnable {
private final AsyncProcessor processor;
private ExecutorService executor;
private ScheduledExecutorService taskExecutor;
+ private volatile boolean transferredExchangeLogged;
public HazelcastSedaConsumer(final Endpoint endpoint, final Processor
processor) {
super(endpoint, processor);
@@ -115,8 +117,8 @@ public class HazelcastSedaConsumer extends DefaultConsumer
implements Runnable {
TimeUnit.MILLISECONDS);
if (body != null) {
- if (body instanceof DefaultExchangeHolder
defaultExchangeHolder) {
- DefaultExchangeHolder.unmarshal(exchange,
defaultExchangeHolder);
+ if (body instanceof DefaultExchangeHolder holder) {
+ takeTransferredExchange(exchange, holder);
} else {
exchange.getIn().setBody(body);
}
@@ -190,6 +192,27 @@ public class HazelcastSedaConsumer extends DefaultConsumer
implements Runnable {
}
}
+ /**
+ * An exchange that a producer with transferExchange=true put on the
queue: the consumer restores its headers and
+ * exchange properties only when it has transferExchange=true as well, and
otherwise takes only its body.
+ */
+ private void takeTransferredExchange(Exchange exchange,
DefaultExchangeHolder holder) {
+ if (endpoint.getConfiguration().isTransferExchange()) {
+ DefaultExchangeHolder.unmarshal(exchange, holder);
+ return;
+ }
+ if (!transferredExchangeLogged) {
+ transferredExchangeLogged = true;
+ LOG.warn("The queue {} holds an exchange that a producer with
transferExchange=true put on it, but this consumer"
+ + " has transferExchange=false: it takes only the body of
such an exchange, without its headers and"
+ + " exchange properties. Set transferExchange=true on the
consumer to restore them.",
+ endpoint.getConfiguration().getQueueName());
+ }
+ Exchange transferred = new DefaultExchange(endpoint.getCamelContext());
+ DefaultExchangeHolder.unmarshal(transferred, holder);
+ exchange.getIn().setBody(transferred.getIn().getBody());
+ }
+
private void onExchangeDone(Exchange exchange, TransactionContext txc) {
// a rollback only exchange (without an exception) did not complete
successfully either
boolean rollback = exchange.getException() != null ||
exchange.isRollbackOnly()
diff --git
a/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaEndpoint.java
b/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaEndpoint.java
index e1ab848af547..1eb975f1ec0f 100644
---
a/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaEndpoint.java
+++
b/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/seda/HazelcastSedaEndpoint.java
@@ -46,8 +46,9 @@ import static
org.apache.camel.component.hazelcast.HazelcastConstants.SCHEME_SED
Carrier.TEXT, Carrier.BYTES, Carrier.FILE, Carrier.VALUE, Carrier.MAP,
Carrier.LIST, Carrier.POJO },
description = "The body the producer put on
the Hazelcast queue, as Hazelcast "
+ "deserializes it: a body
that is not Serializable, such as a "
- + "stream, arrives as bytes.
With transferExchange=true on the "
- + "producer the headers and
exchange properties come along"),
+ + "stream, arrives as bytes.
With transferExchange=true on both the "
+ + "producer and the consumer
the headers and exchange properties "
+ + "come along: a consumer
without it takes only the body"),
producerIn = @BodyType(value = {
Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE,
Carrier.VALUE, Carrier.MAP, Carrier.LIST,
Carrier.POJO },
diff --git
a/components/camel-hazelcast/src/test/java/org/apache/camel/component/hazelcast/HazelcastSedaTransferExchangeTest.java
b/components/camel-hazelcast/src/test/java/org/apache/camel/component/hazelcast/HazelcastSedaTransferExchangeTest.java
index df51b1e44bc6..129d29899c31 100644
---
a/components/camel-hazelcast/src/test/java/org/apache/camel/component/hazelcast/HazelcastSedaTransferExchangeTest.java
+++
b/components/camel-hazelcast/src/test/java/org/apache/camel/component/hazelcast/HazelcastSedaTransferExchangeTest.java
@@ -23,6 +23,7 @@ import org.apache.camel.EndpointInject;
import org.apache.camel.Exchange;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.support.DefaultExchangeHolder;
import org.apache.camel.test.infra.common.TestEntityNameGenerator;
import org.apache.camel.test.infra.hazelcast.services.HazelcastService;
import org.apache.camel.test.infra.hazelcast.services.HazelcastServiceFactory;
@@ -34,6 +35,8 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.extension.RegisterExtension;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class HazelcastSedaTransferExchangeTest extends CamelTestSupport {
@@ -46,6 +49,12 @@ public class HazelcastSedaTransferExchangeTest extends
CamelTestSupport {
@EndpointInject("mock:result")
private MockEndpoint mock;
+ @EndpointInject("mock:transferred")
+ private MockEndpoint transferred;
+
+ @EndpointInject("mock:bodyOnly")
+ private MockEndpoint bodyOnly;
+
private HazelcastInstance hazelcastInstance;
@BeforeAll
@@ -56,6 +65,8 @@ public class HazelcastSedaTransferExchangeTest extends
CamelTestSupport {
@AfterEach
public void afterEach() {
mock.reset();
+ transferred.reset();
+ bodyOnly.reset();
}
@AfterAll
@@ -69,18 +80,69 @@ public class HazelcastSedaTransferExchangeTest extends
CamelTestSupport {
public void testExchangeTransferEnabled() throws InterruptedException {
final String value = "CAMEL-3983";
- mock.expectedMessageCount(1);
- mock.expectedBodiesReceived("test");
- mock.expectedHeaderReceived("test", value);
+ transferred.expectedMessageCount(1);
+ transferred.expectedBodiesReceived("test");
+ transferred.expectedHeaderReceived("test", value);
+ transferred.expectedPropertyReceived("test", value);
Exchange exchange = createExchangeWithBody("test");
exchange.getIn().setHeader("test", value);
+ exchange.setProperty("test", value);
template.send("direct:foobar", exchange);
MockEndpoint.assertIsSatisfied(context);
}
+ @Test
+ void
transferredExchangeGivesOnlyItsBodyToAConsumerWithoutTransferExchange() throws
InterruptedException {
+ bodyOnly.expectedMessageCount(1);
+ bodyOnly.expectedBodiesReceived("test");
+ bodyOnly.expectedNoHeaderReceived();
+
+ Exchange exchange = createExchangeWithBody("test");
+ exchange.getIn().setHeader("test", "Not propagated");
+ exchange.setProperty("test", "Not propagated");
+
+ template.send("direct:bodyOnly", exchange);
+
+ MockEndpoint.assertIsSatisfied(context);
+ assertNull(bodyOnly.getReceivedExchanges().get(0).getProperty("test"));
+ }
+
+ @Test
+ void holderOnTheQueueGivesOnlyItsBodyWithoutTransferExchange() throws
InterruptedException {
+ bodyOnly.expectedMessageCount(1);
+ bodyOnly.expectedBodiesReceived("held");
+ bodyOnly.expectedNoHeaderReceived();
+
+ hazelcastInstance.getQueue("body-only").add(holder("held"));
+
+ MockEndpoint.assertIsSatisfied(context);
+ Exchange received = bodyOnly.getReceivedExchanges().get(0);
+ assertNull(received.getProperty("test"));
+ assertNull(received.getException());
+ }
+
+ @Test
+ void holderOnTheQueueGivesItsHeadersAndPropertiesWithTransferExchange()
throws InterruptedException {
+ transferred.expectedMessageCount(1);
+ transferred.expectedBodiesReceived("held");
+ transferred.expectedHeaderReceived("test", "held header");
+ transferred.expectedPropertyReceived("test", "held property");
+
+ hazelcastInstance.getQueue("transferred").add(holder("held"));
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ private DefaultExchangeHolder holder(String body) {
+ Exchange exchange = createExchangeWithBody(body);
+ exchange.getIn().setHeader("test", "held header");
+ exchange.setProperty("test", "held property");
+ return DefaultExchangeHolder.marshal(exchange);
+ }
+
@Test
public void testExchangeTransferDisabled() throws InterruptedException {
mock.expectedMessageCount(1);
@@ -110,9 +172,17 @@ public class HazelcastSedaTransferExchangeTest extends
CamelTestSupport {
public void configure() {
from("direct:foo").to("hazelcast-seda:foo");
-
from("direct:foobar").to("hazelcast-seda:foo?transferExchange=true");
-
from("hazelcast-seda:foo").to("mock:result");
+
+ // transferExchange on both sides: the headers and exchange
properties come along
+
from("direct:foobar").to("hazelcast-seda:transferred?transferExchange=true");
+
+
from("hazelcast-seda:transferred?transferExchange=true").to("mock:transferred");
+
+ // transferExchange only on the producer: the consumer takes
only the body
+
from("direct:bodyOnly").to("hazelcast-seda:body-only?transferExchange=true");
+
+ from("hazelcast-seda:body-only").to("mock:bodyOnly");
}
};
}
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
index 07b80d388019..a1fcefc37f1b 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
@@ -72,6 +72,17 @@ Checkpoint failures from the timer are now logged at `WARN`
level with the full
at `DEBUG` level with the message only. Checkpoint failures triggered by batch
size are still logged at
`WARN`.
+=== camel-hazelcast - the hazelcast-seda consumer restores a transferred
exchange only with transferExchange=true
+
+A `hazelcast-seda` consumer now restores the headers and exchange properties
of an exchange that a producer with
+`transferExchange=true` put on the queue only when the consumer has
`transferExchange=true` as well. A consumer without
+the option, the default, now takes only the body of such an exchange, as it
does for any other item of the queue, and
+logs a warning the first time. Before, the consumer restored the headers and
exchange properties whatever its
+`transferExchange` option said.
+
+Set `transferExchange=true` on both the producer and the consumer endpoints to
keep transferring the headers and
+exchange properties.
+
=== camel-lra - only an LRA hosted by the configured coordinator is joined
The LRA saga service now joins, completes or compensates an LRA only when its
URL is under the configured LRA
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
index 4c8a35dc8da5..51be81c771df 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
@@ -70,6 +70,17 @@ scheduled time of its window, but before the (late) timer
has run, joins that wi
checkpointed by that timer. Before, such an event always started a new window,
so `timeout` was practically never
set. Routes that read this header can now see `timeout` as well as `size`.
+=== camel-hazelcast - the hazelcast-seda consumer restores a transferred
exchange only with transferExchange=true
+
+A `hazelcast-seda` consumer now restores the headers and exchange properties
of an exchange that a producer with
+`transferExchange=true` put on the queue only when the consumer has
`transferExchange=true` as well. A consumer without
+the option, the default, now takes only the body of such an exchange, as it
does for any other item of the queue, and
+logs a warning the first time. Before, the consumer restored the headers and
exchange properties whatever its
+`transferExchange` option said.
+
+Set `transferExchange=true` on both the producer and the consumer endpoints to
keep transferring the headers and
+exchange properties.
+
=== camel-milo - the OPC UA client validates the server certificate
When the endpoint it selects uses a security policy other than `None`, the
`milo-client` and `milo-browse` components
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 7fdfc73bea93..4ff53d3c933a 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
@@ -6282,6 +6282,17 @@ Previously the newest message was left out.
The `stream:header` producer now fails with a `NoSuchHeaderException` when the
`stream` header is missing or is not an
`OutputStream`. Previously it failed with a `NullPointerException`, or did
nothing when the body was null.
+=== camel-hazelcast - the hazelcast-seda consumer restores a transferred
exchange only with transferExchange=true
+
+A `hazelcast-seda` consumer now restores the headers and exchange properties
of an exchange that a producer with
+`transferExchange=true` put on the queue only when the consumer has
`transferExchange=true` as well. A consumer without
+the option, the default, now takes only the body of such an exchange, as it
does for any other item of the queue, and
+logs a warning the first time. Before, the consumer restored the headers and
exchange properties whatever its
+`transferExchange` option said.
+
+Set `transferExchange=true` on both the producer and the consumer endpoints to
keep transferring the headers and
+exchange properties.
+
=== camel-knative - a structured CloudEvent whose Content-Type has parameters
The consumer now finds the content mode of a CloudEvent by the media type of
the `Content-Type` header, ignoring its
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/HazelcastSedaEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/HazelcastSedaEndpointBuilderFactory.java
index 75ae9dc56bd9..1e4f9b50b648 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/HazelcastSedaEndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/HazelcastSedaEndpointBuilderFactory.java
@@ -289,7 +289,10 @@ public interface HazelcastSedaEndpointBuilderFactory {
}
/**
* If set to true the whole Exchange will be transfered. If header or
- * body contains not serializable objects, they will be skipped.
+ * body contains not serializable objects, they will be skipped. Set it
+ * on both the producer and the consumer: the producer puts the whole
+ * Exchange on the queue, and the consumer restores its headers and
+ * exchange properties. A consumer without it takes only the body.
*
* The option is a: <code>boolean</code> type.
*
@@ -305,7 +308,10 @@ public interface HazelcastSedaEndpointBuilderFactory {
}
/**
* If set to true the whole Exchange will be transfered. If header or
- * body contains not serializable objects, they will be skipped.
+ * body contains not serializable objects, they will be skipped. Set it
+ * on both the producer and the consumer: the producer puts the whole
+ * Exchange on the queue, and the consumer restores its headers and
+ * exchange properties. A consumer without it takes only the body.
*
* The option will be converted to a <code>boolean</code> type.
*
@@ -704,7 +710,10 @@ public interface HazelcastSedaEndpointBuilderFactory {
}
/**
* If set to true the whole Exchange will be transfered. If header or
- * body contains not serializable objects, they will be skipped.
+ * body contains not serializable objects, they will be skipped. Set it
+ * on both the producer and the consumer: the producer puts the whole
+ * Exchange on the queue, and the consumer restores its headers and
+ * exchange properties. A consumer without it takes only the body.
*
* The option is a: <code>boolean</code> type.
*
@@ -720,7 +729,10 @@ public interface HazelcastSedaEndpointBuilderFactory {
}
/**
* If set to true the whole Exchange will be transfered. If header or
- * body contains not serializable objects, they will be skipped.
+ * body contains not serializable objects, they will be skipped. Set it
+ * on both the producer and the consumer: the producer puts the whole
+ * Exchange on the queue, and the consumer restores its headers and
+ * exchange properties. A consumer without it takes only the body.
*
* The option will be converted to a <code>boolean</code> type.
*
@@ -1048,7 +1060,10 @@ public interface HazelcastSedaEndpointBuilderFactory {
}
/**
* If set to true the whole Exchange will be transfered. If header or
- * body contains not serializable objects, they will be skipped.
+ * body contains not serializable objects, they will be skipped. Set it
+ * on both the producer and the consumer: the producer puts the whole
+ * Exchange on the queue, and the consumer restores its headers and
+ * exchange properties. A consumer without it takes only the body.
*
* The option is a: <code>boolean</code> type.
*
@@ -1064,7 +1079,10 @@ public interface HazelcastSedaEndpointBuilderFactory {
}
/**
* If set to true the whole Exchange will be transfered. If header or
- * body contains not serializable objects, they will be skipped.
+ * body contains not serializable objects, they will be skipped. Set it
+ * on both the producer and the consumer: the producer puts the whole
+ * Exchange on the queue, and the consumer restores its headers and
+ * exchange properties. A consumer without it takes only the body.
*
* The option will be converted to a <code>boolean</code> type.
*