CAMEL-10303 - added ability to detect when the consumer fails to deliver the 
MLLP acknowledgement


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/62715117
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/62715117
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/62715117

Branch: refs/heads/master
Commit: 62715117184b01d52b261bfda3c19e7f95fc6698
Parents: 8a11d47
Author: Quinn Stevenson <qu...@pronoia-solutions.com>
Authored: Mon Sep 12 12:47:10 2016 -0600
Committer: Andrea Cosentino <anco...@gmail.com>
Committed: Thu Sep 15 09:23:22 2016 +0200

----------------------------------------------------------------------
 .../MllpAcknowledgementDeliveryException.java   |  32 +++
 .../mllp/MllpAcknowledgementException.java      |  43 +++-
 .../MllpAcknowledgementTimoutException.java     |  16 +-
 ...pplicationErrorAcknowledgementException.java |  16 +-
 ...plicationRejectAcknowledgementException.java |  16 +-
 ...MllpCommitErrorAcknowledgementException.java |  16 +-
 ...llpCommitRejectAcknowledgementException.java |  16 +-
 .../camel/component/mllp/MllpComponent.java     |   2 +-
 .../camel/component/mllp/MllpConstants.java     |   2 +
 .../mllp/MllpCorruptFrameException.java         |  40 ----
 .../camel/component/mllp/MllpException.java     |  25 +--
 .../component/mllp/MllpFrameException.java      |  60 ++++++
 .../MllpInvalidAcknowledgementException.java    |  16 +-
 .../component/mllp/MllpTcpClientProducer.java   |  19 +-
 .../component/mllp/MllpTcpServerConsumer.java   | 132 +-----------
 .../component/mllp/MllpTimeoutException.java    |  34 ++-
 .../component/mllp/MllpWriteException.java      |  34 ++-
 .../AcknowledgmentSynchronizationAdapter.java   | 212 +++++++++++++++++++
 .../camel/component/mllp/impl/MllpUtil.java     |  28 +--
 .../mllp/MllpAcknowledgementExceptionTest.java  | 127 +++++++++++
 .../component/mllp/MllpFrameExceptionTest.java  | 101 +++++++++
 .../mllp/MllpProducerConsumerLoopbackTest.java  |   8 +-
 .../mllp/MllpTcpClientProducerTest.java         |  10 +-
 ...llpTcpServerConsumerAcknowledgementTest.java |  97 +++++++--
 .../mllp/MllpTimeoutExceptionTest.java          | 101 +++++++++
 .../component/mllp/MllpWriteExceptionTest.java  | 101 +++++++++
 .../junit/rule/mllp/MllpClientResource.java     |  51 +++--
 .../blueprint/mllp-tcp-client-producer-test.xml |   2 +-
 28 files changed, 1026 insertions(+), 331 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementDeliveryException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementDeliveryException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementDeliveryException.java
new file mode 100644
index 0000000..4ac46c9
--- /dev/null
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementDeliveryException.java
@@ -0,0 +1,32 @@
+/**
+ * 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;
+
+/**
+ * Raised when a MLLP Consumer cannot deliver the MLLP Acknowledgement
+ */
+public class MllpAcknowledgementDeliveryException extends 
MllpAcknowledgementException {
+    static final String EXCEPTION_MESSAGE = "HL7 Acknowledgment Delivery 
Failed";
+
+    public MllpAcknowledgementDeliveryException(byte[] hl7Message, byte[] 
hl7Acknowledgement) {
+        super(EXCEPTION_MESSAGE, hl7Message, hl7Acknowledgement);
+    }
+
+    public MllpAcknowledgementDeliveryException(byte[] hl7Message, byte[] 
hl7Acknowledgement, Throwable cause) {
+        super(EXCEPTION_MESSAGE, hl7Message, hl7Acknowledgement, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementException.java
index 624745c..992d506 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementException.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementException.java
@@ -20,20 +20,49 @@ package org.apache.camel.component.mllp;
  * Base class for HL7 Application Acknowledgement Exceptions
  */
 public abstract class MllpAcknowledgementException extends MllpException {
-    public MllpAcknowledgementException(String message) {
+    private final byte[] hl7Message;
+    private final byte[] hl7Acknowledgement;
+
+    public MllpAcknowledgementException(String message, byte[] hl7Message, 
byte[] hl7Acknowledgement) {
         super(message);
+        this.hl7Message = hl7Message;
+        this.hl7Acknowledgement = hl7Acknowledgement;
     }
 
-    public MllpAcknowledgementException(String message, byte[] mllpPayload) {
-        super(message, mllpPayload);
+    public MllpAcknowledgementException(String message, byte[] hl7Message, 
byte[] hl7Acknowledgement, Throwable cause) {
+        super(message, cause);
+        this.hl7Message = hl7Message;
+        this.hl7Acknowledgement = hl7Acknowledgement;
     }
 
-    public MllpAcknowledgementException(String message, Throwable cause) {
-        super(message, cause);
+    public byte[] getHl7Message() {
+        return hl7Message;
+    }
+
+    public byte[] getHl7Acknowledgement() {
+        return hl7Acknowledgement;
     }
 
-    public MllpAcknowledgementException(String message, byte[] mllpPayload, 
Throwable cause) {
-        super(message, mllpPayload, cause);
+    @Override
+    public String getMessage() {
+        if (isLogPhi()) {
+            return String.format("%s:\n\tHL7 Message: %s\n\tHL7 
Acknowledgement: %s",
+                    super.getMessage(), 
covertBytesToPrintFriendlyString(hl7Message), 
covertBytesToPrintFriendlyString(hl7Acknowledgement));
+        } else {
+            return super.getMessage();
+        }
     }
 
+    @Override
+    public String toString() {
+        StringBuilder stringBuilder = new 
StringBuilder(this.getClass().getName());
+
+        stringBuilder.append(": {hl7Message=")
+                .append(covertBytesToPrintFriendlyString(hl7Message))
+                .append(", hl7Acknowledgement=")
+                .append(covertBytesToPrintFriendlyString(hl7Acknowledgement))
+                .append("}");
+
+        return stringBuilder.toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementTimoutException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementTimoutException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementTimoutException.java
index 9288a14..a1cf147 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementTimoutException.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpAcknowledgementTimoutException.java
@@ -20,19 +20,11 @@ package org.apache.camel.component.mllp;
  * Raised when a MLLP Producer does not receive a HL7 acknowledgement within 
the configured timespan
  */
 public class MllpAcknowledgementTimoutException extends MllpTimeoutException {
-    public MllpAcknowledgementTimoutException(String message) {
-        super(message);
+    public MllpAcknowledgementTimoutException(String message, byte[] 
hl7Message) {
+        super(message, hl7Message);
     }
 
-    public MllpAcknowledgementTimoutException(String message, byte[] 
mllpPayload) {
-        super(message, mllpPayload);
-    }
-
-    public MllpAcknowledgementTimoutException(String message, Throwable cause) 
{
-        super(message, cause);
-    }
-
-    public MllpAcknowledgementTimoutException(String message, byte[] 
mllpPayload, Throwable cause) {
-        super(message, mllpPayload, cause);
+    public MllpAcknowledgementTimoutException(String message, byte[] 
hl7Message, Throwable cause) {
+        super(message, hl7Message, cause);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpApplicationErrorAcknowledgementException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpApplicationErrorAcknowledgementException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpApplicationErrorAcknowledgementException.java
index 7d7ecd2..5b6fed1 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpApplicationErrorAcknowledgementException.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpApplicationErrorAcknowledgementException.java
@@ -20,19 +20,13 @@ package org.apache.camel.component.mllp;
  * Raised when a MLLP Producer receives a HL7 Application Error Acknowledgement
  */
 public class MllpApplicationErrorAcknowledgementException extends 
MllpAcknowledgementException {
-    public MllpApplicationErrorAcknowledgementException(String message) {
-        super(message);
-    }
-
-    public MllpApplicationErrorAcknowledgementException(String message, byte[] 
mllpPayload) {
-        super(message, mllpPayload);
-    }
+    static final String EXCEPTION_MESSAGE = "HL7 Application Error 
Acknowledgment Received";
 
-    public MllpApplicationErrorAcknowledgementException(String message, 
Throwable cause) {
-        super(message, cause);
+    public MllpApplicationErrorAcknowledgementException(byte[] hl7Message, 
byte[] hl7Acknowledgement) {
+        super(EXCEPTION_MESSAGE, hl7Message, hl7Acknowledgement);
     }
 
-    public MllpApplicationErrorAcknowledgementException(String message, byte[] 
mllpPayload, Throwable cause) {
-        super(message, mllpPayload, cause);
+    public MllpApplicationErrorAcknowledgementException(byte[] hl7Message, 
byte[] hl7Acknowledgement, Throwable cause) {
+        super(EXCEPTION_MESSAGE, hl7Message, hl7Acknowledgement, cause);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpApplicationRejectAcknowledgementException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpApplicationRejectAcknowledgementException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpApplicationRejectAcknowledgementException.java
index ef2a39d..76cbf2c 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpApplicationRejectAcknowledgementException.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpApplicationRejectAcknowledgementException.java
@@ -20,19 +20,13 @@ package org.apache.camel.component.mllp;
  * Raised when a MLLP Producer receives a HL7 Application Reject 
Acknowledgement
  */
 public class MllpApplicationRejectAcknowledgementException extends 
MllpAcknowledgementException {
-    public MllpApplicationRejectAcknowledgementException(String message) {
-        super(message);
-    }
-
-    public MllpApplicationRejectAcknowledgementException(String message, 
byte[] mllpPayload) {
-        super(message, mllpPayload);
-    }
+    static final String EXCEPTION_MESSAGE = "HL7 Application Reject 
Acknowledgment Received";
 
-    public MllpApplicationRejectAcknowledgementException(String message, 
Throwable cause) {
-        super(message, cause);
+    public MllpApplicationRejectAcknowledgementException(byte[] hl7Message, 
byte[] hl7Acknowledgement) {
+        super(EXCEPTION_MESSAGE, hl7Message, hl7Acknowledgement);
     }
 
-    public MllpApplicationRejectAcknowledgementException(String message, 
byte[] mllpPayload, Throwable cause) {
-        super(message, mllpPayload, cause);
+    public MllpApplicationRejectAcknowledgementException(byte[] hl7Message, 
byte[] hl7Acknowledgement, Throwable cause) {
+        super(EXCEPTION_MESSAGE, hl7Message, hl7Acknowledgement, cause);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCommitErrorAcknowledgementException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCommitErrorAcknowledgementException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCommitErrorAcknowledgementException.java
index 1269c56..aef1a27 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCommitErrorAcknowledgementException.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCommitErrorAcknowledgementException.java
@@ -20,19 +20,13 @@ package org.apache.camel.component.mllp;
  * Raised when a MLLP Producer receives a HL7 Commit Error Acknowledgement
  */
 public class MllpCommitErrorAcknowledgementException extends 
MllpAcknowledgementException {
-    public MllpCommitErrorAcknowledgementException(String message) {
-        super(message);
-    }
-
-    public MllpCommitErrorAcknowledgementException(String message, byte[] 
mllpPayload) {
-        super(message, mllpPayload);
-    }
+    static final String EXCEPTION_MESSAGE = "HL7 Commit Error Acknowledgment 
Received";
 
-    public MllpCommitErrorAcknowledgementException(String message, Throwable 
cause) {
-        super(message, cause);
+    public MllpCommitErrorAcknowledgementException(byte[] hl7Message, byte[] 
hl7Acknowledgement) {
+        super(EXCEPTION_MESSAGE, hl7Message, hl7Acknowledgement);
     }
 
-    public MllpCommitErrorAcknowledgementException(String message, byte[] 
mllpPayload, Throwable cause) {
-        super(message, mllpPayload, cause);
+    public MllpCommitErrorAcknowledgementException(byte[] hl7Message, byte[] 
hl7Acknowledgement, Throwable cause) {
+        super(EXCEPTION_MESSAGE, hl7Message, hl7Acknowledgement, cause);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCommitRejectAcknowledgementException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCommitRejectAcknowledgementException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCommitRejectAcknowledgementException.java
index 99043a9..3907694 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCommitRejectAcknowledgementException.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCommitRejectAcknowledgementException.java
@@ -20,19 +20,13 @@ package org.apache.camel.component.mllp;
  * Raised when a MLLP Producer receives a HL7 Commit Reject Acknowledgement
  */
 public class MllpCommitRejectAcknowledgementException extends 
MllpAcknowledgementException {
-    public MllpCommitRejectAcknowledgementException(String message) {
-        super(message);
-    }
-
-    public MllpCommitRejectAcknowledgementException(String message, byte[] 
mllpPayload) {
-        super(message, mllpPayload);
-    }
+    static final String EXCEPTION_MESSAGE = "HL7 Commit Reject Acknowledgment 
Received";
 
-    public MllpCommitRejectAcknowledgementException(String message, Throwable 
cause) {
-        super(message, cause);
+    public MllpCommitRejectAcknowledgementException(byte[] hl7Message, byte[] 
hl7Acknowledgement) {
+        super(EXCEPTION_MESSAGE, hl7Message, hl7Acknowledgement);
     }
 
-    public MllpCommitRejectAcknowledgementException(String message, byte[] 
mllpPayload, Throwable cause) {
-        super(message, mllpPayload, cause);
+    public MllpCommitRejectAcknowledgementException(byte[] hl7Message, byte[] 
hl7Acknowledgement, Throwable cause) {
+        super(EXCEPTION_MESSAGE, hl7Message, hl7Acknowledgement, cause);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpComponent.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpComponent.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpComponent.java
index 3a67dd3..b23a421 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpComponent.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpComponent.java
@@ -26,7 +26,7 @@ import org.apache.camel.impl.UriEndpointComponent;
  * Represents the component that manages {@link MllpEndpoint}.
  */
 public class MllpComponent extends UriEndpointComponent {
-    public static final String MLLP_LOG_PHI_PROPERTY = 
"org.apache.camel.mllp.logPHI";
+    public static final String MLLP_LOG_PHI_PROPERTY = 
"org.apache.camel.component.mllp.logPHI";
 
     public MllpComponent() {
         super(MllpEndpoint.class);

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConstants.java
----------------------------------------------------------------------
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 da5eb77..8275a0e 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
@@ -23,6 +23,8 @@ public final class MllpConstants {
     public static final String MLLP_ACKNOWLEDGEMENT = 
"CamelMllpAcknowledgement";
     public static final String MLLP_ACKNOWLEDGEMENT_TYPE = 
"CamelMllpAcknowledgementType";
 
+    public static final String MLLP_ACKNOWLEDGEMENT_EXCEPTION = 
"CamelMllpAcknowledgementException";
+    public static final String MLLP_AUTO_ACKNOWLEDGE = 
"CamelMllpAutoAcknowledge";
     /*
      Connection Control Exchange Properties
       - For Consumers, "SEND" => ACKNOWLEDGEMENT

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCorruptFrameException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCorruptFrameException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCorruptFrameException.java
deleted file mode 100644
index 0310530..0000000
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpCorruptFrameException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * 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;
-
-/**
- * Raised when a MLLP Producer or consumer encounters a corrupt MLLP Frame 
while attempting
- * to read or write a MLLP payload.
- */
-public class MllpCorruptFrameException extends MllpException {
-    public MllpCorruptFrameException(String message) {
-        super(message);
-    }
-
-    public MllpCorruptFrameException(String message, byte[] mllpPayload) {
-        super(message, mllpPayload);
-    }
-
-    public MllpCorruptFrameException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public MllpCorruptFrameException(String message, byte[] mllpPayload, 
Throwable cause) {
-        super(message, mllpPayload, cause);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpException.java
index a1bb182..f0d5e84 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpException.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpException.java
@@ -20,30 +20,25 @@ package org.apache.camel.component.mllp;
  * Base class for all MLLP Exceptions, and also used as a generic MLLP 
exception
  */
 public class MllpException extends Exception {
-    private final byte[] mllpPayload;
-
     public MllpException(String message) {
         super(message);
-        this.mllpPayload = null;
-    }
-
-    public MllpException(String message, byte[] mllpPayload) {
-        super(message);
-        this.mllpPayload = mllpPayload;
     }
 
     public MllpException(String message, Throwable cause) {
         super(message, cause);
-        this.mllpPayload = null;
     }
 
-    public MllpException(String message, byte[] mllpPayload, Throwable cause) {
-        super(message, cause);
-        this.mllpPayload = mllpPayload;
+    public boolean isLogPhi() {
+        String logPhiProperty = 
System.getProperty(MllpComponent.MLLP_LOG_PHI_PROPERTY, "true");
+        return Boolean.valueOf(logPhiProperty);
     }
 
-    public byte[] getMllpPayload() {
-        return mllpPayload;
+    protected String covertBytesToPrintFriendlyString(byte[] hl7Bytes) {
+        if (null == hl7Bytes) {
+            return "null";
+        } else if (hl7Bytes.length == 0) {
+            return "";
+        }
+        return new String(hl7Bytes).replaceAll("\r", "<CR>").replaceAll("\n", 
"<LF>");
     }
-
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpFrameException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpFrameException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpFrameException.java
new file mode 100644
index 0000000..43b1281
--- /dev/null
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpFrameException.java
@@ -0,0 +1,60 @@
+/**
+ * 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;
+
+/**
+ * Raised when a MLLP Producer or consumer encounters a corrupt MLLP Frame 
while attempting
+ * to read or write a MLLP payload.
+ */
+public class MllpFrameException extends MllpException {
+    private final byte[] mllpPayload;
+
+    public MllpFrameException(String message, byte[] mllpPayload) {
+        super(message);
+        this.mllpPayload = mllpPayload;
+    }
+
+    public MllpFrameException(String message, byte[] mllpPayload, Throwable 
cause) {
+        super(message, cause);
+        this.mllpPayload = mllpPayload;
+    }
+
+    public byte[] getMllpPayload() {
+        return mllpPayload;
+    }
+
+    @Override
+    public String getMessage() {
+        if (isLogPhi()) {
+            return String.format("%s:\n\tMLLP Payload: %s", 
super.getMessage(), covertBytesToPrintFriendlyString(mllpPayload));
+        } else {
+            return super.getMessage();
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder stringBuilder = new 
StringBuilder(this.getClass().getName());
+
+        stringBuilder.append(": {mllpPayload=")
+                .append(covertBytesToPrintFriendlyString(mllpPayload))
+                .append("}");
+
+        return stringBuilder.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpInvalidAcknowledgementException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpInvalidAcknowledgementException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpInvalidAcknowledgementException.java
index 495cfae..67d5316 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpInvalidAcknowledgementException.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpInvalidAcknowledgementException.java
@@ -20,19 +20,11 @@ package org.apache.camel.component.mllp;
  * Raised when a MLLP Producer receives a HL7 Acknowledgement for which the 
HL7 Acknowledgement type cannot be determined.
  */
 public class MllpInvalidAcknowledgementException extends 
MllpAcknowledgementException {
-    public MllpInvalidAcknowledgementException(String message) {
-        super(message);
+    public MllpInvalidAcknowledgementException(String message, byte[] 
hl7Message, byte[] hl7Acknowledgement) {
+        super(message, hl7Message, hl7Acknowledgement);
     }
 
-    public MllpInvalidAcknowledgementException(String message, byte[] 
mllpPayload) {
-        super(message, mllpPayload);
-    }
-
-    public MllpInvalidAcknowledgementException(String message, Throwable 
cause) {
-        super(message, cause);
-    }
-
-    public MllpInvalidAcknowledgementException(String message, byte[] 
mllpPayload, Throwable cause) {
-        super(message, mllpPayload, cause);
+    public MllpInvalidAcknowledgementException(String message, byte[] 
hl7Message, byte[] hl7Acknowledgement, Throwable cause) {
+        super(message, hl7Message, hl7Acknowledgement, cause);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpClientProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpClientProducer.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpClientProducer.java
index da04286..5793aea 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpClientProducer.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpClientProducer.java
@@ -19,7 +19,6 @@ package org.apache.camel.component.mllp;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.Socket;
-import java.net.SocketAddress;
 import java.net.SocketException;
 import java.net.SocketTimeoutException;
 
@@ -111,7 +110,7 @@ public class MllpTcpClientProducer extends DefaultProducer {
                 acknowledgementBytes = MllpUtil.closeFrame(socket, 
endpoint.receiveTimeout, endpoint.readTimeout);
             }
         } catch (SocketTimeoutException timeoutEx) {
-            exchange.setException(new 
MllpAcknowledgementTimoutException("Acknowledgement timout", timeoutEx));
+            exchange.setException(new 
MllpAcknowledgementTimoutException("Acknowledgement timout", hl7MessageBytes, 
timeoutEx));
             return;
         } catch (MllpException mllpEx) {
             exchange.setException(mllpEx);
@@ -146,14 +145,14 @@ public class MllpTcpClientProducer extends 
DefaultProducer {
                             // Found the beginning of the MSA - the next two 
bytes should be our acknowledgement code
                             msaStartIndex = i + 1;
                             if (bA != acknowledgementBytes[i + 5] && bC != 
acknowledgementBytes[i + 5]) {
-                                exchange.setException(new 
MllpInvalidAcknowledgementException(new String(acknowledgementBytes)));
+                                exchange.setException(new 
MllpInvalidAcknowledgementException(new String(acknowledgementBytes, i + 5, 2), 
hl7MessageBytes, acknowledgementBytes));
                             } else {
                                 String acknowledgemenTypeString;
                                 switch (acknowledgementBytes[i + 6]) {
                                 case bA:
                                     // We have an AA or CA- make sure that's 
the end of the field
                                     if (fieldDelim != acknowledgementBytes[i + 
7]) {
-                                        exchange.setException(new 
MllpInvalidAcknowledgementException(new String(acknowledgementBytes)));
+                                        exchange.setException(new 
MllpInvalidAcknowledgementException(new String(acknowledgementBytes, i + 5, 3), 
hl7MessageBytes, acknowledgementBytes));
                                     }
                                     if (bA == acknowledgementBytes[i + 5]) {
                                         
message.setHeader(MLLP_ACKNOWLEDGEMENT_TYPE, "AA");
@@ -165,24 +164,24 @@ public class MllpTcpClientProducer extends 
DefaultProducer {
                                     // We have an AE or CE
                                     if (bA == acknowledgementBytes[i + 5]) {
                                         
message.setHeader(MLLP_ACKNOWLEDGEMENT_TYPE, "AE");
-                                        exchange.setException(new 
MllpApplicationErrorAcknowledgementException(new String(acknowledgementBytes)));
+                                        exchange.setException(new 
MllpApplicationErrorAcknowledgementException(hl7MessageBytes, 
acknowledgementBytes));
                                     } else {
                                         
message.setHeader(MLLP_ACKNOWLEDGEMENT_TYPE, "CE");
-                                        exchange.setException(new 
MllpCommitErrorAcknowledgementException(new String(acknowledgementBytes)));
+                                        exchange.setException(new 
MllpCommitErrorAcknowledgementException(hl7MessageBytes, acknowledgementBytes));
                                     }
                                     break;
                                 case bR:
                                     // We have an AR or CR
                                     if (bA == acknowledgementBytes[i + 5]) {
                                         
message.setHeader(MLLP_ACKNOWLEDGEMENT_TYPE, "AR");
-                                        exchange.setException(new 
MllpApplicationRejectAcknowledgementException(new 
String(acknowledgementBytes)));
+                                        exchange.setException(new 
MllpApplicationRejectAcknowledgementException(hl7MessageBytes, 
acknowledgementBytes));
                                     } else {
                                         
message.setHeader(MLLP_ACKNOWLEDGEMENT_TYPE, "CR");
-                                        exchange.setException(new 
MllpCommitRejectAcknowledgementException(new String(acknowledgementBytes)));
+                                        exchange.setException(new 
MllpCommitRejectAcknowledgementException(hl7MessageBytes, 
acknowledgementBytes));
                                     }
                                     break;
                                 default:
-                                    exchange.setException(new 
MllpInvalidAcknowledgementException(new String(acknowledgementBytes)));
+                                    exchange.setException(new 
MllpInvalidAcknowledgementException(new String(acknowledgementBytes, i + 5, 2), 
hl7MessageBytes, acknowledgementBytes));
                                 }
                             }
 
@@ -194,7 +193,7 @@ public class MllpTcpClientProducer extends DefaultProducer {
             }
             if (-1 == msaStartIndex) {
                 // Didn't find an MSA
-                exchange.setException(new 
MllpInvalidAcknowledgementException(new String(acknowledgementBytes)));
+                exchange.setException(new 
MllpInvalidAcknowledgementException("MSA Not found in acknowledgement", 
hl7MessageBytes, acknowledgementBytes));
             }
         }
         // Check AFTER_SEND Properties

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpServerConsumer.java
----------------------------------------------------------------------
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 61f29db..1648b8a 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
@@ -33,18 +33,14 @@ import org.apache.camel.Exchange;
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
+import 
org.apache.camel.component.mllp.impl.AcknowledgmentSynchronizationAdapter;
 import org.apache.camel.component.mllp.impl.MllpUtil;
-import org.apache.camel.converter.IOConverter;
 import org.apache.camel.impl.DefaultConsumer;
-import org.apache.camel.processor.mllp.Hl7AcknowledgementGenerationException;
 import org.apache.camel.processor.mllp.Hl7AcknowledgementGenerator;
 import org.apache.camel.util.IOHelper;
 
-import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_ACKNOWLEDGEMENT;
-import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_ACKNOWLEDGEMENT_TYPE;
+import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_AUTO_ACKNOWLEDGE;
 import static org.apache.camel.component.mllp.MllpConstants.MLLP_CHARSET;
-import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_CLOSE_CONNECTION_AFTER_SEND;
-import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_CLOSE_CONNECTION_BEFORE_SEND;
 import static org.apache.camel.component.mllp.MllpConstants.MLLP_EVENT_TYPE;
 import static org.apache.camel.component.mllp.MllpConstants.MLLP_LOCAL_ADDRESS;
 import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_MESSAGE_CONTROL;
@@ -53,8 +49,6 @@ import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_PROCESSING_ID;
 import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_RECEIVING_APPLICATION;
 import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_RECEIVING_FACILITY;
 import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_REMOTE_ADDRESS;
-import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_RESET_CONNECTION_AFTER_SEND;
-import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_RESET_CONNECTION_BEFORE_SEND;
 import static org.apache.camel.component.mllp.MllpConstants.MLLP_SECURITY;
 import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_SENDING_APPLICATION;
 import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_SENDING_FACILITY;
@@ -428,128 +422,20 @@ public class MllpTcpServerConsumer extends 
DefaultConsumer {
 
                 message.setHeader(MLLP_LOCAL_ADDRESS, 
clientSocket.getLocalAddress().toString());
                 message.setHeader(MLLP_REMOTE_ADDRESS, 
clientSocket.getRemoteSocketAddress());
+                message.setHeader(MLLP_AUTO_ACKNOWLEDGE, endpoint.autoAck);
 
                 populateHl7DataHeaders(exchange, message, hl7MessageBytes);
 
+                exchange.addOnCompletion(new 
AcknowledgmentSynchronizationAdapter(clientSocket, hl7MessageBytes));
 
                 log.debug("Calling processor");
                 try {
                     getProcessor().process(exchange);
-                    // processed the message - send the acknowledgement
-
-                    // Check BEFORE_SEND Properties
-                    if 
(exchange.getProperty(MLLP_RESET_CONNECTION_BEFORE_SEND, boolean.class)) {
-                        MllpUtil.resetConnection(clientSocket);
-                        return;
-                    } else if 
(exchange.getProperty(MLLP_CLOSE_CONNECTION_BEFORE_SEND, boolean.class)) {
-                        MllpUtil.closeConnection(clientSocket);
-                    }
-
-                    // Find the acknowledgement body
-                    byte[] acknowledgementMessageBytes = 
exchange.getProperty(MLLP_ACKNOWLEDGEMENT, byte[].class);
-                    String acknowledgementMessageType = null;
-                    if (null == acknowledgementMessageBytes) {
-                        if (!endpoint.autoAck) {
-                            exchange.setException(new 
MllpInvalidAcknowledgementException("Automatic Acknowledgement is disabled and 
the "
-                                    + MLLP_ACKNOWLEDGEMENT + " exchange 
property is null or cannot be converted to byte[]"));
-                            return;
-                        }
-
-                        String acknowledgmentTypeProperty = 
exchange.getProperty(MLLP_ACKNOWLEDGEMENT_TYPE, String.class);
-                        try {
-                            if (null == acknowledgmentTypeProperty) {
-                                if (null == exchange.getException()) {
-                                    acknowledgementMessageType = "AA";
-                                    acknowledgementMessageBytes = 
acknowledgementGenerator.generateApplicationAcceptAcknowledgementMessage(hl7MessageBytes);
-                                } else {
-                                    acknowledgementMessageType = "AE";
-                                    acknowledgementMessageBytes = 
acknowledgementGenerator.generateApplicationErrorAcknowledgementMessage(hl7MessageBytes);
-                                }
-                            } else {
-                                switch (acknowledgmentTypeProperty) {
-                                case "AA":
-                                    acknowledgementMessageType = "AA";
-                                    acknowledgementMessageBytes = 
acknowledgementGenerator.generateApplicationAcceptAcknowledgementMessage(hl7MessageBytes);
-                                    break;
-                                case "AE":
-                                    acknowledgementMessageType = "AE";
-                                    acknowledgementMessageBytes = 
acknowledgementGenerator.generateApplicationErrorAcknowledgementMessage(hl7MessageBytes);
-                                    break;
-                                case "AR":
-                                    acknowledgementMessageType = "AR";
-                                    acknowledgementMessageBytes = 
acknowledgementGenerator.generateApplicationRejectAcknowledgementMessage(hl7MessageBytes);
-                                    break;
-                                default:
-                                    exchange.setException(new 
Hl7AcknowledgementGenerationException("Unsupported acknowledgment type: " + 
acknowledgmentTypeProperty));
-                                    return;
-                                }
-                            }
-                        } catch (Hl7AcknowledgementGenerationException 
ackGenerationException) {
-                            exchange.setException(ackGenerationException);
-                        }
-                    } else {
-                        final byte bM = 77;
-                        final byte bS = 83;
-                        final byte bA = 65;
-                        final byte bE = 69;
-                        final byte bR = 82;
-
-                        final byte fieldSeparator = hl7MessageBytes[3];
-                        // Acknowledgment is specified in exchange property - 
determine the acknowledgement type
-                        for (int i = 0; i < hl7MessageBytes.length; ++i) {
-                            if (SEGMENT_DELIMITER == i) {
-                                if (i + 7 < hl7MessageBytes.length // Make 
sure we don't run off the end of the message
-                                        && bM == hl7MessageBytes[i + 1] && bS 
== hl7MessageBytes[i + 2] && bA == hl7MessageBytes[i + 3] && fieldSeparator == 
hl7MessageBytes[i + 4]) {
-                                    if (fieldSeparator != hl7MessageBytes[i + 
7]) {
-                                        log.warn("MSA-1 is longer than 2-bytes 
- ignoring trailing bytes");
-                                    }
-                                    // Found MSA - pull acknowledgement bytes
-                                    byte[] acknowledgmentTypeBytes = new 
byte[2];
-                                    acknowledgmentTypeBytes[0] = 
hl7MessageBytes[i + 5];
-                                    acknowledgmentTypeBytes[1] = 
hl7MessageBytes[i + 6];
-                                    acknowledgementMessageType = 
IOConverter.toString(acknowledgmentTypeBytes, exchange);
-
-                                    // Verify it's a valid acknowledgement code
-                                    if (bA != acknowledgmentTypeBytes[0]) {
-                                        switch 
(acknowledgementMessageBytes[1]) {
-                                        case bA:
-                                        case bR:
-                                        case bE:
-                                            break;
-                                        default:
-                                            log.warn("Invalid acknowledgement 
type [" + acknowledgementMessageType + "] found in message - should be AA, AE 
or AR");
-                                        }
-                                    }
-
-                                    // if the MLLP_ACKNOWLEDGEMENT_TYPE 
property is set on the exchange, make sure it matches
-                                    String acknowledgementTypeProperty = 
exchange.getProperty(MLLP_ACKNOWLEDGEMENT_TYPE, String.class);
-                                    if (null != acknowledgementTypeProperty && 
!acknowledgementTypeProperty.equals(acknowledgementMessageType)) {
-                                        log.warn("Acknowledgement type found 
in message [" + acknowledgementMessageType + "] does not match "
-                                                + MLLP_ACKNOWLEDGEMENT_TYPE + 
" exchange property value [" + acknowledgementTypeProperty + "] - using value 
found in message");
-                                    }
-                                }
-                            }
-                        }
-                    }
-
-                    // Send the acknowledgement
-                    log.debug("Writing Acknowledgement");
-                    MllpUtil.writeFramedPayload(clientSocket, 
acknowledgementMessageBytes);
-                    exchange.getIn().setHeader(MLLP_ACKNOWLEDGEMENT, 
acknowledgementMessageBytes);
-                    exchange.getIn().setHeader(MLLP_ACKNOWLEDGEMENT_TYPE, 
acknowledgementMessageType);
-                    exchange.setProperty(MLLP_ACKNOWLEDGEMENT, 
acknowledgementMessageBytes);
-                    exchange.setProperty(MLLP_ACKNOWLEDGEMENT_TYPE, 
acknowledgementMessageType);
-
-                    // Check AFTER_SEND Properties
-                    if (exchange.getProperty(MLLP_RESET_CONNECTION_AFTER_SEND, 
boolean.class)) {
-                        MllpUtil.resetConnection(clientSocket);
-                        return;
-                    } else if 
(exchange.getProperty(MLLP_CLOSE_CONNECTION_AFTER_SEND, boolean.class)) {
-                        MllpUtil.closeConnection(clientSocket);
-                    }
-
-                } catch (Exception e) {
-                    exchange.setException(e);
+                } catch (RuntimeException runtimeEx) {
+                    throw runtimeEx;
+                } catch (Exception ex) {
+                    log.error("Unexpected exception processing exchange", ex);
+                    throw new RuntimeException("Unexpected exception 
processing exchange", ex);
                 }
 
             }

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTimeoutException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTimeoutException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTimeoutException.java
index 0e54772..7c2014a 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTimeoutException.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTimeoutException.java
@@ -20,20 +20,40 @@ package org.apache.camel.component.mllp;
  * Raised when a MLLP Producer or Consumer encounter a timeout reading a 
message
  */
 public class MllpTimeoutException extends MllpException {
-    public MllpTimeoutException(String message) {
+    private final byte[] hl7Message;
+
+    public MllpTimeoutException(String message, byte[] hl7Message) {
         super(message);
+        this.hl7Message = hl7Message;
     }
 
-    public MllpTimeoutException(String message, byte[] mllpPayload) {
-        super(message, mllpPayload);
+    public MllpTimeoutException(String message, byte[] hl7Message, Throwable 
cause) {
+        super(message, cause);
+        this.hl7Message = hl7Message;
     }
 
-    public MllpTimeoutException(String message, Throwable cause) {
-        super(message, cause);
+    public byte[] getHl7Message() {
+        return hl7Message;
     }
 
-    public MllpTimeoutException(String message, byte[] mllpPayload, Throwable 
cause) {
-        super(message, mllpPayload, cause);
+    @Override
+    public String getMessage() {
+        if (isLogPhi()) {
+            return String.format("%s:\n\tHL7 Message: %s", super.getMessage(), 
covertBytesToPrintFriendlyString(hl7Message));
+        } else {
+            return super.getMessage();
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder stringBuilder = new 
StringBuilder(this.getClass().getName());
+
+        stringBuilder.append(": {hl7Message=")
+                .append(covertBytesToPrintFriendlyString(hl7Message))
+                .append("}");
+
+        return stringBuilder.toString();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpWriteException.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpWriteException.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpWriteException.java
index 43fe740..dd5bf42 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpWriteException.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpWriteException.java
@@ -20,20 +20,40 @@ package org.apache.camel.component.mllp;
  * Raised when a MLLP Producer or consumer encounter an error transmitting data
  */
 public class MllpWriteException extends MllpException {
-    public MllpWriteException(String message) {
-        super(message);
-    }
+    private final byte[] mllpPayload;
 
     public MllpWriteException(String message, byte[] mllpPayload) {
-        super(message, mllpPayload);
+        super(message);
+        this.mllpPayload = mllpPayload;
     }
 
-    public MllpWriteException(String message, Throwable cause) {
+    public MllpWriteException(String message, byte[] mllpPayload, Throwable 
cause) {
         super(message, cause);
+        this.mllpPayload = mllpPayload;
     }
 
-    public MllpWriteException(String message, byte[] mllpPayload, Throwable 
cause) {
-        super(message, mllpPayload, cause);
+    public byte[] getMllpPayload() {
+        return mllpPayload;
+    }
+
+    @Override
+    public String getMessage() {
+        if (isLogPhi()) {
+            return String.format("%s:\n\tMLLP Payload: %s", 
super.getMessage(), covertBytesToPrintFriendlyString(mllpPayload));
+        } else {
+            return super.getMessage();
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder stringBuilder = new 
StringBuilder(this.getClass().getName());
+
+        stringBuilder.append(": {mllpPayload=")
+                .append(covertBytesToPrintFriendlyString(mllpPayload))
+                .append("}");
+
+        return stringBuilder.toString();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/impl/AcknowledgmentSynchronizationAdapter.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/impl/AcknowledgmentSynchronizationAdapter.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/impl/AcknowledgmentSynchronizationAdapter.java
new file mode 100644
index 0000000..6d4b76c
--- /dev/null
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/impl/AcknowledgmentSynchronizationAdapter.java
@@ -0,0 +1,212 @@
+/**
+ * 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.impl;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Route;
+import org.apache.camel.component.mllp.MllpAcknowledgementDeliveryException;
+import org.apache.camel.component.mllp.MllpException;
+import org.apache.camel.component.mllp.MllpInvalidAcknowledgementException;
+import org.apache.camel.converter.IOConverter;
+import org.apache.camel.processor.mllp.Hl7AcknowledgementGenerationException;
+import org.apache.camel.processor.mllp.Hl7AcknowledgementGenerator;
+import org.apache.camel.support.SynchronizationAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_ACKNOWLEDGEMENT;
+import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_ACKNOWLEDGEMENT_EXCEPTION;
+import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_ACKNOWLEDGEMENT_TYPE;
+import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_AUTO_ACKNOWLEDGE;
+import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_CLOSE_CONNECTION_AFTER_SEND;
+import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_CLOSE_CONNECTION_BEFORE_SEND;
+import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_RESET_CONNECTION_AFTER_SEND;
+import static 
org.apache.camel.component.mllp.MllpConstants.MLLP_RESET_CONNECTION_BEFORE_SEND;
+import static org.apache.camel.component.mllp.MllpEndpoint.SEGMENT_DELIMITER;
+
+public class AcknowledgmentSynchronizationAdapter extends 
SynchronizationAdapter {
+    Logger log = LoggerFactory.getLogger(this.getClass());
+    final byte[] originalHl7MessageBytes;
+    Hl7AcknowledgementGenerator acknowledgementGenerator = new 
Hl7AcknowledgementGenerator();
+    private Socket clientSocket;
+
+    public AcknowledgmentSynchronizationAdapter(Socket clientSocket, byte[] 
hl7MessageBytes) {
+        this.clientSocket = clientSocket;
+        this.originalHl7MessageBytes = hl7MessageBytes;
+    }
+
+    @Override
+    public int getOrder() {
+        return HIGHEST;
+    }
+
+    @Override
+    public void onAfterRoute(Route route, Exchange exchange) {
+        log.info("onAfterRoute");
+
+        // Check BEFORE_SEND Properties
+        if (exchange.getProperty(MLLP_RESET_CONNECTION_BEFORE_SEND, 
boolean.class)) {
+            MllpUtil.resetConnection(clientSocket);
+            return;
+        } else if (exchange.getProperty(MLLP_CLOSE_CONNECTION_BEFORE_SEND, 
boolean.class)) {
+            MllpUtil.closeConnection(clientSocket);
+            return;
+        }
+
+        // Find the acknowledgement body
+        // TODO:  Enhance this to say whether or not the acknowlment is 
missing or just of an uncovertable type
+        byte[] acknowledgementMessageBytes = 
exchange.getProperty(MLLP_ACKNOWLEDGEMENT, byte[].class);
+        String acknowledgementMessageType = null;
+        if (null == acknowledgementMessageBytes) {
+            boolean autoAck = exchange.getProperty(MLLP_AUTO_ACKNOWLEDGE, 
true, boolean.class);
+            if (!autoAck) {
+                exchange.setException(new 
MllpInvalidAcknowledgementException("Automatic Acknowledgement is disabled and 
the "
+                        + MLLP_ACKNOWLEDGEMENT + " exchange property is null 
or cannot be converted to byte[]", originalHl7MessageBytes, 
acknowledgementMessageBytes));
+                return;
+            }
+
+            String acknowledgmentTypeProperty = 
exchange.getProperty(MLLP_ACKNOWLEDGEMENT_TYPE, String.class);
+            try {
+                if (null == acknowledgmentTypeProperty) {
+                    if (null == exchange.getException()) {
+                        acknowledgementMessageType = "AA";
+                        acknowledgementMessageBytes = 
acknowledgementGenerator.generateApplicationAcceptAcknowledgementMessage(originalHl7MessageBytes);
+                    } else {
+                        acknowledgementMessageType = "AE";
+                        acknowledgementMessageBytes = 
acknowledgementGenerator.generateApplicationErrorAcknowledgementMessage(originalHl7MessageBytes);
+                    }
+                } else {
+                    switch (acknowledgmentTypeProperty) {
+                    case "AA":
+                        acknowledgementMessageType = "AA";
+                        acknowledgementMessageBytes = 
acknowledgementGenerator.generateApplicationAcceptAcknowledgementMessage(originalHl7MessageBytes);
+                        break;
+                    case "AE":
+                        acknowledgementMessageType = "AE";
+                        acknowledgementMessageBytes = 
acknowledgementGenerator.generateApplicationErrorAcknowledgementMessage(originalHl7MessageBytes);
+                        break;
+                    case "AR":
+                        acknowledgementMessageType = "AR";
+                        acknowledgementMessageBytes = 
acknowledgementGenerator.generateApplicationRejectAcknowledgementMessage(originalHl7MessageBytes);
+                        break;
+                    default:
+                        exchange.setException(new 
Hl7AcknowledgementGenerationException("Unsupported acknowledgment type: " + 
acknowledgmentTypeProperty));
+                        return;
+                    }
+                }
+            } catch (Hl7AcknowledgementGenerationException 
ackGenerationException) {
+                exchange.setProperty(MLLP_ACKNOWLEDGEMENT_EXCEPTION, 
ackGenerationException);
+                exchange.setException(ackGenerationException);
+            }
+        } else {
+            final byte bM = 77;
+            final byte bS = 83;
+            final byte bA = 65;
+            final byte bE = 69;
+            final byte bR = 82;
+
+            final byte fieldSeparator = originalHl7MessageBytes[3];
+            // Acknowledgment is specified in exchange property - determine 
the acknowledgement type
+            for (int i = 0; i < originalHl7MessageBytes.length; ++i) {
+                if (SEGMENT_DELIMITER == i) {
+                    if (i + 7 < originalHl7MessageBytes.length // Make sure we 
don't run off the end of the message
+                            && bM == originalHl7MessageBytes[i + 1] && bS == 
originalHl7MessageBytes[i + 2]
+                            && bA == originalHl7MessageBytes[i + 3] && 
fieldSeparator == originalHl7MessageBytes[i + 4]) {
+                        if (fieldSeparator != originalHl7MessageBytes[i + 7]) {
+                            log.warn("MSA-1 is longer than 2-bytes - ignoring 
trailing bytes");
+                        }
+                        // Found MSA - pull acknowledgement bytes
+                        byte[] acknowledgmentTypeBytes = new byte[2];
+                        acknowledgmentTypeBytes[0] = originalHl7MessageBytes[i 
+ 5];
+                        acknowledgmentTypeBytes[1] = originalHl7MessageBytes[i 
+ 6];
+                        try {
+                            acknowledgementMessageType = 
IOConverter.toString(acknowledgmentTypeBytes, exchange);
+                        } catch (IOException ioEx) {
+                            throw new RuntimeException("Failed to convert 
acknowledgement message to string", ioEx);
+                        }
+
+                        // Verify it's a valid acknowledgement code
+                        if (bA != acknowledgmentTypeBytes[0]) {
+                            switch (acknowledgementMessageBytes[1]) {
+                            case bA:
+                            case bR:
+                            case bE:
+                                break;
+                            default:
+                                log.warn("Invalid acknowledgement type [" + 
acknowledgementMessageType + "] found in message - should be AA, AE or AR");
+                            }
+                        }
+
+                        // if the MLLP_ACKNOWLEDGEMENT_TYPE property is set on 
the exchange, make sure it matches
+                        String acknowledgementTypeProperty = 
exchange.getProperty(MLLP_ACKNOWLEDGEMENT_TYPE, String.class);
+                        if (null != acknowledgementTypeProperty && 
!acknowledgementTypeProperty.equals(acknowledgementMessageType)) {
+                            log.warn("Acknowledgement type found in message [" 
+ acknowledgementMessageType + "] does not match "
+                                    + MLLP_ACKNOWLEDGEMENT_TYPE + " exchange 
property value [" + acknowledgementTypeProperty + "] - using value found in 
message");
+                        }
+                    }
+                }
+            }
+        }
+
+        Message message;
+        if (exchange.hasOut()) {
+            message = exchange.getOut();
+        } else {
+            message = exchange.getIn();
+        }
+        message.setHeader(MLLP_ACKNOWLEDGEMENT, acknowledgementMessageBytes);
+        message.setHeader(MLLP_ACKNOWLEDGEMENT_TYPE, 
acknowledgementMessageType);
+
+        // Send the acknowledgement
+        log.debug("Sending Acknowledgement");
+        try {
+            MllpUtil.writeFramedPayload(clientSocket, 
acknowledgementMessageBytes);
+        } catch (MllpException mllpEx) {
+            log.error("MLLP Acknowledgement failure: {}", mllpEx);
+            MllpAcknowledgementDeliveryException deliveryException = new 
MllpAcknowledgementDeliveryException(originalHl7MessageBytes, 
acknowledgementMessageBytes, mllpEx);
+            exchange.setProperty(MLLP_ACKNOWLEDGEMENT_EXCEPTION, 
deliveryException);
+            exchange.setException(deliveryException);
+        }
+
+        // Check AFTER_SEND Properties
+        if (exchange.getProperty(MLLP_RESET_CONNECTION_AFTER_SEND, 
boolean.class)) {
+            MllpUtil.resetConnection(clientSocket);
+            return;
+        } else if (exchange.getProperty(MLLP_CLOSE_CONNECTION_AFTER_SEND, 
boolean.class)) {
+            MllpUtil.closeConnection(clientSocket);
+        }
+
+        super.onAfterRoute(route, exchange);
+    }
+
+    @Override
+    public void onComplete(Exchange exchange) {
+        log.info("onComplete");
+        super.onComplete(exchange);
+
+    }
+
+    @Override
+    public void onFailure(Exchange exchange) {
+        log.warn("onFailure");
+        super.onFailure(exchange);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/impl/MllpUtil.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/impl/MllpUtil.java
 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/impl/MllpUtil.java
index 276d3ae..20315e7 100644
--- 
a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/impl/MllpUtil.java
+++ 
b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/impl/MllpUtil.java
@@ -26,8 +26,8 @@ import java.net.SocketException;
 import java.net.SocketTimeoutException;
 
 import org.apache.camel.component.mllp.MllpComponent;
-import org.apache.camel.component.mllp.MllpCorruptFrameException;
 import org.apache.camel.component.mllp.MllpException;
+import org.apache.camel.component.mllp.MllpFrameException;
 import org.apache.camel.component.mllp.MllpTimeoutException;
 import org.apache.camel.component.mllp.MllpWriteException;
 import org.slf4j.Logger;
@@ -65,10 +65,10 @@ public final class MllpUtil {
      * @param socket the Socket to read
      * @throws SocketTimeoutException    thrown if a timeout occurs while 
looking for the beginning of the MLLP frame, but
      *                                   nothing is yet available - this is 
NOT an error condition
-     * @throws MllpCorruptFrameException if the MLLP Frame is corrupted in 
some way
+     * @throws MllpFrameException if the MLLP Frame is corrupted in some way
      * @throws MllpException             for other unexpected error conditions
      */
-    public static boolean openFrame(Socket socket, int receiveTimeout, int 
readTimeout) throws SocketTimeoutException, MllpCorruptFrameException, 
MllpException {
+    public static boolean openFrame(Socket socket, int receiveTimeout, int 
readTimeout) throws SocketTimeoutException, MllpFrameException, MllpException {
         if (socket.isConnected() && !socket.isClosed()) {
             InputStream socketInputStream = MllpUtil.getInputStream(socket);
 
@@ -125,7 +125,7 @@ public final class MllpUtil {
                         }
                         resetConnection(socket);
 
-                        throw new MllpCorruptFrameException("END_OF_STREAM 
read while looking for the beginning of the MLLP frame", 
outOfFrameData.toByteArray());
+                        throw new MllpFrameException("END_OF_STREAM read while 
looking for the beginning of the MLLP frame", outOfFrameData.toByteArray());
                     case START_OF_BLOCK:
                         if (isLogPHIEnabled(LOG)) {
                             LOG.warn("The beginning of the MLLP frame was 
preceded by out-of-frame data - eating data: {}", 
outOfFrameData.toString().replace('\r', '\n'));
@@ -133,7 +133,7 @@ public final class MllpUtil {
                             LOG.warn("The beginning of the MLLP frame was 
preceded by out-of-frame data - eating data");
                         }
 
-                        throw new MllpCorruptFrameException("The beginning of 
the MLLP frame was preceded by out-of-frame data", 
outOfFrameData.toByteArray());
+                        throw new MllpFrameException("The beginning of the 
MLLP frame was preceded by out-of-frame data", outOfFrameData.toByteArray());
                     default:
                         // still reading out-of-frame data
                         outOfFrameData.write(readByte);
@@ -150,7 +150,7 @@ public final class MllpUtil {
 
                 resetConnection(socket);
 
-                throw new MllpCorruptFrameException("Timeout looking for the 
beginning of the MLLP frame, and out-of-frame data had been read", 
outOfFrameData.toByteArray());
+                throw new MllpFrameException("Timeout looking for the 
beginning of the MLLP frame, and out-of-frame data had been read", 
outOfFrameData.toByteArray());
             } catch (IOException e) {
                 if (isLogPHIEnabled(LOG)) {
                     LOG.error("Exception encountered looking for the beginning 
of the MLLP frame, and out-of-frame data had been read - resetting connection 
and eating out-of-frame data: {}",
@@ -161,7 +161,7 @@ public final class MllpUtil {
 
                 resetConnection(socket);
 
-                throw new MllpCorruptFrameException("Exception encountered 
looking for the beginning of the MLLP frame, and out-of-frame data had been 
read", outOfFrameData.toByteArray());
+                throw new MllpFrameException("Exception encountered looking 
for the beginning of the MLLP frame, and out-of-frame data had been read", 
outOfFrameData.toByteArray());
             }
         }
 
@@ -182,10 +182,10 @@ public final class MllpUtil {
      * @param socket the Socket to be read
      * @return the payload of the MLLP-Enveloped message as a byte[]
      * @throws MllpTimeoutException      thrown if a timeout occurs while 
closing the MLLP frame
-     * @throws MllpCorruptFrameException if the MLLP Frame is corrupted in 
some way
+     * @throws MllpFrameException if the MLLP Frame is corrupted in some way
      * @throws MllpException             for other unexpected error conditions
      */
-    public static byte[] closeFrame(Socket socket, int receiveTimeout, int 
readTimeout) throws MllpTimeoutException, MllpCorruptFrameException, 
MllpException {
+    public static byte[] closeFrame(Socket socket, int receiveTimeout, int 
readTimeout) throws MllpTimeoutException, MllpFrameException, MllpException {
         if (socket.isConnected() && !socket.isClosed()) {
             InputStream socketInputStream = MllpUtil.getInputStream(socket);
             // TODO:  Come up with an intelligent way to size this stream
@@ -204,7 +204,7 @@ public final class MllpUtil {
 
                         resetConnection(socket);
 
-                        throw new MllpCorruptFrameException("END_OF_STREAM 
read while looking for the end of the MLLP frame", payload.size() > 0 ? 
payload.toByteArray() : null);
+                        throw new MllpFrameException("END_OF_STREAM read while 
looking for the end of the MLLP frame", payload.size() > 0 ? 
payload.toByteArray() : null);
                     case START_OF_BLOCK:
                         if (isLogPHIEnabled(LOG)) {
                             LOG.error("A new MLLP frame was opened before the 
previous frame was closed - resetting connection and eating data: {}", 
payload.toString().replace('\r', '\n'));
@@ -214,7 +214,7 @@ public final class MllpUtil {
 
                         resetConnection(socket);
 
-                        throw new MllpCorruptFrameException("A new MLLP frame 
was opened before the previous frame was closed", payload.size() > 0 ? 
payload.toByteArray() : null);
+                        throw new MllpFrameException("A new MLLP frame was 
opened before the previous frame was closed", payload.size() > 0 ? 
payload.toByteArray() : null);
                     case END_OF_BLOCK:
                         if (END_OF_DATA != socketInputStream.read()) {
                             if (isLogPHIEnabled(LOG)) {
@@ -226,7 +226,7 @@ public final class MllpUtil {
 
                             resetConnection(socket);
 
-                            throw new MllpCorruptFrameException("The MLLP 
frame was partially closed - END_OF_BLOCK was not followed by END_OF_DATA",
+                            throw new MllpFrameException("The MLLP frame was 
partially closed - END_OF_BLOCK was not followed by END_OF_DATA",
                                     payload.size() > 0 ? payload.toByteArray() 
: null);
                         }
                         socket.setSoTimeout(receiveTimeout);
@@ -249,7 +249,7 @@ public final class MllpUtil {
 
                 resetConnection(socket);
 
-                throw new MllpCorruptFrameException("Timeout looking for the 
end of the MLLP frame", payload.size() > 0 ? payload.toByteArray() : null, 
timeoutEx);
+                throw new MllpFrameException("Timeout looking for the end of 
the MLLP frame", payload.size() > 0 ? payload.toByteArray() : null, timeoutEx);
             } catch (IOException ioEx) {
                 if (0 < payload.size()) {
                     if (isLogPHIEnabled(LOG)) {
@@ -263,7 +263,7 @@ public final class MllpUtil {
 
                 resetConnection(socket);
 
-                throw new MllpException("Exception encountered looking for the 
end of the MLLP frame", payload.size() > 0 ? payload.toByteArray() : null, 
ioEx);
+                throw new MllpFrameException("Exception encountered looking 
for the end of the MLLP frame", payload.size() > 0 ? payload.toByteArray() : 
null, ioEx);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementExceptionTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementExceptionTest.java
 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementExceptionTest.java
new file mode 100644
index 0000000..439a3c9
--- /dev/null
+++ 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementExceptionTest.java
@@ -0,0 +1,127 @@
+/**
+ * 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.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertEquals;
+
+public class MllpAcknowledgementExceptionTest {
+    static final String HL7_MESSAGE = 
"MSH|^~\\&|APP_A|FAC_A|^org^sys||||ADT^A04^ADT_A04|||2.6" + '\r'
+            + "PID|1||1100832^^^^PI||TEST^FIG||98765432|U||R|435 MAIN 
STREET^^LONGMONT^CO^80503||123-456-7890|||S" + '\r'
+            + '\r' + '\n';
+
+    static final String HL7_ACKNOWLEDGEMENT = 
"MSH|^~\\&|^org^sys||APP_A|FAC_A|||ACK^A04^ADT_A04|||2.6" + '\r' + "MSA|AA|" + 
'\r' + '\n';
+
+    static final String EXCEPTION_MESSAGE_WITH_LOG_PHI_DISABLED = 
MllpAcknowledgementDeliveryException.EXCEPTION_MESSAGE;
+    static final String EXCEPTION_MESSAGE_WITH_LOG_PHI_ENABLED =
+            String.format("%s:\n\tHL7 Message: %s\n\tHL7 Acknowledgement: %s",
+                    MllpAcknowledgementDeliveryException.EXCEPTION_MESSAGE,
+                    new String(HL7_MESSAGE).replaceAll("\r", 
"<CR>").replaceAll("\n", "<LF>"),
+                    new String(HL7_ACKNOWLEDGEMENT).replaceAll("\r", 
"<CR>").replaceAll("\n", "<LF>")
+            );
+
+    Exception exception;
+
+    Logger log = LoggerFactory.getLogger(this.getClass());
+
+    @Before
+    public void setUp() throws Exception {
+        exception = new 
MllpAcknowledgementDeliveryException(HL7_MESSAGE.getBytes(), 
HL7_ACKNOWLEDGEMENT.getBytes());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        System.clearProperty(MllpComponent.MLLP_LOG_PHI_PROPERTY);
+    }
+
+
+    @Test
+    public void testLogPhiDefault() throws Exception {
+        String exceptionMessage = exception.getMessage();
+
+        assertEquals(EXCEPTION_MESSAGE_WITH_LOG_PHI_ENABLED, exceptionMessage);
+    }
+
+    @Test
+    public void testLogPhiDisabled() throws Exception {
+        System.setProperty(MllpComponent.MLLP_LOG_PHI_PROPERTY, "false");
+
+        String exceptionMessage = exception.getMessage();
+
+        assertEquals(EXCEPTION_MESSAGE_WITH_LOG_PHI_DISABLED, 
exceptionMessage);
+    }
+
+    @Test
+    public void testLogPhiEnabled() throws Exception {
+        System.setProperty(MllpComponent.MLLP_LOG_PHI_PROPERTY, "true");
+
+        String exceptionMessage = exception.getMessage();
+
+        assertEquals(EXCEPTION_MESSAGE_WITH_LOG_PHI_ENABLED, exceptionMessage);
+    }
+
+    @Test
+    public void testNullMessage() throws Exception {
+        final String expectedMessage =
+                String.format("%s:\n\tHL7 Message: null\n\tHL7 
Acknowledgement: %s",
+                        MllpAcknowledgementDeliveryException.EXCEPTION_MESSAGE,
+                        new String(HL7_ACKNOWLEDGEMENT).replaceAll("\r", 
"<CR>").replaceAll("\n", "<LF>")
+                );
+
+        exception = new MllpAcknowledgementDeliveryException(null, 
HL7_ACKNOWLEDGEMENT.getBytes());
+
+        System.setProperty(MllpComponent.MLLP_LOG_PHI_PROPERTY, "true");
+        String exceptionMessage = exception.getMessage();
+
+        assertEquals(expectedMessage, exceptionMessage);
+    }
+
+    @Test
+    public void testNullAcknowledgement() throws Exception {
+        final String expectedMessage =
+                String.format("%s:\n\tHL7 Message: %s\n\tHL7 Acknowledgement: 
null",
+                        MllpAcknowledgementDeliveryException.EXCEPTION_MESSAGE,
+                        new String(HL7_MESSAGE).replaceAll("\r", 
"<CR>").replaceAll("\n", "<LF>")
+                );
+
+        exception = new 
MllpAcknowledgementDeliveryException(HL7_MESSAGE.getBytes(), null);
+
+        System.setProperty(MllpComponent.MLLP_LOG_PHI_PROPERTY, "true");
+        String exceptionMessage = exception.getMessage();
+
+        assertEquals(expectedMessage, exceptionMessage);
+    }
+
+    @Test
+    public void testToString() throws Exception {
+        final String expectedString =
+                
"org.apache.camel.component.mllp.MllpAcknowledgementDeliveryException: "
+                        + "{hl7Message="
+                        +      
"MSH|^~\\&|APP_A|FAC_A|^org^sys||||ADT^A04^ADT_A04|||2.6<CR>"
+                        +      
"PID|1||1100832^^^^PI||TEST^FIG||98765432|U||R|435 MAIN 
STREET^^LONGMONT^CO^80503||123-456-7890|||S<CR><CR><LF>"
+                        + ", hl7Acknowledgement="
+                        +      
"MSH|^~\\&|^org^sys||APP_A|FAC_A|||ACK^A04^ADT_A04|||2.6<CR>MSA|AA|<CR><LF>"
+                        + "}";
+
+        assertEquals(expectedString, exception.toString());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpFrameExceptionTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpFrameExceptionTest.java
 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpFrameExceptionTest.java
new file mode 100644
index 0000000..ca713dc
--- /dev/null
+++ 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpFrameExceptionTest.java
@@ -0,0 +1,101 @@
+/**
+ * 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.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class MllpFrameExceptionTest {
+    static final String EXCEPTION_MESSAGE = "Test Frame Exception";
+
+    static final String HL7_MESSAGE =
+            "MSH|^~\\&|APP_A|FAC_A|^org^sys||||ADT^A04^ADT_A04|||2.6" + '\r'
+            + "PID|1||1100832^^^^PI||TEST^FIG||98765432|U||R|435 MAIN 
STREET^^LONGMONT^CO^80503||123-456-7890|||S" + '\r'
+            + '\r' + '\n';
+
+    static final String EXCEPTION_MESSAGE_WITH_LOG_PHI_DISABLED = 
EXCEPTION_MESSAGE;
+    static final String EXCEPTION_MESSAGE_WITH_LOG_PHI_ENABLED =
+            String.format(String.format("%s:\n\tMLLP Payload: %s",
+                    EXCEPTION_MESSAGE,
+                    new String(HL7_MESSAGE).replaceAll("\r", 
"<CR>").replaceAll("\n", "<LF>"))
+            );
+
+    Exception exception;
+
+    @Before
+    public void setUp() throws Exception {
+        exception = new MllpFrameException(EXCEPTION_MESSAGE, 
HL7_MESSAGE.getBytes());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        System.clearProperty(MllpComponent.MLLP_LOG_PHI_PROPERTY);
+    }
+
+    @Test
+    public void testLogPhiDefault() throws Exception {
+        String exceptionMessage = exception.getMessage();
+
+        assertEquals(EXCEPTION_MESSAGE_WITH_LOG_PHI_ENABLED, exceptionMessage);
+    }
+
+    @Test
+    public void testLogPhiDisabled() throws Exception {
+        System.setProperty(MllpComponent.MLLP_LOG_PHI_PROPERTY, "false");
+
+        String exceptionMessage = exception.getMessage();
+
+        assertEquals(EXCEPTION_MESSAGE_WITH_LOG_PHI_DISABLED, 
exceptionMessage);
+    }
+
+    @Test
+    public void testLogPhiEnabled() throws Exception {
+        System.setProperty(MllpComponent.MLLP_LOG_PHI_PROPERTY, "true");
+
+        String exceptionMessage = exception.getMessage();
+
+        assertEquals(EXCEPTION_MESSAGE_WITH_LOG_PHI_ENABLED, exceptionMessage);
+    }
+
+    @Test
+    public void testNullPayload() throws Exception {
+        final String expectedMessage = String.format("%s:\n\tMLLP Payload: 
null", EXCEPTION_MESSAGE);
+
+        exception = new MllpFrameException(EXCEPTION_MESSAGE, null);
+
+        System.setProperty(MllpComponent.MLLP_LOG_PHI_PROPERTY, "true");
+        String exceptionMessage = exception.getMessage();
+
+        assertEquals(expectedMessage, exceptionMessage);
+    }
+    @Test
+    public void testToString() throws Exception {
+        final String expectedString =
+                "org.apache.camel.component.mllp.MllpFrameException: "
+                        + "{mllpPayload="
+                        +      
"MSH|^~\\&|APP_A|FAC_A|^org^sys||||ADT^A04^ADT_A04|||2.6<CR>"
+                        +      
"PID|1||1100832^^^^PI||TEST^FIG||98765432|U||R|435 MAIN 
STREET^^LONGMONT^CO^80503||123-456-7890|||S<CR><CR><LF>"
+                        + "}";
+
+        assertEquals(expectedString, exception.toString());
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpProducerConsumerLoopbackTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpProducerConsumerLoopbackTest.java
 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpProducerConsumerLoopbackTest.java
index d96b24d..116e67c 100644
--- 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpProducerConsumerLoopbackTest.java
+++ 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpProducerConsumerLoopbackTest.java
@@ -30,12 +30,12 @@ import org.apache.camel.test.junit4.CamelTestSupport;
 import org.apache.camel.test.mllp.PassthroughProcessor;
 import org.hamcrest.CoreMatchers;
 import org.junit.Assert;
-import org.junit.Ignore;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 import static org.apache.camel.test.mllp.Hl7MessageGenerator.generateMessage;
+import static org.junit.Assume.assumeTrue;
 
-@Ignore("Fails sometimes on CI server with address already in use")
 public class MllpProducerConsumerLoopbackTest extends CamelTestSupport {
     int mllpPort = AvailablePortFinder.getNextAvailable();
     String mllpHost = "localhost";
@@ -56,6 +56,10 @@ public class MllpProducerConsumerLoopbackTest extends 
CamelTestSupport {
         return context;
     }
 
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        assumeTrue("Skipping test running in CI server - Fails sometimes on CI 
server with address already in use", System.getenv("BUILD_ID") == null);
+    }
 
     @Override
     protected RouteBuilder[] createRouteBuilders() throws Exception {

http://git-wip-us.apache.org/repos/asf/camel/blob/62715117/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpTcpClientProducerTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpTcpClientProducerTest.java
 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpTcpClientProducerTest.java
index 2dcd40b..6edc48c 100644
--- 
a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpTcpClientProducerTest.java
+++ 
b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpTcpClientProducerTest.java
@@ -67,7 +67,6 @@ public class MllpTcpClientProducerTest extends 
CamelTestSupport {
 
     @Override
     protected RouteBuilder createRouteBuilder() {
-
         return new RouteBuilder() {
             int connectTimeout = 1000;
             int responseTimeout = 1000;
@@ -76,34 +75,27 @@ public class MllpTcpClientProducerTest extends 
CamelTestSupport {
             public void configure() throws Exception {
                 errorHandler(
                         
defaultErrorHandler().allowRedeliveryWhileStopping(false));
-
-                onException(MllpCorruptFrameException.class)
+                onException(MllpFrameException.class)
                         .handled(true)
                         .logHandled(false)
                         .to(frame);
-
                 onException(MllpTimeoutException.class)
                         .handled(true)
                         .logHandled(false)
                         .to(timeout);
-
                 onCompletion()
                         .onFailureOnly().log(LoggingLevel.ERROR, "Processing 
Failed");
-
                 from(source.getDefaultEndpoint())
                         .routeId("mllp-sender-test-route")
                         .log(LoggingLevel.INFO, "Sending Message: 
$simple{header[CamelHL7MessageControl]}")
                         
.toF("mllp://%s:%d?connectTimeout=%d&receiveTimeout=%d",
                                 mllpServer.getListenHost(), 
mllpServer.getListenPort(), connectTimeout, responseTimeout)
                         .to(acknowledged);
-
                 from("direct://handle-timeout")
                         .log(LoggingLevel.ERROR, "Response Timeout")
                         .rollback();
-
             }
         };
-
     }
 
     @Test

Reply via email to