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 c92e25590855 CAMEL-25125: camel-mllp - ACK generation uses the MSH-2 
component separator, not '^' (#27034)
c92e25590855 is described below

commit c92e255908550b015639388f934d0e07932db048
Author: allthingssecurity <[email protected]>
AuthorDate: Tue Sep 29 17:25:53 2026 +0530

    CAMEL-25125: camel-mllp - ACK generation uses the MSH-2 component 
separator, not '^' (#27034)
    
    * CAMEL-25125: camel-mllp - ACK generation uses the MSH-2 component 
separator, not '^'
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../camel/component/mllp/internal/Hl7Util.java     | 12 ++---
 ...knowledgementWithoutBridgeErrorHandlerTest.java | 19 ++++++++
 .../camel/component/mllp/internal/Hl7UtilTest.java | 57 ++++++++++++++++++++++
 3 files changed, 82 insertions(+), 6 deletions(-)

diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/Hl7Util.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/Hl7Util.java
index 3d3a308a8767..5e5c8a3c0c4a 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/Hl7Util.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/Hl7Util.java
@@ -305,9 +305,9 @@ public final class Hl7Util {
         if (-1 == msh92start) {
             LOG.warn("Didn't find component separator for MSH-9.2 - sending 
ACK in MSH-9");
         } else {
-            final String msh9Content = 
convertToPrintFriendlyString(hl7MessageBytes, fieldSeparatorIndexes.get(7) + 1,
-                    fieldSeparatorIndexes.get(8));
-            final int[] componentIndexesInMsh9 = caretPositionsIn(msh9Content);
+            // the component separators of MSH-9, from the one that starts 
MSH-9.2 (MSH-2 may define another one than '^')
+            final int[] componentIndexesInMsh9
+                    = componentSeparatorIndexes(hl7MessageBytes, msh92start, 
fieldSeparatorIndexes.get(8), componentSeparator);
             final int componentDiff = 
componentIndexesInMsh9[componentIndexesInMsh9.length - 1] - 
componentIndexesInMsh9[0];
 
             if (componentIndexesInMsh9.length == 2) { //MSH-9.3 is an optional 
field since 2.3.1, required since 2.5; this is a non-breaking change by just 
checking the number of the components in the field MSH-9
@@ -486,9 +486,9 @@ public final class Hl7Util {
         return String.valueOf(c);
     }
 
-    private int[] caretPositionsIn(String data) {
-        return IntStream.range(0, data.length())
-                .filter(i -> data.charAt(i) == '^')
+    private static int[] componentSeparatorIndexes(byte[] hl7MessageBytes, int 
start, int end, byte componentSeparator) {
+        return IntStream.range(start, end)
+                .filter(i -> hl7MessageBytes[i] == componentSeparator)
                 .toArray();
     }
 
diff --git 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpTcpServerConsumerAutoAcknowledgementWithoutBridgeErrorHandlerTest.java
 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpTcpServerConsumerAutoAcknowledgementWithoutBridgeErrorHandlerTest.java
index 81d950e9dc60..a1a94f122c32 100644
--- 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpTcpServerConsumerAutoAcknowledgementWithoutBridgeErrorHandlerTest.java
+++ 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpTcpServerConsumerAutoAcknowledgementWithoutBridgeErrorHandlerTest.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.mllp;
 
 import org.apache.camel.Exchange;
+import org.apache.camel.component.mock.MockEndpoint;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.camel.test.junit6.TestSupport.assertIsInstanceOf;
@@ -58,6 +59,24 @@ public class 
MllpTcpServerConsumerAutoAcknowledgementWithoutBridgeErrorHandlerTe
         assertThat(acknowledgement, 
endsWith("||ACK^A04^ACK|||2.6\rMSA|AA|\r"));
     }
 
+    @Test
+    public void testReceiveMessageWithOtherComponentSeparator() throws 
Exception {
+        // MSH-2 defines the separators, and the component separator does not 
have to be '^'
+        final String testMessage = 
TEST_MESSAGE.replace("MSH|^~\\&|APP_A|FAC_A|^org^sys||||ADT^A04^ADT_A04|",
+                "MSH|$~\\&|APP_A|FAC_A|$org$sys||||ADT$A04$ADT_A04|");
+
+        result.expectedBodiesReceived(testMessage);
+        complete.expectedBodiesReceived(testMessage);
+        
complete.expectedHeaderReceived(MllpConstants.MLLP_ACKNOWLEDGEMENT_TYPE, "AA");
+
+        mllpClient.connect();
+        String acknowledgement = 
mllpClient.sendMessageAndWaitForAcknowledgement(testMessage);
+
+        MockEndpoint.assertIsSatisfied(context);
+        assertThat(acknowledgement, 
startsWith("MSH|$~\\&|$org$sys||APP_A|FAC_A|"));
+        assertThat(acknowledgement, 
endsWith("||ACK$A04$ACK|||2.6\rMSA|AA|\r"));
+    }
+
     public void testAcknowledgementDeliveryFailure() throws Exception {
         result.expectedBodiesReceived(TEST_MESSAGE);
 
diff --git 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/Hl7UtilTest.java
 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/Hl7UtilTest.java
index 82b1cba72ba8..ca733f0dbeaa 100644
--- 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/Hl7UtilTest.java
+++ 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/Hl7UtilTest.java
@@ -110,6 +110,12 @@ public class Hl7UtilTest {
                                                                    + 
MllpProtocolConstants.END_OF_BLOCK
                                                                    + 
MllpProtocolConstants.END_OF_DATA;
 
+    static final String MSH_SEGMENT_BEFORE_MSH9_OTHER_SEPARATOR
+            = "MSH|$~\\&|REQUESTING|ICE|INHOUSE|RTH00|20250912193919||";
+
+    static final String EXPECTED_ACKNOWLEDGEMENT_PAYLOAD_START_OTHER_SEPARATOR
+            = MllpProtocolConstants.START_OF_BLOCK + 
"MSH|$~\\&|INHOUSE|RTH00|REQUESTING|ICE|";
+
     static final byte[] TEST_MESSAGE_BYTES = TEST_MESSAGE.getBytes();
 
     private final Hl7Util hl7util = new Hl7Util(5120, LOG_PHI_TRUE);
@@ -775,4 +781,55 @@ public class Hl7UtilTest {
         assertThat(actual, endsWith("||ACK^T01^ACK" + 
EXPECTED_ACKNOWLEDGEMENT_PAYLOAD_END_MSH));
     }
 
+    @Test
+    public void 
testGenerateAcknowledgementPayloadWithOtherComponentSeparator() throws 
Exception {
+        final MllpSocketBuffer mllpSocketBuffer = new MllpSocketBuffer(new 
MllpEndpointStub());
+        final String testMessage = MSH_SEGMENT_BEFORE_MSH9_OTHER_SEPARATOR + 
"MDM$T01" + MSH_SEGMENT_AFTER_MSH9;
+        hl7util.generateAcknowledgementPayload(mllpSocketBuffer, 
testMessage.getBytes(), "AA");
+
+        final String actual = mllpSocketBuffer.toString();
+
+        assertThat(actual, 
startsWith(EXPECTED_ACKNOWLEDGEMENT_PAYLOAD_START_OTHER_SEPARATOR));
+        assertThat(actual, endsWith("||ACK$T01" + 
EXPECTED_ACKNOWLEDGEMENT_PAYLOAD_END_MSH));
+    }
+
+    @Test
+    public void 
testGenerateAcknowledgementPayloadWithOtherComponentSeparatorAndMsh93() throws 
Exception {
+        final MllpSocketBuffer mllpSocketBuffer = new MllpSocketBuffer(new 
MllpEndpointStub());
+        final String testMessage = MSH_SEGMENT_BEFORE_MSH9_OTHER_SEPARATOR + 
"MDM$T01$MDM_T01" + MSH_SEGMENT_AFTER_MSH9;
+        hl7util.generateAcknowledgementPayload(mllpSocketBuffer, 
testMessage.getBytes(), "AA");
+
+        final String actual = mllpSocketBuffer.toString();
+
+        assertThat(actual, 
startsWith(EXPECTED_ACKNOWLEDGEMENT_PAYLOAD_START_OTHER_SEPARATOR));
+        assertThat(actual, endsWith("||ACK$T01$ACK" + 
EXPECTED_ACKNOWLEDGEMENT_PAYLOAD_END_MSH));
+    }
+
+    @Test
+    public void 
testGenerateAcknowledgementPayloadWithOtherComponentSeparatorAndCaretInMsh93() 
throws Exception {
+        final MllpSocketBuffer mllpSocketBuffer = new MllpSocketBuffer(new 
MllpEndpointStub());
+        // '^' is not a separator here, so MSH-9 has three components
+        final String testMessage = MSH_SEGMENT_BEFORE_MSH9_OTHER_SEPARATOR + 
"MDM$T01$MDM^T01" + MSH_SEGMENT_AFTER_MSH9;
+        hl7util.generateAcknowledgementPayload(mllpSocketBuffer, 
testMessage.getBytes(), "AA");
+
+        final String actual = mllpSocketBuffer.toString();
+
+        assertThat(actual, 
startsWith(EXPECTED_ACKNOWLEDGEMENT_PAYLOAD_START_OTHER_SEPARATOR));
+        assertThat(actual, endsWith("||ACK$T01$ACK" + 
EXPECTED_ACKNOWLEDGEMENT_PAYLOAD_END_MSH));
+    }
+
+    @Test
+    public void 
testGenerateAcknowledgementPayloadWithMsh93AndSmallLogPhiMaxBytes() throws 
Exception {
+        // logPhiMaxBytes only limits what is logged, it must not change the 
acknowledgement
+        final Hl7Util local = new Hl7Util(3, LOG_PHI_TRUE);
+        final MllpSocketBuffer mllpSocketBuffer = new MllpSocketBuffer(new 
MllpEndpointStub());
+        final String testMessage = MSH_SEGMENT_BEFORE_MSH9 + "MDM^T01^MDM_T01" 
+ MSH_SEGMENT_AFTER_MSH9;
+        local.generateAcknowledgementPayload(mllpSocketBuffer, 
testMessage.getBytes(), "AA");
+
+        final String actual = mllpSocketBuffer.toString();
+
+        assertThat(actual, startsWith(EXPECTED_ACKNOWLEDGEMENT_PAYLOAD_START));
+        assertThat(actual, endsWith("||ACK^T01^ACK" + 
EXPECTED_ACKNOWLEDGEMENT_PAYLOAD_END_MSH));
+    }
+
 }

Reply via email to