This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.22.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.22.x by this push:
new bb264cbb676b [backport camel-4.22.x] CAMEL-26508: camel-netty - with
transferExchange the consumer keeps its own connection headers (#29053)
bb264cbb676b is described below
commit bb264cbb676b24413f387dccd080130be90c3d9b
Author: Guillaume Nodet <[email protected]>
AuthorDate: Wed Nov 4 09:20:24 2026 +0100
[backport camel-4.22.x] CAMEL-26508: camel-netty - with transferExchange
the consumer keeps its own connection headers (#29053)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
.../camel/catalog/components/netty-http.json | 4 +-
.../org/apache/camel/catalog/components/netty.json | 4 +-
.../camel/component/netty/http/netty-http.json | 4 +-
.../org/apache/camel/component/netty/netty.json | 4 +-
.../camel/component/netty/NettyConfiguration.java | 11 +-
.../camel/component/netty/NettyPayloadHelper.java | 53 ++++++-
...NettyTransferExchangeConnectionHeadersTest.java | 157 +++++++++++++++++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_22.adoc | 10 ++
.../dsl/NettyComponentBuilderFactory.java | 8 +-
.../dsl/NettyHttpComponentBuilderFactory.java | 8 +-
.../endpoint/dsl/NettyEndpointBuilderFactory.java | 48 ++++++-
.../dsl/NettyHttpEndpointBuilderFactory.java | 48 ++++++-
12 files changed, 331 insertions(+), 28 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/netty-http.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/netty-http.json
index 7961051ea48f..f3c5469436b8 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/netty-http.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/netty-http.json
@@ -77,7 +77,7 @@
"receiveBufferSizePredictor": { "index": 49, "kind": "property",
"displayName": "Receive Buffer Size Predictor", "group": "advanced", "label":
"advanced", "required": false, "type": "integer", "javaType": "int",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Configures the buffer size predictor. See
details at Jetty documentation and this mail [...]
"sendBufferSize": { "index": 50, "kind": "property", "displayName": "Send
Buffer Size", "group": "advanced", "label": "advanced", "required": false,
"type": "integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 65536, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "The TCP\/UDP buffer sizes to be used during
outbound communication. Size is bytes." },
"shutdownTimeout": { "index": 51, "kind": "property", "displayName":
"Shutdown Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": 100, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Shutdown await timeout in milliseconds" },
- "transferExchange": { "index": 52, "kind": "property", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the exc
[...]
+ "transferExchange": { "index": 52, "kind": "property", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the exc
[...]
"udpByteArrayCodec": { "index": 53, "kind": "property", "displayName":
"Udp Byte Array Codec", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false,
"configurationClass": "org.apache.camel.component.netty.NettyConfiguration",
"configurationField": "configuration", "description": "For UDP only. If enabled
the using byte array codec instead of Java serializa [...]
"unixDomainSocketPath": { "index": 54, "kind": "property", "displayName":
"Unix Domain Socket Path", "group": "advanced", "label": "advanced",
"required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Path to unix domain socket to use instead of
inet socket. Host and port parameters wil [...]
"workerCount": { "index": 55, "kind": "property", "displayName": "Worker
Count", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "When netty works on nio mode, it uses default
workerCount parameter from Netty (which is cpu_core_threads x 2). User c [...]
@@ -200,7 +200,7 @@
"shutdownTimeout": { "index": 65, "kind": "parameter", "displayName":
"Shutdown Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": 100, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "Shutdown await timeout
in milliseconds" },
"synchronous": { "index": 66, "kind": "parameter", "displayName":
"Synchronous", "group": "advanced", "label": "advanced", "required": false,
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "Sets whether synchronous
processing should be strictly used" },
"transferException": { "index": 67, "kind": "parameter", "displayName":
"Transfer Exception", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "If enabled and an
Exchange fail [...]
- "transferExchange": { "index": 68, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "Only used for TCP. You
can transf [...]
+ "transferExchange": { "index": 68, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "Only used for TCP. You
can transf [...]
"unixDomainSocketPath": { "index": 69, "kind": "parameter", "displayName":
"Unix Domain Socket Path", "group": "advanced", "label": "advanced",
"required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "Path to unix domain
socket to use instead of inet socket. Host and port para [...]
"workerCount": { "index": 70, "kind": "parameter", "displayName": "Worker
Count", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "When netty works on nio
mode, it uses default workerCount parameter from Netty (which is
cpu_core_threads x [...]
"workerGroup": { "index": 71, "kind": "parameter", "displayName": "Worker
Group", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "io.netty.channel.EventLoopGroup", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "To use a explicit
EventLoopGroup as the boss thread pool. For example to share a [...]
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/netty.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/netty.json
index 29c97da19505..77cb5c4988b9 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/netty.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/netty.json
@@ -73,7 +73,7 @@
"receiveBufferSizePredictor": { "index": 46, "kind": "property",
"displayName": "Receive Buffer Size Predictor", "group": "advanced", "label":
"advanced", "required": false, "type": "integer", "javaType": "int",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Configures the buffer size predictor. See
details at Jetty documentation and this mail [...]
"sendBufferSize": { "index": 47, "kind": "property", "displayName": "Send
Buffer Size", "group": "advanced", "label": "advanced", "required": false,
"type": "integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 65536, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "The TCP\/UDP buffer sizes to be used during
outbound communication. Size is bytes." },
"shutdownTimeout": { "index": 48, "kind": "property", "displayName":
"Shutdown Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": 100, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Shutdown await timeout in milliseconds" },
- "transferExchange": { "index": 49, "kind": "property", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the exc
[...]
+ "transferExchange": { "index": 49, "kind": "property", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the exc
[...]
"udpByteArrayCodec": { "index": 50, "kind": "property", "displayName":
"Udp Byte Array Codec", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false,
"configurationClass": "org.apache.camel.component.netty.NettyConfiguration",
"configurationField": "configuration", "description": "For UDP only. If enabled
the using byte array codec instead of Java serializa [...]
"unixDomainSocketPath": { "index": 51, "kind": "property", "displayName":
"Unix Domain Socket Path", "group": "advanced", "label": "advanced",
"required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Path to unix domain socket to use instead of
inet socket. Host and port parameters wil [...]
"workerCount": { "index": 52, "kind": "property", "displayName": "Worker
Count", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "When netty works on nio mode, it uses default
workerCount parameter from Netty (which is cpu_core_threads x 2). User c [...]
@@ -166,7 +166,7 @@
"sendBufferSize": { "index": 48, "kind": "parameter", "displayName": "Send
Buffer Size", "group": "advanced", "label": "advanced", "required": false,
"type": "integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 65536, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "The TCP\/UDP buffer sizes to be used during
outbound communication. Size is bytes." },
"shutdownTimeout": { "index": 49, "kind": "parameter", "displayName":
"Shutdown Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": 100, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Shutdown await timeout in milliseconds" },
"synchronous": { "index": 50, "kind": "parameter", "displayName":
"Synchronous", "group": "advanced", "label": "advanced", "required": false,
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": false, "description": "Sets whether
synchronous processing should be strictly used" },
- "transferExchange": { "index": 51, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the ex
[...]
+ "transferExchange": { "index": 51, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the ex
[...]
"udpByteArrayCodec": { "index": 52, "kind": "parameter", "displayName":
"Udp Byte Array Codec", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false,
"configurationClass": "org.apache.camel.component.netty.NettyConfiguration",
"configurationField": "configuration", "description": "For UDP only. If enabled
the using byte array codec instead of Java serializ [...]
"unixDomainSocketPath": { "index": 53, "kind": "parameter", "displayName":
"Unix Domain Socket Path", "group": "advanced", "label": "advanced",
"required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Path to unix domain socket to use instead of
inet socket. Host and port parameters wi [...]
"workerCount": { "index": 54, "kind": "parameter", "displayName": "Worker
Count", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "When netty works on nio mode, it uses default
workerCount parameter from Netty (which is cpu_core_threads x 2). User [...]
diff --git
a/components/camel-netty-http/src/generated/resources/META-INF/org/apache/camel/component/netty/http/netty-http.json
b/components/camel-netty-http/src/generated/resources/META-INF/org/apache/camel/component/netty/http/netty-http.json
index 7961051ea48f..f3c5469436b8 100644
---
a/components/camel-netty-http/src/generated/resources/META-INF/org/apache/camel/component/netty/http/netty-http.json
+++
b/components/camel-netty-http/src/generated/resources/META-INF/org/apache/camel/component/netty/http/netty-http.json
@@ -77,7 +77,7 @@
"receiveBufferSizePredictor": { "index": 49, "kind": "property",
"displayName": "Receive Buffer Size Predictor", "group": "advanced", "label":
"advanced", "required": false, "type": "integer", "javaType": "int",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Configures the buffer size predictor. See
details at Jetty documentation and this mail [...]
"sendBufferSize": { "index": 50, "kind": "property", "displayName": "Send
Buffer Size", "group": "advanced", "label": "advanced", "required": false,
"type": "integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 65536, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "The TCP\/UDP buffer sizes to be used during
outbound communication. Size is bytes." },
"shutdownTimeout": { "index": 51, "kind": "property", "displayName":
"Shutdown Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": 100, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Shutdown await timeout in milliseconds" },
- "transferExchange": { "index": 52, "kind": "property", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the exc
[...]
+ "transferExchange": { "index": 52, "kind": "property", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the exc
[...]
"udpByteArrayCodec": { "index": 53, "kind": "property", "displayName":
"Udp Byte Array Codec", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false,
"configurationClass": "org.apache.camel.component.netty.NettyConfiguration",
"configurationField": "configuration", "description": "For UDP only. If enabled
the using byte array codec instead of Java serializa [...]
"unixDomainSocketPath": { "index": 54, "kind": "property", "displayName":
"Unix Domain Socket Path", "group": "advanced", "label": "advanced",
"required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Path to unix domain socket to use instead of
inet socket. Host and port parameters wil [...]
"workerCount": { "index": 55, "kind": "property", "displayName": "Worker
Count", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "When netty works on nio mode, it uses default
workerCount parameter from Netty (which is cpu_core_threads x 2). User c [...]
@@ -200,7 +200,7 @@
"shutdownTimeout": { "index": 65, "kind": "parameter", "displayName":
"Shutdown Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": 100, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "Shutdown await timeout
in milliseconds" },
"synchronous": { "index": 66, "kind": "parameter", "displayName":
"Synchronous", "group": "advanced", "label": "advanced", "required": false,
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "Sets whether synchronous
processing should be strictly used" },
"transferException": { "index": 67, "kind": "parameter", "displayName":
"Transfer Exception", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "If enabled and an
Exchange fail [...]
- "transferExchange": { "index": 68, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "Only used for TCP. You
can transf [...]
+ "transferExchange": { "index": 68, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "Only used for TCP. You
can transf [...]
"unixDomainSocketPath": { "index": 69, "kind": "parameter", "displayName":
"Unix Domain Socket Path", "group": "advanced", "label": "advanced",
"required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "Path to unix domain
socket to use instead of inet socket. Host and port para [...]
"workerCount": { "index": 70, "kind": "parameter", "displayName": "Worker
Count", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "When netty works on nio
mode, it uses default workerCount parameter from Netty (which is
cpu_core_threads x [...]
"workerGroup": { "index": 71, "kind": "parameter", "displayName": "Worker
Group", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "io.netty.channel.EventLoopGroup", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.http.NettyHttpConfiguration",
"configurationField": "configuration", "description": "To use a explicit
EventLoopGroup as the boss thread pool. For example to share a [...]
diff --git
a/components/camel-netty/src/generated/resources/META-INF/org/apache/camel/component/netty/netty.json
b/components/camel-netty/src/generated/resources/META-INF/org/apache/camel/component/netty/netty.json
index 29c97da19505..77cb5c4988b9 100644
---
a/components/camel-netty/src/generated/resources/META-INF/org/apache/camel/component/netty/netty.json
+++
b/components/camel-netty/src/generated/resources/META-INF/org/apache/camel/component/netty/netty.json
@@ -73,7 +73,7 @@
"receiveBufferSizePredictor": { "index": 46, "kind": "property",
"displayName": "Receive Buffer Size Predictor", "group": "advanced", "label":
"advanced", "required": false, "type": "integer", "javaType": "int",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Configures the buffer size predictor. See
details at Jetty documentation and this mail [...]
"sendBufferSize": { "index": 47, "kind": "property", "displayName": "Send
Buffer Size", "group": "advanced", "label": "advanced", "required": false,
"type": "integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 65536, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "The TCP\/UDP buffer sizes to be used during
outbound communication. Size is bytes." },
"shutdownTimeout": { "index": 48, "kind": "property", "displayName":
"Shutdown Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": 100, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Shutdown await timeout in milliseconds" },
- "transferExchange": { "index": 49, "kind": "property", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the exc
[...]
+ "transferExchange": { "index": 49, "kind": "property", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the exc
[...]
"udpByteArrayCodec": { "index": 50, "kind": "property", "displayName":
"Udp Byte Array Codec", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false,
"configurationClass": "org.apache.camel.component.netty.NettyConfiguration",
"configurationField": "configuration", "description": "For UDP only. If enabled
the using byte array codec instead of Java serializa [...]
"unixDomainSocketPath": { "index": 51, "kind": "property", "displayName":
"Unix Domain Socket Path", "group": "advanced", "label": "advanced",
"required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Path to unix domain socket to use instead of
inet socket. Host and port parameters wil [...]
"workerCount": { "index": 52, "kind": "property", "displayName": "Worker
Count", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "When netty works on nio mode, it uses default
workerCount parameter from Netty (which is cpu_core_threads x 2). User c [...]
@@ -166,7 +166,7 @@
"sendBufferSize": { "index": 48, "kind": "parameter", "displayName": "Send
Buffer Size", "group": "advanced", "label": "advanced", "required": false,
"type": "integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": 65536, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "The TCP\/UDP buffer sizes to be used during
outbound communication. Size is bytes." },
"shutdownTimeout": { "index": 49, "kind": "parameter", "displayName":
"Shutdown Timeout", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": 100, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Shutdown await timeout in milliseconds" },
"synchronous": { "index": 50, "kind": "parameter", "displayName":
"Synchronous", "group": "advanced", "label": "advanced", "required": false,
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired":
false, "secret": false, "defaultValue": false, "description": "Sets whether
synchronous processing should be strictly used" },
- "transferExchange": { "index": 51, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the ex
[...]
+ "transferExchange": { "index": 51, "kind": "parameter", "displayName":
"Transfer Exchange", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "security": "insecure:serialization",
"defaultValue": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Only used for TCP. You can transfer the ex
[...]
"udpByteArrayCodec": { "index": 52, "kind": "parameter", "displayName":
"Udp Byte Array Codec", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": false,
"configurationClass": "org.apache.camel.component.netty.NettyConfiguration",
"configurationField": "configuration", "description": "For UDP only. If enabled
the using byte array codec instead of Java serializ [...]
"unixDomainSocketPath": { "index": 53, "kind": "parameter", "displayName":
"Unix Domain Socket Path", "group": "advanced", "label": "advanced",
"required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "Path to unix domain socket to use instead of
inet socket. Host and port parameters wi [...]
"workerCount": { "index": 54, "kind": "parameter", "displayName": "Worker
Count", "group": "advanced", "label": "advanced", "required": false, "type":
"integer", "javaType": "int", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.netty.NettyConfiguration", "configurationField":
"configuration", "description": "When netty works on nio mode, it uses default
workerCount parameter from Netty (which is cpu_core_threads x 2). User [...]
diff --git
a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConfiguration.java
b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConfiguration.java
index 78a2cbd99f46..10b8290bcc72 100644
---
a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConfiguration.java
+++
b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConfiguration.java
@@ -96,7 +96,11 @@ public class NettyConfiguration extends
NettyServerBootstrapConfiguration implem
description = "Only used for TCP. You can transfer the exchange
over the wire instead of just the body. The following fields are"
+ " transferred: In body, Out body, fault body, In
headers, Out headers, fault headers, exchange properties, exchange"
+ " exception. This requires that the objects are
serializable. Camel will exclude any non-serializable objects and"
- + " log it at WARN level.")
+ + " log it at WARN level. The connection headers
(CamelNettyRemoteAddress, CamelNettyLocalAddress,"
+ + " CamelNettyChannelHandlerContext,
CamelNettySSLSession and the CamelNettySSLClientCert headers) and the"
+ + " CamelNettyRemoteAddress and CamelNettyChannel
exchange properties are always the ones of the receiving"
+ + " side: the connection it accepted is the source
of truth, and these values are never taken from the"
+ + " transferred exchange.")
private boolean transferExchange;
@UriParam(label = "advanced", security = "insecure:serialization",
description = "Only used for TCP when transferExchange is true.
When set to true, serializable objects in headers and properties"
@@ -567,7 +571,10 @@ public class NettyConfiguration extends
NettyServerBootstrapConfiguration implem
* Only used for TCP. You can transfer the exchange over the wire instead
of just the body. The following fields are
* transferred: In body, Out body, fault body, In headers, Out headers,
fault headers, exchange properties, exchange
* exception. This requires that the objects are serializable. Camel will
exclude any non-serializable objects and
- * log it at WARN level.
+ * log it at WARN level. The connection headers (CamelNettyRemoteAddress,
CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
CamelNettySSLClientCert headers) and the
+ * CamelNettyRemoteAddress and CamelNettyChannel exchange properties are
always the ones of the receiving side: the
+ * connection it accepted is the source of truth, and these values are
never taken from the transferred exchange.
*/
public void setTransferExchange(boolean transferExchange) {
this.transferExchange = transferExchange;
diff --git
a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyPayloadHelper.java
b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyPayloadHelper.java
index d09c5d8ae4d5..5dfddf03c45d 100644
---
a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyPayloadHelper.java
+++
b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyPayloadHelper.java
@@ -17,6 +17,8 @@
package org.apache.camel.component.netty;
import java.net.InetSocketAddress;
+import java.util.HashMap;
+import java.util.Map;
import io.netty.buffer.ByteBuf;
import io.netty.channel.AddressedEnvelope;
@@ -63,13 +65,13 @@ public final class NettyPayloadHelper {
public static void setIn(Exchange exchange, Object payload) {
if (payload instanceof DefaultExchangeHolder defaultExchangeHolder) {
- DefaultExchangeHolder.unmarshal(exchange, defaultExchangeHolder);
+ unmarshal(exchange, defaultExchangeHolder);
} else if (payload instanceof AddressedEnvelope) {
@SuppressWarnings("unchecked")
AddressedEnvelope<Object, InetSocketAddress> dp =
(AddressedEnvelope<Object, InetSocketAddress>) payload;
// need to check if the content is ExchangeHolder
if (dp.content() instanceof DefaultExchangeHolder
defaultExchangeHolder) {
- DefaultExchangeHolder.unmarshal(exchange,
defaultExchangeHolder);
+ unmarshal(exchange, defaultExchangeHolder);
} else {
// need to take out the payload here
exchange.getIn().setBody(dp.content());
@@ -86,13 +88,13 @@ public final class NettyPayloadHelper {
public static void setOut(Exchange exchange, Object payload) {
if (payload instanceof DefaultExchangeHolder defaultExchangeHolder) {
- DefaultExchangeHolder.unmarshal(exchange, defaultExchangeHolder);
+ unmarshal(exchange, defaultExchangeHolder);
} else if (payload instanceof AddressedEnvelope) {
@SuppressWarnings("unchecked")
AddressedEnvelope<Object, InetSocketAddress> dp =
(AddressedEnvelope<Object, InetSocketAddress>) payload;
// need to check if the content is ExchangeHolder
if (dp.content() instanceof DefaultExchangeHolder
defaultExchangeHolder) {
- DefaultExchangeHolder.unmarshal(exchange,
defaultExchangeHolder);
+ unmarshal(exchange, defaultExchangeHolder);
} else {
// need to take out the payload here
exchange.getOut().setBody(dp.content());
@@ -106,4 +108,47 @@ public final class NettyPayloadHelper {
}
}
+ /**
+ * The headers and exchange properties that describe the Netty connection
of this side.
+ */
+ private static final String[] CONNECTION_KEYS = {
+ NettyConstants.NETTY_CHANNEL_HANDLER_CONTEXT,
NettyConstants.NETTY_REMOTE_ADDRESS,
+ NettyConstants.NETTY_LOCAL_ADDRESS, NettyConstants.NETTY_CHANNEL,
+ NettyConstants.NETTY_SSL_SESSION,
NettyConstants.NETTY_SSL_CLIENT_CERT_SUBJECT_NAME,
+ NettyConstants.NETTY_SSL_CLIENT_CERT_ISSUER_NAME,
NettyConstants.NETTY_SSL_CLIENT_CERT_SERIAL_NO,
+ NettyConstants.NETTY_SSL_CLIENT_CERT_NOT_BEFORE,
NettyConstants.NETTY_SSL_CLIENT_CERT_NOT_AFTER };
+
+ /**
+ * Unmarshals the transferred exchange into the exchange, but keeps the
connection headers and exchange properties
+ * of this side: the connection this side accepted (or opened) is the
source of truth for them. A connection header
+ * or property in the transferred exchange is never used, also when this
side has no value for it (for example the
+ * SSL client certificate headers when the connection has no client
certificate).
+ */
+ private static void unmarshal(Exchange exchange, DefaultExchangeHolder
holder) {
+ Map<String, Object> headers = new HashMap<>();
+ Map<String, Object> properties = new HashMap<>();
+ for (String key : CONNECTION_KEYS) {
+ Object value = exchange.getIn().getHeader(key);
+ if (value != null) {
+ headers.put(key, value);
+ }
+ value = exchange.getProperty(key);
+ if (value != null) {
+ properties.put(key, value);
+ }
+ }
+
+ DefaultExchangeHolder.unmarshal(exchange, holder);
+
+ for (String key : CONNECTION_KEYS) {
+ exchange.getIn().removeHeader(key);
+ if (exchange.hasOut()) {
+ exchange.getOut().removeHeader(key);
+ }
+ exchange.removeProperty(key);
+ }
+ headers.forEach(exchange.getIn()::setHeader);
+ properties.forEach(exchange::setProperty);
+ }
+
}
diff --git
a/components/camel-netty/src/test/java/org/apache/camel/component/netty/NettyTransferExchangeConnectionHeadersTest.java
b/components/camel-netty/src/test/java/org/apache/camel/component/netty/NettyTransferExchangeConnectionHeadersTest.java
new file mode 100644
index 000000000000..360185c2913f
--- /dev/null
+++
b/components/camel-netty/src/test/java/org/apache/camel/component/netty/NettyTransferExchangeConnectionHeadersTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.netty;
+
+import java.io.File;
+import java.net.InetSocketAddress;
+
+import io.netty.channel.ChannelHandler;
+import io.netty.handler.codec.serialization.ClassResolvers;
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.netty.codec.ObjectDecoder;
+import org.apache.camel.component.netty.codec.ObjectEncoder;
+import org.apache.camel.test.AvailablePortFinder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+/**
+ * With transferExchange the consumer keeps its own connection headers: the
connection it accepted is the source of
+ * truth, so the connection headers and properties in the transferred exchange
are not used.
+ */
+@DisabledIfSystemProperty(named = "java.vendor", matches = ".*ibm.*")
+public class NettyTransferExchangeConnectionHeadersTest extends BaseNettyTest {
+
+ private static final String CLIENT_CERT_SUBJECT
+ = "SERIALNUMBER=1234567890, CN=CommonName, OU=Unit, O=Org, L=Loc,
ST=State, C=US";
+ private static final String CODECS =
"&encoders=#encoder&decoders=#decoder";
+ private static final String SSL_OPTIONS =
"&ssl=true&passphrase=changeit&keyStoreResource=#ksf&trustStoreResource=#tsf";
+
+ @RegisterExtension
+ AvailablePortFinder.Port sslPort = AvailablePortFinder.find();
+
+ @BindToRegistry("ksf")
+ public File loadKeystoreKsf() {
+ return new File("src/test/resources/keystore.jks");
+ }
+
+ @BindToRegistry("tsf")
+ public File loadKeystoreTsf() {
+ return new File("src/test/resources/keystore.jks");
+ }
+
+ @BindToRegistry("encoder")
+ public ChannelHandler getEncoder() {
+ return new ShareableChannelHandlerFactory(new ObjectEncoder());
+ }
+
+ @BindToRegistry("decoder")
+ public ChannelHandler getDecoder() {
+ return new DefaultChannelHandlerFactory() {
+ @Override
+ public ChannelHandler newChannelHandler() {
+ return new
ObjectDecoder(ClassResolvers.weakCachingResolver(null));
+ }
+ };
+ }
+
+ @Test
+ public void testConsumerKeepsItsConnectionHeaders() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:plain");
+ mock.expectedBodiesReceived("Hello World");
+ mock.expectedHeaderReceived("cheese", "gouda");
+
+ Exchange reply =
template.request("netty:tcp://localhost:{{port}}?sync=true&transferExchange=true"
+ CODECS, e -> {
+ e.getIn().setBody("Hello World");
+ e.getIn().setHeader("cheese", "gouda");
+ e.getIn().setHeader(NettyConstants.NETTY_REMOTE_ADDRESS,
"10.1.2.3:4567");
+ e.getIn().setHeader(NettyConstants.NETTY_LOCAL_ADDRESS,
"10.1.2.3:8910");
+
e.getIn().setHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_SUBJECT_NAME,
"CN=Sender");
+
e.getIn().setHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_SERIAL_NO, "42");
+ e.setProperty(NettyConstants.NETTY_REMOTE_ADDRESS,
"10.1.2.3:4567");
+ });
+ assertNull(reply.getException());
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange received = mock.getReceivedExchanges().get(0);
+ Message in = received.getIn();
+ // the addresses of the connection the consumer accepted
+ assertInstanceOf(InetSocketAddress.class,
in.getHeader(NettyConstants.NETTY_REMOTE_ADDRESS));
+ InetSocketAddress local = assertInstanceOf(InetSocketAddress.class,
in.getHeader(NettyConstants.NETTY_LOCAL_ADDRESS));
+ assertEquals(getPort(), local.getPort());
+ // no client certificate on this connection, so no client certificate
headers
+
assertNull(in.getHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_SUBJECT_NAME));
+
assertNull(in.getHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_SERIAL_NO));
+ assertNull(received.getProperty(NettyConstants.NETTY_REMOTE_ADDRESS));
+
+ // the producer keeps its own connection headers too: the reply has
none from the consumer
+ Message message = reply.getMessage();
+ assertEquals("Bye World", message.getBody());
+ assertEquals("cheddar", message.getHeader("cheese"));
+
assertNull(message.getHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_SUBJECT_NAME));
+ assertNull(message.getHeader(NettyConstants.NETTY_REMOTE_ADDRESS));
+ }
+
+ @Test
+ public void testConsumerKeepsItsClientCertHeaders() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:ssl");
+ mock.expectedBodiesReceived("Hello World");
+
mock.expectedHeaderReceived(NettyConstants.NETTY_SSL_CLIENT_CERT_SUBJECT_NAME,
CLIENT_CERT_SUBJECT);
+
mock.expectedHeaderReceived(NettyConstants.NETTY_SSL_CLIENT_CERT_ISSUER_NAME,
CLIENT_CERT_SUBJECT);
+
mock.expectedHeaderReceived(NettyConstants.NETTY_SSL_CLIENT_CERT_SERIAL_NO,
"1234567890");
+
+ Exchange reply = template.request(
+ "netty:tcp://localhost:" + sslPort.getPort() +
"?sync=true&transferExchange=true" + CODECS + SSL_OPTIONS, e -> {
+ e.getIn().setBody("Hello World");
+
e.getIn().setHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_SUBJECT_NAME,
"CN=Sender");
+
e.getIn().setHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_ISSUER_NAME,
"CN=Sender CA");
+
e.getIn().setHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_SERIAL_NO, "42");
+ });
+ assertNull(reply.getException());
+ assertEquals("Bye World", reply.getMessage().getBody());
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+
from("netty:tcp://localhost:{{port}}?sync=true&transferExchange=true" + CODECS)
+ .to("mock:plain")
+ .setHeader("cheese", constant("cheddar"))
+
.setHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_SUBJECT_NAME,
constant("CN=Consumer"))
+ .transform().constant("Bye World");
+
+ from("netty:tcp://localhost:" + sslPort.getPort() +
"?sync=true&transferExchange=true" + CODECS + SSL_OPTIONS
+ + "&needClientAuth=true&sslClientCertHeaders=true")
+ .to("mock:ssl")
+ .transform().constant("Bye World");
+ }
+ };
+ }
+}
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 1c2b25546979..780d9f5fdb33 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
@@ -163,6 +163,16 @@ credentials. A deployment that counted on the inherited
list as a restriction ha
A consumer whose `requestUriPattern` is `/` now also uses its own keys,
certificates and asynchronous MDN settings when
another consumer created the shared server connection; before, it used the
first consumer's.
+=== camel-netty - with transferExchange the consumer keeps its own connection
headers
+
+With `transferExchange=true` the connection headers `CamelNettyRemoteAddress`,
`CamelNettyLocalAddress`,
+`CamelNettyChannelHandlerContext`, `CamelNettySSLSession` and the
`CamelNettySSLClientCert*` headers (and the
+`CamelNettyRemoteAddress` and `CamelNettyChannel` exchange properties) are now
always the ones of the receiving side:
+the connection it accepted is the source of truth. Before, the headers of the
transferred exchange replaced them. Such
+a header in the transferred exchange is no longer used, also when the
receiving side has no value for it (for example
+the `CamelNettySSLClientCert*` headers on a connection without a client
certificate). This also applies to the reply
+the producer receives. Send any such value of the sender under a header name
of your own.
+
== Upgrading from 4.22.1 to 4.22.2
=== camel-management - Route group exchange counters count once per entry into
the group again
diff --git
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/NettyComponentBuilderFactory.java
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/NettyComponentBuilderFactory.java
index e10919a8a683..8a2ee3d37965 100644
---
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/NettyComponentBuilderFactory.java
+++
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/NettyComponentBuilderFactory.java
@@ -994,7 +994,13 @@ public interface NettyComponentBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option is a: <code>boolean</code> type.
*
diff --git
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/NettyHttpComponentBuilderFactory.java
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/NettyHttpComponentBuilderFactory.java
index d8036cb42c42..719419f6e9ef 100644
---
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/NettyHttpComponentBuilderFactory.java
+++
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/NettyHttpComponentBuilderFactory.java
@@ -1048,7 +1048,13 @@ public interface NettyHttpComponentBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option is a: <code>boolean</code> type.
*
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/NettyEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/NettyEndpointBuilderFactory.java
index b221fedb2319..d962147a03f7 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/NettyEndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/NettyEndpointBuilderFactory.java
@@ -1653,7 +1653,13 @@ public interface NettyEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option is a: <code>boolean</code> type.
*
@@ -1673,7 +1679,13 @@ public interface NettyEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option will be converted to a <code>boolean</code> type.
*
@@ -3373,7 +3385,13 @@ public interface NettyEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option is a: <code>boolean</code> type.
*
@@ -3393,7 +3411,13 @@ public interface NettyEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option will be converted to a <code>boolean</code> type.
*
@@ -4543,7 +4567,13 @@ public interface NettyEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option is a: <code>boolean</code> type.
*
@@ -4563,7 +4593,13 @@ public interface NettyEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option will be converted to a <code>boolean</code> type.
*
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/NettyHttpEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/NettyHttpEndpointBuilderFactory.java
index 69e1832d3666..ed681904f616 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/NettyHttpEndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/NettyHttpEndpointBuilderFactory.java
@@ -2136,7 +2136,13 @@ public interface NettyHttpEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option is a: <code>boolean</code> type.
*
@@ -2156,7 +2162,13 @@ public interface NettyHttpEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option will be converted to a <code>boolean</code> type.
*
@@ -3887,7 +3899,13 @@ public interface NettyHttpEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option is a: <code>boolean</code> type.
*
@@ -3907,7 +3925,13 @@ public interface NettyHttpEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option will be converted to a <code>boolean</code> type.
*
@@ -5096,7 +5120,13 @@ public interface NettyHttpEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option is a: <code>boolean</code> type.
*
@@ -5116,7 +5146,13 @@ public interface NettyHttpEndpointBuilderFactory {
* body, Out body, fault body, In headers, Out headers, fault headers,
* exchange properties, exchange exception. This requires that the
* objects are serializable. Camel will exclude any non-serializable
- * objects and log it at WARN level.
+ * objects and log it at WARN level. The connection headers
+ * (CamelNettyRemoteAddress, CamelNettyLocalAddress,
+ * CamelNettyChannelHandlerContext, CamelNettySSLSession and the
+ * CamelNettySSLClientCert headers) and the CamelNettyRemoteAddress and
+ * CamelNettyChannel exchange properties are always the ones of the
+ * receiving side: the connection it accepted is the source of truth,
+ * and these values are never taken from the transferred exchange.
*
* The option will be converted to a <code>boolean</code> type.
*