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 a119256dca75 [CAMEL-22000] Expose mTLS headers for camel-mllp (#20587)
a119256dca75 is described below

commit a119256dca7538d0933be17f7df4abd0cba12cef
Author: anders-p-andersson-vgregion-se <[email protected]>
AuthorDate: Thu Jan 1 10:29:06 2026 +0100

    [CAMEL-22000] Expose mTLS headers for camel-mllp (#20587)
    
    * [CAMEL-22000] Expose peer certificate values through headers for 
camel-mllp
    
    * [CAMEL-22000] - Corrections based on feeback
    
    - MLLP_SSL_CLIENT_CERT_NOT_BEFORE and MLLP_SSL_CLIENT_CERT_NOT_AFTER
      supposed to be java.util.Date as camel-netty does it.
    - Fixed test case to expect SSLHandshakeException instead of
      SocketException.
    - Ran mvn clean install -DskipTests to ensure formatting and code
      generation doesn't leave modified files behind.
    
    ---------
    
    Co-authored-by: Anders Andersson <[email protected]>
---
 .../org/apache/camel/catalog/components/mllp.json  |  37 ++--
 .../org/apache/camel/component/mllp/mllp.json      |  37 ++--
 .../apache/camel/component/mllp/MllpConstants.java |  11 ++
 .../component/mllp/MllpTcpServerConsumer.java      |  58 +++++-
 .../mllp/MllpMutualTlsConnectionAndHeaderBase.java | 202 +++++++++++++++++++++
 ...nectionAndHeaderNoClientAuthenticationTest.java |  73 ++++++++
 ...nAndHeaderRequiresClientAuthenticationTest.java |  68 +++++++
 ...tionAndHeaderWantsClientAuthenticationTest.java |  83 +++++++++
 .../endpoint/dsl/MllpEndpointBuilderFactory.java   |  60 ++++++
 9 files changed, 592 insertions(+), 37 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mllp.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mllp.json
index 64e17075301f..1791ae834f81 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mllp.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mllp.json
@@ -62,22 +62,27 @@
   "headers": {
     "CamelMllpLocalAddress": { "index": 0, "kind": "header", "displayName": 
"", "group": "common", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The local TCP Address of the Socket", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_LOCAL_ADDRESS" },
     "CamelMllpRemoteAddress": { "index": 1, "kind": "header", "displayName": 
"", "group": "common", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The remote TCP Address of the Socket", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_REMOTE_ADDRESS" },
-    "CamelMllpAcknowledgement": { "index": 2, "kind": "header", "displayName": 
"", "group": "common", "label": "", "required": false, "javaType": "byte[]", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The HL7 Acknowledgment received in bytes", 
"constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT" },
-    "CamelMllpAcknowledgementString": { "index": 3, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The HL7 Acknowledgment received, 
converted to a String", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT_STRING" },
-    "CamelMllpAcknowledgementType": { "index": 4, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The HL7 acknowledgement type (AA, AE, 
AR, etc)", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT_TYPE" },
-    "CamelMllpSendingApplication": { "index": 5, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-3 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SENDING_APPLICATION" },
-    "CamelMllpSendingFacility": { "index": 6, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-4 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SENDING_FACILITY" },
-    "CamelMllpReceivingApplication": { "index": 7, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-5 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_RECEIVING_APPLICATION" },
-    "CamelMllpReceivingFacility": { "index": 8, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-6 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_RECEIVING_FACILITY" },
-    "CamelMllpTimestamp": { "index": 9, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-7 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_TIMESTAMP" },
-    "CamelMllpSecurity": { "index": 10, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-8 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SECURITY" },
-    "CamelMllpMessageType": { "index": 11, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_MESSAGE_TYPE" },
-    "CamelMllpEventType": { "index": 12, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9.1 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_EVENT_TYPE" },
-    "CamelMllpTriggerEvent": { "index": 13, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9.2 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_TRIGGER_EVENT" },
-    "CamelMllpMessageControlId": { "index": 14, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-10 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_MESSAGE_CONTROL" },
-    "CamelMllpProcessingId": { "index": 15, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-11 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_PROCESSING_ID" },
-    "CamelMllpVersionId": { "index": 16, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-12 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_VERSION_ID" },
-    "CamelMllpCharset": { "index": 17, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-18 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_CHARSET" }
+    "CamelMllpSslClientCertSubjectName": { "index": 2, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The SSL client certificate subject 
name", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SSL_CLIENT_CERT_SUBJECT_NAME"
 },
+    "CamelMllpSslClientCertIssuerName": { "index": 3, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The SSL client certificate issuer 
name", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SSL_CLIENT_CERT_ISSUER_NAME"
 },
+    "CamelMllpSslClientCertSerialNo": { "index": 4, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The SSL client certificate serial 
number", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SSL_CLIENT_CERT_SERIAL_NO" 
},
+    "CamelMllpSslClientCertNotBefore": { "index": 5, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "java.util.Date", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The SSL client certificate 
not before.", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SSL_CLIENT_CERT_NOT_BEFORE" 
},
+    "CamelMllpSslClientCertNotAfter": { "index": 6, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "java.util.Date", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The SSL client certificate 
not after.", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SSL_CLIENT_CERT_NOT_AFTER" 
},
+    "CamelMllpAcknowledgement": { "index": 7, "kind": "header", "displayName": 
"", "group": "common", "label": "", "required": false, "javaType": "byte[]", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The HL7 Acknowledgment received in bytes", 
"constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT" },
+    "CamelMllpAcknowledgementString": { "index": 8, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The HL7 Acknowledgment received, 
converted to a String", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT_STRING" },
+    "CamelMllpAcknowledgementType": { "index": 9, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The HL7 acknowledgement type (AA, AE, 
AR, etc)", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT_TYPE" },
+    "CamelMllpSendingApplication": { "index": 10, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-3 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SENDING_APPLICATION" },
+    "CamelMllpSendingFacility": { "index": 11, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-4 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SENDING_FACILITY" },
+    "CamelMllpReceivingApplication": { "index": 12, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-5 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_RECEIVING_APPLICATION" },
+    "CamelMllpReceivingFacility": { "index": 13, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-6 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_RECEIVING_FACILITY" },
+    "CamelMllpTimestamp": { "index": 14, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-7 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_TIMESTAMP" },
+    "CamelMllpSecurity": { "index": 15, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-8 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SECURITY" },
+    "CamelMllpMessageType": { "index": 16, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_MESSAGE_TYPE" },
+    "CamelMllpEventType": { "index": 17, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9.1 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_EVENT_TYPE" },
+    "CamelMllpTriggerEvent": { "index": 18, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9.2 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_TRIGGER_EVENT" },
+    "CamelMllpMessageControlId": { "index": 19, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-10 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_MESSAGE_CONTROL" },
+    "CamelMllpProcessingId": { "index": 20, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-11 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_PROCESSING_ID" },
+    "CamelMllpVersionId": { "index": 21, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-12 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_VERSION_ID" },
+    "CamelMllpCharset": { "index": 22, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-18 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_CHARSET" }
   },
   "properties": {
     "hostname": { "index": 0, "kind": "path", "displayName": "Hostname", 
"group": "common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Hostname or IP for connection for the 
TCP connection. The default value is null, which means any local IP address" },
diff --git 
a/components/camel-mllp/src/generated/resources/META-INF/org/apache/camel/component/mllp/mllp.json
 
b/components/camel-mllp/src/generated/resources/META-INF/org/apache/camel/component/mllp/mllp.json
index 64e17075301f..1791ae834f81 100644
--- 
a/components/camel-mllp/src/generated/resources/META-INF/org/apache/camel/component/mllp/mllp.json
+++ 
b/components/camel-mllp/src/generated/resources/META-INF/org/apache/camel/component/mllp/mllp.json
@@ -62,22 +62,27 @@
   "headers": {
     "CamelMllpLocalAddress": { "index": 0, "kind": "header", "displayName": 
"", "group": "common", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The local TCP Address of the Socket", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_LOCAL_ADDRESS" },
     "CamelMllpRemoteAddress": { "index": 1, "kind": "header", "displayName": 
"", "group": "common", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The remote TCP Address of the Socket", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_REMOTE_ADDRESS" },
-    "CamelMllpAcknowledgement": { "index": 2, "kind": "header", "displayName": 
"", "group": "common", "label": "", "required": false, "javaType": "byte[]", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The HL7 Acknowledgment received in bytes", 
"constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT" },
-    "CamelMllpAcknowledgementString": { "index": 3, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The HL7 Acknowledgment received, 
converted to a String", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT_STRING" },
-    "CamelMllpAcknowledgementType": { "index": 4, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The HL7 acknowledgement type (AA, AE, 
AR, etc)", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT_TYPE" },
-    "CamelMllpSendingApplication": { "index": 5, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-3 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SENDING_APPLICATION" },
-    "CamelMllpSendingFacility": { "index": 6, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-4 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SENDING_FACILITY" },
-    "CamelMllpReceivingApplication": { "index": 7, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-5 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_RECEIVING_APPLICATION" },
-    "CamelMllpReceivingFacility": { "index": 8, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-6 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_RECEIVING_FACILITY" },
-    "CamelMllpTimestamp": { "index": 9, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-7 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_TIMESTAMP" },
-    "CamelMllpSecurity": { "index": 10, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-8 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SECURITY" },
-    "CamelMllpMessageType": { "index": 11, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_MESSAGE_TYPE" },
-    "CamelMllpEventType": { "index": 12, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9.1 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_EVENT_TYPE" },
-    "CamelMllpTriggerEvent": { "index": 13, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9.2 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_TRIGGER_EVENT" },
-    "CamelMllpMessageControlId": { "index": 14, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-10 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_MESSAGE_CONTROL" },
-    "CamelMllpProcessingId": { "index": 15, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-11 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_PROCESSING_ID" },
-    "CamelMllpVersionId": { "index": 16, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-12 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_VERSION_ID" },
-    "CamelMllpCharset": { "index": 17, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-18 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_CHARSET" }
+    "CamelMllpSslClientCertSubjectName": { "index": 2, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The SSL client certificate subject 
name", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SSL_CLIENT_CERT_SUBJECT_NAME"
 },
+    "CamelMllpSslClientCertIssuerName": { "index": 3, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The SSL client certificate issuer 
name", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SSL_CLIENT_CERT_ISSUER_NAME"
 },
+    "CamelMllpSslClientCertSerialNo": { "index": 4, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The SSL client certificate serial 
number", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SSL_CLIENT_CERT_SERIAL_NO" 
},
+    "CamelMllpSslClientCertNotBefore": { "index": 5, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "java.util.Date", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The SSL client certificate 
not before.", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SSL_CLIENT_CERT_NOT_BEFORE" 
},
+    "CamelMllpSslClientCertNotAfter": { "index": 6, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "java.util.Date", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The SSL client certificate 
not after.", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SSL_CLIENT_CERT_NOT_AFTER" 
},
+    "CamelMllpAcknowledgement": { "index": 7, "kind": "header", "displayName": 
"", "group": "common", "label": "", "required": false, "javaType": "byte[]", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The HL7 Acknowledgment received in bytes", 
"constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT" },
+    "CamelMllpAcknowledgementString": { "index": 8, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The HL7 Acknowledgment received, 
converted to a String", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT_STRING" },
+    "CamelMllpAcknowledgementType": { "index": 9, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The HL7 acknowledgement type (AA, AE, 
AR, etc)", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_ACKNOWLEDGEMENT_TYPE" },
+    "CamelMllpSendingApplication": { "index": 10, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-3 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SENDING_APPLICATION" },
+    "CamelMllpSendingFacility": { "index": 11, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-4 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SENDING_FACILITY" },
+    "CamelMllpReceivingApplication": { "index": 12, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-5 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_RECEIVING_APPLICATION" },
+    "CamelMllpReceivingFacility": { "index": 13, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-6 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_RECEIVING_FACILITY" },
+    "CamelMllpTimestamp": { "index": 14, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-7 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_TIMESTAMP" },
+    "CamelMllpSecurity": { "index": 15, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-8 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_SECURITY" },
+    "CamelMllpMessageType": { "index": 16, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_MESSAGE_TYPE" },
+    "CamelMllpEventType": { "index": 17, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9.1 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_EVENT_TYPE" },
+    "CamelMllpTriggerEvent": { "index": 18, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-9.2 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_TRIGGER_EVENT" },
+    "CamelMllpMessageControlId": { "index": 19, "kind": "header", 
"displayName": "", "group": "consumer", "label": "consumer", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "MSH-10 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_MESSAGE_CONTROL" },
+    "CamelMllpProcessingId": { "index": 20, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-11 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_PROCESSING_ID" },
+    "CamelMllpVersionId": { "index": 21, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-12 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_VERSION_ID" },
+    "CamelMllpCharset": { "index": 22, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "MSH-18 value", "constantName": 
"org.apache.camel.component.mllp.MllpConstants#MLLP_CHARSET" }
   },
   "properties": {
     "hostname": { "index": 0, "kind": "path", "displayName": "Hostname", 
"group": "common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Hostname or IP for connection for the 
TCP connection. The default value is null, which means any local IP address" },
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConstants.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConstants.java
index 00eede06d2cf..1b084c2ae2b8 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConstants.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConstants.java
@@ -26,6 +26,17 @@ public final class MllpConstants {
     public static final String MLLP_LOCAL_ADDRESS = "CamelMllpLocalAddress";
     @Metadata(description = "The remote TCP Address of the Socket", javaType = 
"String")
     public static final String MLLP_REMOTE_ADDRESS = "CamelMllpRemoteAddress";
+    @Metadata(description = "The SSL client certificate subject name", label = 
"consumer", javaType = "String")
+    public static final String MLLP_SSL_CLIENT_CERT_SUBJECT_NAME = 
"CamelMllpSslClientCertSubjectName";
+    @Metadata(description = "The SSL client certificate issuer name", label = 
"consumer", javaType = "String")
+    public static final String MLLP_SSL_CLIENT_CERT_ISSUER_NAME = 
"CamelMllpSslClientCertIssuerName";
+    @Metadata(description = "The SSL client certificate serial number", label 
= "consumer", javaType = "String")
+    public static final String MLLP_SSL_CLIENT_CERT_SERIAL_NO = 
"CamelMllpSslClientCertSerialNo";
+    @Metadata(description = "The SSL client certificate not before.", label = 
"consumer", javaType = "java.util.Date")
+    public static final String MLLP_SSL_CLIENT_CERT_NOT_BEFORE = 
"CamelMllpSslClientCertNotBefore";
+    @Metadata(description = "The SSL client certificate not after.", label = 
"consumer", javaType = "java.util.Date")
+    public static final String MLLP_SSL_CLIENT_CERT_NOT_AFTER = 
"CamelMllpSslClientCertNotAfter";
+
     @Metadata(description = "The HL7 Acknowledgment received in bytes", 
javaType = "byte[]")
     public static final String MLLP_ACKNOWLEDGEMENT = 
"CamelMllpAcknowledgement";
     @Metadata(description = "The HL7 Acknowledgment received, converted to a 
String", javaType = "String")
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpServerConsumer.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpServerConsumer.java
index 037b8e66be2d..8ab1e9884137 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpServerConsumer.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpServerConsumer.java
@@ -17,15 +17,15 @@
 package org.apache.camel.component.mllp;
 
 import java.io.IOException;
+import java.math.BigInteger;
 import java.net.BindException;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -35,6 +35,10 @@ import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Pattern;
 
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
 import org.apache.camel.Exchange;
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.ExchangePropertyKey;
@@ -255,6 +259,10 @@ public class MllpTcpServerConsumer extends DefaultConsumer 
{
 
             Message message = exchange.getIn();
 
+            if (consumerRunnable.getSocket() instanceof SSLSocket sslSocket) {
+                enrichWithClientCertInformation(sslSocket.getSession(), 
message);
+            }
+
             if (consumerRunnable.hasLocalAddress()) {
                 message.setHeader(MllpConstants.MLLP_LOCAL_ADDRESS, 
consumerRunnable.getLocalAddress());
             }
@@ -305,6 +313,46 @@ public class MllpTcpServerConsumer extends DefaultConsumer 
{
         }
     }
 
+    /**
+     * Enriches the message with client certificate details such as subject 
name, serial number, etc.
+     * <p/>
+     * If the certificate is unverified then the headers is not enriched.
+     *
+     * @param sslSession the SSL session
+     * @param message    the message to enrich
+     */
+    protected void enrichWithClientCertInformation(SSLSession sslSession, 
Message message) {
+        if (sslSession == null || message == null) {
+            return;
+        }
+
+        try {
+            Certificate[] certificates = sslSession.getPeerCertificates();
+            if (certificates != null && certificates.length > 0) {
+                if (!(certificates[0] instanceof X509Certificate cert)) {
+                    return;
+                }
+
+                Principal subject = cert.getSubjectX500Principal();
+                if (subject != null) {
+                    
message.setHeader(MllpConstants.MLLP_SSL_CLIENT_CERT_SUBJECT_NAME, 
subject.toString());
+                }
+                Principal issuer = cert.getIssuerX500Principal();
+                if (issuer != null) {
+                    
message.setHeader(MllpConstants.MLLP_SSL_CLIENT_CERT_ISSUER_NAME, 
issuer.toString());
+                }
+                BigInteger serial = cert.getSerialNumber();
+                if (serial != null) {
+                    
message.setHeader(MllpConstants.MLLP_SSL_CLIENT_CERT_SERIAL_NO, 
serial.toString());
+                }
+                
message.setHeader(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_BEFORE, 
cert.getNotBefore());
+                
message.setHeader(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_AFTER, 
cert.getNotAfter());
+            }
+        } catch (SSLPeerUnverifiedException e) {
+            // ignore
+        }
+    }
+
     void populateHl7DataHeaders(Exchange exchange, Message message, byte[] 
hl7MessageBytes) {
         if (getConfiguration().isHl7Headers() && exchange != null && 
exchange.getException() == null) {
             if (hl7MessageBytes == null || hl7MessageBytes.length < 8) {
diff --git 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderBase.java
 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderBase.java
new file mode 100644
index 000000000000..5289311b0c0d
--- /dev/null
+++ 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderBase.java
@@ -0,0 +1,202 @@
+/*
+ * 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.mllp;
+
+import java.io.File;
+import java.net.URI;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.jsse.*;
+import org.apache.camel.test.AvailablePortFinder;
+import org.apache.camel.test.junit.rule.mllp.MllpClientResource;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+/**
+ * Does mTLS connection with MLLP and asserts that the headers are properly 
set.
+ */
+public class MllpMutualTlsConnectionAndHeaderBase extends CamelTestSupport {
+
+    public static final String WANTS_CLIENT_AUTHENTICATION = 
"sslContextParametersWantsClientAuthentication";
+    public static final String REQUIRES_CLIENT_AUTHENTICATION = 
"sslContextParametersRequiresClientAuthentication";
+    public static final String NO_CLIENT_AUTHENTICATION = 
"sslContextParametersNoClientAuthentication";
+    public static final String WITH_ONLY_TRUSTSTORE = 
"sslContextParametersWithOnlyTruststore";
+
+    public static final String TEST_PAYLOAD = 
"MSH|^~\\&|CLIENT|TEST|SERVER|ACK|20231118120000||ADT^A01|123456|T|2.6\r" +
+                                              "EVN|A01|20231118120000\r" +
+                                              
"PID|1|12345|67890||DOE^JOHN||19800101|M|||123 Main 
St^^Springfield^IL^62704||(555)555-5555|||||S\r"
+                                              +
+                                              "PV1|1|O\r";
+
+    private final String sslContextParamtersUsedInTestRoute;
+
+    protected String expectedCertSubjectName;
+    protected String expectedCertIssuerName;
+    protected String expectedCertSerialNo;
+    protected Date expectedCertNotBefore;
+    protected Date expectedCertNotAfter;
+
+    @RegisterExtension
+    public MllpClientResource mllpClient = new MllpClientResource();
+
+    @EndpointInject("mock://result")
+    protected MockEndpoint result;
+
+    protected MllpMutualTlsConnectionAndHeaderBase(String 
sslContextParametersUsedInTestRoute) {
+        this.sslContextParamtersUsedInTestRoute = 
sslContextParametersUsedInTestRoute;
+    }
+
+    /**
+     * Creates test route.
+     *
+     * @return RouteBuilder.
+     */
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+
+            public void configure() {
+                fromF(assembleEndpointUri(sslContextParamtersUsedInTestRoute))
+                        .log(LoggingLevel.INFO, "mllp-ssl-sender", "Received 
Message: ${body}")
+                        .to(result);
+            }
+        };
+    }
+
+    /**
+     * Creates an SSLContextParameters object with a key and truststore so 
that mTLS is conducted.
+     *
+     * @return           SSLContextParamters with both keystore and truststore 
paramters.
+     * @throws Exception if anything goes wrong and then should fail the test.
+     */
+    private SSLContextParameters 
createSslContextParameters(ClientAuthentication clientAuthentication) throws 
Exception {
+        KeyStoreParameters ksp = new KeyStoreParameters();
+        
ksp.setResource(this.getClass().getClassLoader().getResource("keystore.jks").toString());
+        ksp.setPassword("password");
+
+        KeyManagersParameters kmp = new KeyManagersParameters();
+        kmp.setKeyPassword("password");
+        kmp.setKeyStore(ksp);
+
+        TrustManagersParameters tmp = new TrustManagersParameters();
+        tmp.setKeyStore(ksp);
+
+        SSLContextParameters sslContextParameters = new SSLContextParameters();
+        sslContextParameters.setKeyManagers(kmp);
+        sslContextParameters.setTrustManagers(tmp);
+
+        extractExpectedSSLCertHeaderValuesFromActualCertificate(ksp);
+
+        sslContextParameters.setServerParameters(new 
SSLContextServerParameters());
+        
sslContextParameters.getServerParameters().setClientAuthentication(clientAuthentication.name());
+
+        return sslContextParameters;
+    }
+
+    /**
+     * Extracts values from the certificate the client will use to be used for 
validation during the tests.
+     *
+     * @param  ksp       KeyStoreParameters object created from 
SSLContextParameters creation. Holds the certificate
+     *                   information.
+     * @throws Exception if anything goes wrong and then should fail the test.
+     */
+    private void 
extractExpectedSSLCertHeaderValuesFromActualCertificate(KeyStoreParameters ksp)
+            throws Exception {
+        File certFile = new File(URI.create(ksp.getResource()));
+        char[] password = ksp.getPassword().toCharArray();
+
+        KeyStore ks = KeyStore.getInstance(certFile, password);
+        X509Certificate certificate = (X509Certificate) 
ks.getCertificate("testKey");
+
+        expectedCertIssuerName = 
certificate.getIssuerX500Principal().toString();
+        expectedCertSubjectName = 
certificate.getSubjectX500Principal().toString();
+        expectedCertSerialNo = certificate.getSerialNumber().toString();
+        expectedCertNotBefore = certificate.getNotBefore();
+        expectedCertNotAfter = certificate.getNotAfter();
+
+        // Be really sure the expected headers aren't null as 
expectedHeaderReceived can accept null values,
+        // which could cause false positive test results when the mocks use 
these for comparing with the actual values.
+        Assertions.assertNotNull(expectedCertIssuerName);
+        Assertions.assertNotNull(expectedCertSubjectName);
+        Assertions.assertNotNull(expectedCertSerialNo);
+        Assertions.assertNotNull(expectedCertNotBefore);
+        Assertions.assertNotNull(expectedCertNotAfter);
+    }
+
+    /**
+     * Creates a SSLContextParameters object with only a truststore. With 
this, the client will only do TLS connection,
+     * it will not send its own certificate for validation.
+     *
+     * @return           SSLContextParameter object with only a truststore 
configured.
+     * @throws Exception if anything goes wrong and then should fail the test.
+     */
+    private SSLContextParameters 
createSslContextParametersWithOnlyTruststore() {
+        KeyStoreParameters ksp = new KeyStoreParameters();
+        
ksp.setResource(this.getClass().getClassLoader().getResource("keystore.jks").toString());
+        ksp.setPassword("password");
+
+        TrustManagersParameters tmp = new TrustManagersParameters();
+        tmp.setKeyStore(ksp);
+
+        SSLContextParameters sslContextParameters = new SSLContextParameters();
+        sslContextParameters.setTrustManagers(tmp);
+
+        return sslContextParameters;
+    }
+
+    /**
+     * Registers sslContextParametes, both of them, to camel context.
+     *
+     * @return           camelContext.
+     * @throws Exception if anything goes wrong and then should fail the test.
+     */
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        mllpClient.setMllpHost("localhost");
+        mllpClient.setMllpPort(AvailablePortFinder.getNextAvailable());
+
+        DefaultCamelContext context = (DefaultCamelContext) 
super.createCamelContext();
+
+        context.setUseMDCLogging(true);
+        
context.getCamelContextExtension().setName(this.getClass().getSimpleName());
+
+        context.getRegistry().bind(WANTS_CLIENT_AUTHENTICATION,
+                createSslContextParameters(ClientAuthentication.WANT));
+        context.getRegistry().bind(REQUIRES_CLIENT_AUTHENTICATION,
+                createSslContextParameters(ClientAuthentication.REQUIRE));
+        context.getRegistry().bind(NO_CLIENT_AUTHENTICATION,
+                createSslContextParameters(ClientAuthentication.NONE));
+
+        SSLContextParameters sslContextParametersWithOnlyTruststore = 
createSslContextParametersWithOnlyTruststore();
+        context.getRegistry().bind(WITH_ONLY_TRUSTSTORE, 
sslContextParametersWithOnlyTruststore);
+        return context;
+    }
+
+    protected String assembleEndpointUri(String sslContextParameters) {
+        return String.format("mllp://%s:%d?sslContextParameters=#%s", 
mllpClient.getMllpHost(), mllpClient.getMllpPort(),
+                sslContextParameters);
+    }
+}
diff --git 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderNoClientAuthenticationTest.java
 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderNoClientAuthenticationTest.java
new file mode 100644
index 000000000000..a592ce2ce80f
--- /dev/null
+++ 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderNoClientAuthenticationTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.mllp;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Does mTLS connection with MLLP and asserts that the headers are properly 
set.
+ */
+class MllpMutualTlsConnectionAndHeaderNoClientAuthenticationTest extends 
MllpMutualTlsConnectionAndHeaderBase {
+    MllpMutualTlsConnectionAndHeaderNoClientAuthenticationTest() {
+        super(NO_CLIENT_AUTHENTICATION);
+    }
+
+    /**
+     * This test does TLS connection without a client sending its certificate, 
that is, no mTLS. In this case, none of
+     * the MLLP_SSL_CLIENT_CERT* headers should exist as the client didn't 
provide a certificate.
+     *
+     * @throws Exception if anything goes wrong and then should fail the test.
+     */
+    @Test
+    void 
testSendingTlsWithNoClientCertificateToMllpConsumerWithNoClientAuthentication() 
throws Exception {
+        result.expectedBodiesReceived(TEST_PAYLOAD);
+
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_SUBJECT_NAME, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_ISSUER_NAME, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_SERIAL_NO, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_BEFORE, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_AFTER, 
null);
+
+        template.sendBody(assembleEndpointUri(WITH_ONLY_TRUSTSTORE), 
TEST_PAYLOAD);
+        result.assertIsSatisfied();
+    }
+
+    /**
+     * As the server is configured to not do any client authentication, make 
sure the MLLP_SSL_CLIENT_CERT* headers are
+     * not present.
+     *
+     * @throws Exception if anything goes wrong and then should fail the test.
+     */
+    @Test
+    void 
testCommunicationWithConfiguredClientCertificateWithMllpConsumerWhichDoesNotDoClientAuthentication()
+            throws Exception {
+        result.expectedBodiesReceived(TEST_PAYLOAD);
+
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_SUBJECT_NAME, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_ISSUER_NAME, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_SERIAL_NO, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_BEFORE, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_AFTER, 
null);
+
+        // Any sslContextParameter with a client certificate should be valid 
here, but the worst case scenario for this test
+        // should be the context with the server flag for requiring client 
authentication. That flag should not matter,
+        // and here is the proof it doesn't.
+        template.sendBody(assembleEndpointUri(REQUIRES_CLIENT_AUTHENTICATION), 
TEST_PAYLOAD);
+        result.assertIsSatisfied();
+
+    }
+}
diff --git 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderRequiresClientAuthenticationTest.java
 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderRequiresClientAuthenticationTest.java
new file mode 100644
index 000000000000..4a63d482d9c5
--- /dev/null
+++ 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderRequiresClientAuthenticationTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.mllp;
+
+import javax.net.ssl.SSLHandshakeException;
+
+import org.apache.camel.CamelExecutionException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Does mTLS connection with MLLP and asserts that the headers are properly 
set.
+ */
+class MllpMutualTlsConnectionAndHeaderRequiresClientAuthenticationTest extends 
MllpMutualTlsConnectionAndHeaderBase {
+    MllpMutualTlsConnectionAndHeaderRequiresClientAuthenticationTest() {
+        super(REQUIRES_CLIENT_AUTHENTICATION);
+    }
+
+    /**
+     * This test does TLS connection without a client sending its certificate, 
i.e., no mTLS. As the server is
+     * configured to require client authentication, this should fail.
+     *
+     */
+    @Test
+    void 
testSendingTlsWithNoClientCertificateToMllpConsumerWhichRequiresClientAuthentication()
 {
+        try {
+            template.sendBody(assembleEndpointUri(WITH_ONLY_TRUSTSTORE), 
TEST_PAYLOAD);
+            Assertions.fail("Should not be able to connect without a client 
certificate");
+        } catch (CamelExecutionException e) {
+            Assertions.assertInstanceOf(SSLHandshakeException.class, 
e.getCause().getCause().getCause());
+        }
+    }
+
+    /**
+     * This test does a proper mTLS connection with MLLP. Here the headers are 
asserted to be present and non-null, all
+     * the MLLP_SSL* headers.
+     *
+     * @throws Exception if anything goes wrong and then should fail the test.
+     */
+    @Test
+    void testMutualTlsInOutWithMllpConsumer() throws Exception {
+        result.expectedBodiesReceived(TEST_PAYLOAD);
+
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_SUBJECT_NAME, 
expectedCertSubjectName);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_ISSUER_NAME, 
expectedCertIssuerName);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_SERIAL_NO, 
expectedCertSerialNo);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_BEFORE, 
expectedCertNotBefore);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_AFTER, 
expectedCertNotAfter);
+
+        template.sendBody(assembleEndpointUri(REQUIRES_CLIENT_AUTHENTICATION), 
TEST_PAYLOAD);
+        result.assertIsSatisfied();
+
+    }
+}
diff --git 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderWantsClientAuthenticationTest.java
 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderWantsClientAuthenticationTest.java
new file mode 100644
index 000000000000..472ae5e5413e
--- /dev/null
+++ 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpMutualTlsConnectionAndHeaderWantsClientAuthenticationTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.mllp;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Does mTLS connection with MLLP and asserts that the headers are properly 
set.
+ */
+class MllpMutualTlsConnectionAndHeaderWantsClientAuthenticationTest extends 
MllpMutualTlsConnectionAndHeaderBase {
+
+    MllpMutualTlsConnectionAndHeaderWantsClientAuthenticationTest() {
+        super(WANTS_CLIENT_AUTHENTICATION);
+    }
+
+    /**
+     * This test does TLS connection without client sending its certificate 
i.e., no mTLS. In this case, none of the
+     * MLLP_SSL_CLIENT_CERT* headers should exist as the client didn't provide 
a certificate.
+     *
+     * @throws Exception if anything goes wrong and then should fail the test.
+     */
+    @Test
+    void testTlsNoClientCertificateInOutWithMllpConsumer() throws Exception {
+        result.expectedBodiesReceived(TEST_PAYLOAD);
+
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_SUBJECT_NAME, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_ISSUER_NAME, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_SERIAL_NO, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_BEFORE, 
null);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_AFTER, 
null);
+
+        String endpointUri = 
String.format("mllp://%s:%d?sslContextParameters=#sslContextParametersWithOnlyTruststore",
+                mllpClient.getMllpHost(), mllpClient.getMllpPort());
+        template.sendBody(endpointUri, TEST_PAYLOAD);
+        result.assertIsSatisfied();
+
+    }
+
+    /**
+     * This test does a proper mTLS connection with MLLP. Here the headers are 
asserted to be present and non-null, all
+     * MLLP_SSL* headers.
+     *
+     * @throws Exception if anything goes wrong and then should fail the test.
+     */
+    @Test
+    void testMutalTlsInOutWithMllpConsumer() throws Exception {
+        result.expectedBodiesReceived(TEST_PAYLOAD);
+
+        // Be really sure the expected headers aren't null as 
expectedHeaderReceived can accept null values,
+        // which could create false positive test results.
+        Assertions.assertNotNull(expectedCertIssuerName);
+        Assertions.assertNotNull(expectedCertSubjectName);
+        Assertions.assertNotNull(expectedCertNotBefore);
+        Assertions.assertNotNull(expectedCertNotAfter);
+        Assertions.assertNotNull(expectedCertSerialNo);
+
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_SUBJECT_NAME, 
expectedCertSubjectName);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_ISSUER_NAME, 
expectedCertIssuerName);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_SERIAL_NO, 
expectedCertSerialNo);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_BEFORE, 
expectedCertNotBefore);
+        
result.expectedHeaderReceived(MllpConstants.MLLP_SSL_CLIENT_CERT_NOT_AFTER, 
expectedCertNotAfter);
+
+        String endpointUri = 
String.format("mllp://%s:%d?sslContextParameters=#sslContextParametersWantsClientAuthentication",
+                mllpClient.getMllpHost(), mllpClient.getMllpPort());
+        template.sendBody(endpointUri, TEST_PAYLOAD);
+        result.assertIsSatisfied();
+    }
+}
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MllpEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MllpEndpointBuilderFactory.java
index e2170af38eef..8268dcf65514 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MllpEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MllpEndpointBuilderFactory.java
@@ -2096,6 +2096,66 @@ public interface MllpEndpointBuilderFactory {
         public String mllpRemoteAddress() {
             return "CamelMllpRemoteAddress";
         }
+        /**
+         * The SSL client certificate subject name.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: consumer
+         * 
+         * @return the name of the header {@code MllpSslClientCertSubjectName}.
+         */
+        public String mllpSslClientCertSubjectName() {
+            return "CamelMllpSslClientCertSubjectName";
+        }
+        /**
+         * The SSL client certificate issuer name.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: consumer
+         * 
+         * @return the name of the header {@code MllpSslClientCertIssuerName}.
+         */
+        public String mllpSslClientCertIssuerName() {
+            return "CamelMllpSslClientCertIssuerName";
+        }
+        /**
+         * The SSL client certificate serial number.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: consumer
+         * 
+         * @return the name of the header {@code MllpSslClientCertSerialNo}.
+         */
+        public String mllpSslClientCertSerialNo() {
+            return "CamelMllpSslClientCertSerialNo";
+        }
+        /**
+         * The SSL client certificate not before.
+         * 
+         * The option is a: {@code java.util.Date} type.
+         * 
+         * Group: consumer
+         * 
+         * @return the name of the header {@code MllpSslClientCertNotBefore}.
+         */
+        public String mllpSslClientCertNotBefore() {
+            return "CamelMllpSslClientCertNotBefore";
+        }
+        /**
+         * The SSL client certificate not after.
+         * 
+         * The option is a: {@code java.util.Date} type.
+         * 
+         * Group: consumer
+         * 
+         * @return the name of the header {@code MllpSslClientCertNotAfter}.
+         */
+        public String mllpSslClientCertNotAfter() {
+            return "CamelMllpSslClientCertNotAfter";
+        }
         /**
          * The HL7 Acknowledgment received in bytes.
          * 

Reply via email to