...
- HL7 MLLP codec for Mina
- Agnostic data format using either plain String objects or HAPI HL7 model objects.
- Type Converter from/to HAPI and String
- HL7 DataFormat using HAPI library
- Even more ease-of-use as it's integrated well with
the
- the camel-
mina (
Camel 2.11
: camel-
- mina2
)
- component.
Maven users will need to add the following dependency to their pom.xml
for this component:
...
To expose a HL7 listener service we reuse the existing mina/ mina2 component where we just use the HL7MLLPCodec
as codec.
...
div |
class |
confluenceTableSmall |
|
Name |
Default Value |
Description |
startByte |
0x0b |
The start byte spanning the HL7 payload. |
endByte1 |
0x1c |
The first end byte spanning the HL7 payload. |
endByte2 |
0x0d |
The 2nd end byte spanning the HL7 payload. |
charset |
JVM Default |
The encoding (is a charset name) to use for the codec. If not provided, Camel will use the JVM default Charset. |
convertLFtoCR |
true (Camel 2.11:false ) |
Will convert \n to \r (0x0d , 13 decimal) as HL7 stipulates \r as segment terminators. The HAPI library requires the use of \r . |
validate |
true |
Whether HAPI Parser should validate or not. |
parser |
ca.uhn.hl7v2.parser.PipeParser |
Camel 2.11: To use a custom parser. Must be of type ca.uhn.hl7v2.parser.Parser . |
|
Exposing a HL7 listener
In our Spring XML file, we configure an endpoint to listen for HL7 requests using TCP:
...
div |
class |
confluenceTableSmall |
|
Key |
MSH field |
Example |
CamelHL7SendingApplication |
MSH-3 |
MYSERVER |
CamelHL7SendingFacility |
MSH-4 |
MYSERVERAPP |
CamelHL7ReceivingApplication |
MSH-5 |
MYCLIENT |
CamelHL7ReceivingFacility |
MSH-6 |
MYCLIENTAPP |
CamelHL7Timestamp |
MSH-7 |
20071231235900 |
CamelHL7Security |
MSH-8 |
null |
CamelHL7MessageType |
MSH-9-1 |
ADT |
CamelHL7TriggerEvent |
MSH-9-2 |
A01 |
CamelHL7MessageControl |
MSH-10 |
1234 |
CamelHL7ProcessingId |
MSH-11 |
P |
CamelHL7VersionId |
MSH-12 |
2.4 |
CamelHL7Context |
- |
(Camel 2.14) contains the HapiContext that was used to parse the message |
|
All headers except CamelHL7Context
are String
types. If a header value is missing, its value is null
.
...
div |
class |
confluenceTableSmall |
|
Option |
Default |
Description |
validate |
true |
Whether the HAPI Parser should validate using the default validation rules. Camel 2.11: better Better use the parser or hapiContext option and initialize the parser it with the desired HAPI ValidationContext |
parser |
ca.uhn.hl7v2.parser.GenericParser |
Camel 2.11: To use Use a custom parser. Must be of type ca.uhn.hl7v2.parser.Parser . Note that GenericParser also allows to parse XML-encoded HL7v2 messages |
hapiContext |
ca.uhn.hl7v2.DefaultHapiContext |
Camel 2.14: Use a custom HAPI context that can define a custom parser, custom ValidationContext etc. This gives you full control over the HL7 parsing and rendering process. |
|
Dependencies
To use HL7 in your Camel routes you'll need to add a dependency on camel-hl7 listed above, which implements this data format.
...
Codeblock |
|
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v24</artifactId>
<version>1<version>2.2</version>
<!-- use the same version as your hapi-base version -->
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v25</artifactId>
<version>1<version>2.2</version>
<!-- use the same version as your hapi-base version -->
</dependency>
|
...
Codeblock |
|
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-osgi-base</artifactId>
<version>1<version>2.2</version>
</dependency>
|
Terser language
...
HAPI provides a Terser class that provides access to fields using a commonly used terse location specification syntax. The Terser language allows to use this syntax to extract values from messages and to use them as expressions and predicates for filtering, content-based routing etc.
...
Codeblock |
|
import static org.apache.camel.component.hl7.HL7.terser;
...
// extract patient ID from field QRD-8 in the QRY_A19 message above and put into message header
from("direct:test1")
.setHeader("PATIENT_ID",terser("QRD-8(0)-1"))
.to("mock:test1");
// continue processing if extracted field equals a message header
from("direct:test2")
.filter(terser("QRD-8(0)-1")
.isEqualTo(header("PATIENT_ID"))
.to("mock:test2");
|
HL7 Validation predicate
...
Often it is preferable to parse a HL7v2 message and validate it against a HAPI ValidationContext in a separate step afterwards.
...
Codeblock |
|
import static org.apache.camel.component.hl7.HL7.messageConformsTo;
import ca.uhn.hl7v2.validation.impl.DefaultValidation;
...
// Use standard or define your own validation rules
ValidationContext defaultContext = new DefaultValidation();
// Throws PredicateValidationException if message does not validate
from("direct:test1").validate(messageConformsTo(defaultContext)).to("mock:test1");
|
HL7
...
Validation predicate using the HapiContext (Camel 2.
...
14)
The HAPI Context is always configured with a ValidationContext (or a ValidationRuleBuilder), so you can access the validation rules indirectly. Furthermore, when unmarshalling the HL7DataFormat forwards the configured HAPI context in the CamelHL7Context
header, and the validation rules of this context can be easily reused:
Codeblock |
|
import static org.apache.camel.component.hl7.HL7.messageConformsTo;
import static org.apache.camel.component.hl7.HL7.messageConforms
...
HapiContext hapiContext = new DefaultHapiContext();
hapiContext.getParserConfiguration().setValidating(false); // don't validate during parsing
// customize HapiContext some more ... e.g. enforce that PID-8 in ADT_A01 messages of version 2.4 is not empty
ValidationRuleBuilder builder = new ValidationRuleBuilder() {
@Override
protected void configure() {
forVersion(Version.V24)
.message("ADT", "A01")
.terser("PID-8", not(empty()));
}
};
hapiContext.setValidationRuleBuilder(builder);
HL7DataFormat hl7 = new HL7DataFormat();
hl7.setHapiContext(hapiContext);
from("direct:test1")
.unmarshal(hl7) // uses the GenericParser returned from the HapiContext
.validate(messageConforms()) // uses the validation rules returned from the HapiContext
// equivalent with .validate(messageConformsTo(hapiContext))
// route continues from here
|
HL7 Acknowledgement _expression_
A common task in HL7v2 processing is to generate an acknowledgement message as response to an incoming HL7v2 message, e.g. based on a validation result. The ack
_expression_ lets us accomplish this very elegantly:
...