...
HL7
...
Component
...
The
...
hl7
...
component
...
is
...
used
...
for
...
working
...
with
...
the
...
HL7
...
MLLP
...
protocol
...
and
...
...
...
...
using
...
the
...
...
...
.
This component supports the following:
- 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
...
...
- (
...
- Camel
...
- 2.11
...
- :
...
...
- )
...
- component.
...
Maven
...
users
...
will
...
need
...
to
...
add
...
the
...
following
...
dependency
...
to
...
their
...
pom.xml
...
for
...
this
...
component:
Code Block | ||||
---|---|---|---|---|
| ||||
{code:xml} <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-hl7</artifactId> <version>x.x.x</version> <!-- use the same version as your Camel core version --> </dependency> {code} h3. HL7 MLLP protocol HL7 is often used with the HL7 MLLP protocol that is a text based TCP socket based protocol. This component ships with a Mina Codec that conforms to the MLLP protocol so you can easily expose a HL7 listener that accepts HL7 requests over the TCP transport. To expose a HL7 listener service we reuse the existing mina/mina2 component where we just use the {{HL7MLLPCodec}} as codec. The HL7 MLLP codec has the following options: |
HL7 MLLP protocol
HL7 is often used with the HL7 MLLP protocol that is a text based TCP socket based protocol. This component ships with a Mina Codec that conforms to the MLLP protocol so you can easily expose a HL7 listener that accepts HL7 requests over the TCP transport.
To expose a HL7 listener service we reuse the existing mina/mina2 component where we just use the HL7MLLPCodec
as codec.
The HL7 MLLP codec has the following options:
Wiki Markup |
---|
{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|http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html]) to use for the codec. If not provided, Camel will use the [JVM default Charset|http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html#defaultCharset()]. |
| {{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}}. |
{div}
h4. |
Exposing
...
a
...
HL7
...
listener
...
In
...
our
...
Spring
...
XML
...
file,
...
we
...
configure
...
an
...
endpoint
...
to
...
listen
...
for
...
HL7
...
requests
...
using
...
TCP:
Code Block | ||||
---|---|---|---|---|
| ||||
{code:xml} <endpoint id="hl7listener" uri="mina:tcp://localhost:8888?sync=true&codec=#hl7codec"/> <!-- Camel 2.11: uri="mina2:tcp... --> {code} |
Notice
...
that
...
we
...
use
...
TCP
...
on
...
localhost
...
on
...
port
...
8888
...
.
...
We
...
use
...
sync=true
...
to
...
indicate
...
that
...
this
...
listener
...
is
...
synchronous
...
and
...
therefore
...
will
...
return
...
a
...
HL7
...
response
...
to
...
the
...
caller.
...
Then
...
we
...
setup
...
mina
...
to
...
use
...
our
...
HL7
...
codec
...
with
...
codec=#hl7codec
...
.
...
Notice
...
that
...
hl7codec
...
is
...
just
...
a
...
Spring
...
bean
...
ID,
...
so
...
we
...
could
...
have
...
named
...
it
...
mygreatcodecforhl7
...
or
...
whatever.
...
The
...
codec
...
is
...
also
...
set
...
up
...
in
...
the
...
Spring
...
XML
...
file:
Code Block | ||||
---|---|---|---|---|
| ||||
{code:xml} <bean id="hl7codec" class="org.apache.camel.component.hl7.HL7MLLPCodec"> <property name="charset" value="iso-8859-1"/> </bean> {code} |
Above
...
we
...
also
...
configure
...
the
...
charset
...
encoding
...
to
...
use
...
(
...
iso-8859-1
...
).
...
The
...
endpoint
...
hl7listener
...
can
...
then
...
be
...
used
...
in
...
a
...
route
...
as
...
a
...
consumer,
...
as
...
this
...
Java
...
DSL
...
example
...
illustrates:
Code Block | ||||
---|---|---|---|---|
| ||||
{code:java} from("hl7listener").to("patientLookupService"); {code} |
This
...
is
...
a
...
very
...
simple
...
route
...
that
...
will
...
listen
...
for
...
HL7
...
and
...
route
...
it
...
to
...
a
...
service
...
named
...
patientLookupService
...
that
...
is
...
also
...
a
...
Spring
...
bean
...
ID
...
we
...
have
...
configured
...
in
...
the
...
Spring
...
XML
...
as:
Code Block | ||||
---|---|---|---|---|
| ||||
{code:xml} <bean id="patientLookupService" class="com.mycompany.healthcare.service.PatientLookupService"/> {code} |
Another
...
powerful
...
feature
...
of
...
Camel
...
is
...
that
...
we
...
can
...
have
...
our
...
business
...
logic
...
in
...
POJO
...
classes
...
that
...
is
...
not
...
tied
...
to
...
Camel
...
as
...
shown
...
here:
Code Block | ||||
---|---|---|---|---|
| ||||
{code:java} import ca.uhn.hl7v2.HL7Exception; import ca.uhn.hl7v2.model.Message; import ca.uhn.hl7v2.model.v24.segment.QRD; public class PatientLookupService { public Message lookupPatient(Message input) throws HL7Exception { QRD qrd = (QRD)input.get("QRD"); String patientId = qrd.getWhoSubjectFilter(0).getIDNumber().getValue(); // find patient data based on the patient id and create a HL7 model object with the response Message response = ... create and set response data return response } {code} |
Notice
...
that
...
this
...
class
...
uses
...
just
...
imports
...
from
...
the
...
HAPI
...
library
...
and
...
not
...
from
...
Camel.
...
HL7
...
Model
...
using
...
java.lang.String
...
The
...
HL7MLLP
...
codec
...
uses
...
plain
...
String
...
as
...
its
...
data
...
format.
...
Camel
...
uses
...
its
...
...
...
to
...
convert
...
to/from
...
strings
...
to
...
the
...
HAPI
...
HL7
...
model
...
objects.
...
However,
...
you
...
can
...
use
...
plain
...
String
...
objects
...
if
...
you
...
prefer,
...
for
...
instance
...
if
...
you
...
wish
...
to
...
parse
...
the
...
data
...
yourself.
...
See
...
samples
...
for
...
such
...
an
...
example.
...
HL7v2
...
Model
...
using
...
HAPI
...
The
...
HL7v2
...
model
...
uses
...
Java
...
objects
...
from
...
the
...
HAPI
...
library.
...
Using
...
this
...
library,
...
we
...
can
...
encode
...
and
...
decode
...
from
...
the
...
EDI
...
format
...
(ER7)
...
that
...
is
...
mostly
...
used
...
with
...
HL7v2.
...
With
...
this
...
model
...
you
...
can
...
code
...
with
...
Java
...
objects
...
instead
...
of
...
the
...
EDI
...
based
...
HL7
...
format
...
that
...
can
...
be
...
hard
...
for
...
humans
...
to
...
read
...
and
...
understand.
...
The
...
sample
...
below
...
is
...
a
...
request
...
to
...
lookup
...
a
...
patient
...
with
...
the
...
patient
...
ID
...
0101701234
...
.
Code Block |
---|
} MSH|^~\\&|MYSENDER|MYRECEIVER|MYAPPLICATION||200612211200||QRY^A19|1234|P|2.4 QRD|200612211200|R|I|GetPatient|||1^RD|0101701234|DEM|| {code} |
Using
...
the
...
HL7
...
model
...
we
...
can
...
work
...
with
...
the
...
data
...
as
...
a
...
ca.uhn.hl7v2.model.Message
...
object.
...
To
...
retrieve
...
the
...
patient
...
ID
...
in
...
the
...
message
...
above,
...
you
...
can
...
do
...
this
...
in
...
Java
...
code:
Code Block | ||||
---|---|---|---|---|
| ||||
{code:java} Message msg = exchange.getIn().getBody(Message.class); QRD qrd = (QRD)msg.get("QRD"); String patientId = qrd.getWhoSubjectFilter(0).getIDNumber().getValue(); {code} |
If
...
you
...
know
...
the
...
message
...
type
...
in
...
advance,
...
you
...
can
...
be
...
more
...
type-safe:
Code Block | ||||
---|---|---|---|---|
| ||||
{code:java} QRY_A19 msg = exchange.getIn().getBody(QRY_A19.class); String patientId = msg.getQRD().getWhoSubjectFilter(0).getIDNumber().getValue(); {code} |
Camel
...
has
...
built-in
...
type
...
converters,
...
so
...
when
...
this
...
operation
...
is
...
invoked:
Code Block | ||||
---|---|---|---|---|
| ||||
{code:java} Message msg = exchange.getIn().getBody(Message.class); {code} |
Camel
...
will
...
convert
...
the
...
received
...
HL7
...
data from String
to Message
. This is powerful when combined with the HL7 listener, then you as the end-user don't have to work with byte[]
, String
or any other simple object formats. You can just use the HAPI HL7v2 model objects.
Include Page | ||||
---|---|---|---|---|
|
Message Headers
The unmarshal operation adds these MSH fields as headers on the Camel message:
Wiki Markup |
---|
from {{String}} to {{Message}}. This is powerful when combined with the HL7 listener, then you as the end-user don't have to work with {{byte[]}}, {{String}} or any other simple object formats. You can just use the HAPI HL7v2 model objects. {include:HL7 DataFormat} h3. Message Headers The *unmarshal* operation adds these MSH fields as headers on the Camel message: {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}} | {div} |
All
...
headers
...
are
...
String
...
types.
...
If
...
a
...
header
...
value
...
is
...
missing,
...
its
...
value
...
is
...
null
.
Options
The HL7 Data Format supports the following options:
Wiki Markup |
---|
{}}. h3. Options The HL7 Data Format supports the following options: {div:class=confluenceTableSmall} || Option || Default || Description || | {{validate}} | true | Whether the HAPI Parser should validate using the default validation rules. *Camel 2.11:* better use the {{parser}} option and initialize the parser with the desired HAPI {{ValidationContext}} | | {{parser}} | {{ca.uhn.hl7v2.parser.GenericParser}} | *Camel 2.11:* To use a custom parser. Must be of type {{ca.uhn.hl7v2.parser.Parser}}. Note that {{GenericParser}} also allows to parse XML-encoded HL7v2 messages. | {div} h3. Dependencies To use HL7 in your Camel routes |
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.
...
The
...
HAPI
...
library
...
since
...
Version
...
0.6
...
has
...
been
...
split
...
into
...
a
...
base library and several structure libraries, one for each HL7v2 message version:
- v2.1 structures library
- v2.2 structures library
- v2.3 structures library
- v2.3.1 structures library
- v2.4 structures library
- v2.5 structures library
- v2.5.1 structures library
- v2.6 structures library
By default camel-hl7
only references the HAPI base library. Applications are responsible for including structure libraries themselves. For example, if a application works with HL7v2 message versions 2.4 and 2.5 then the following dependencies must be added:
Code Block | ||||
---|---|---|---|---|
| ||||
<dependency> <groupId>ca.uhn.hapi</groupId> <artifactId>hapi-structures-v24</artifactId> <version>1.2</version> <!-- use the same version as your hapi-base version --> </dependency> library|http://repo1.maven.org/maven2/ca/uhn/hapi/hapi-base] and several structure libraries, one for each HL7v2 message version: * [v2.1 structures library|http://repo1.maven.org/maven2/ca/uhn/hapi/hapi-structures-v21] * [v2.2 structures library|http://repo1.maven.org/maven2/ca/uhn/hapi/hapi-structures-v22] * [v2.3 structures library|http://repo1.maven.org/maven2/ca/uhn/hapi/hapi-structures-v23] * [v2.3.1 structures library|http://repo1.maven.org/maven2/ca/uhn/hapi/hapi-structures-v231] * [v2.4 structures library|http://repo1.maven.org/maven2/ca/uhn/hapi/hapi-structures-v24] * [v2.5 structures library|http://repo1.maven.org/maven2/ca/uhn/hapi/hapi-structures-v25] * [v2.5.1 structures library|http://repo1.maven.org/maven2/ca/uhn/hapi/hapi-structures-v251] * [v2.6 structures library|http://repo1.maven.org/maven2/ca/uhn/hapi/hapi-structures-v26] By default {{camel-hl7}} only references the HAPI [base library|http://repo1.maven.org/maven2/ca/uhn/hapi/hapi-base]. Applications are responsible for including structure libraries themselves. For example, if a application works with HL7v2 message versions 2.4 and 2.5 then the following dependencies must be added: {code:xml} <dependency> <groupId>ca.uhn.hapi</groupId> <artifactId>hapi-structures-v24</artifactId> <version>1.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.2</version> <!-- use the same version as your hapi-base version --> </dependency> {code} Alternatively, an OSGi bundle containing the base library, all structures libraries and required dependencies (on the bundle classpath) can be downloaded from the [central Maven repository|http://repo1.maven.org/maven2/ca/uhn/hapi/hapi-osgi-base]. {code:xml} <dependency> <groupId>ca.uhn.hapi</groupId> <artifactId>hapi-osgistructures-base<v25</artifactId> <version>1.2</version> <!-- use the same version as your hapi-base version --> </dependency> |
Alternatively, an OSGi bundle containing the base library, all structures libraries and required dependencies (on the bundle classpath) can be downloaded from the central Maven repository.
Code Block | ||||
---|---|---|---|---|
| ||||
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-osgi-base</artifactId>
<version>1.2</version>
</dependency>
|
Terser language (Camel 2.11)
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.
Sample:
Code Block | ||||
---|---|---|---|---|
| ||||
</dependency> {code} h3. Terser language (*Camel 2.11*) [HAPI|http://hl7api.sourceforge.net] provides a [Terser|http://hl7api.sourceforge.net/base/apidocs/ca/uhn/hl7v2/util/Terser.html] 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. Sample: {code:java} 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"); {code} h3. HL7 Validation predicate (*Camel |
HL7 Validation predicate (Camel 2.11
...
)
...
Often
...
it
...
is
...
preferable to parse a HL7v2 message and validate it against a HAPI ValidationContext in a separate step afterwards.
Sample:
Code Block | ||||
---|---|---|---|---|
| ||||
to parse a HL7v2 message and validate it against a HAPI [ValidationContext|http://hl7api.sourceforge.net/base/apidocs/ca/uhn/hl7v2/validation/ValidationContext.html] in a separate step afterwards. Sample: {code:java} 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"); {code} h3. HL7 Acknowledgement expression (*Camel |
HL7 Acknowledgement expression (Camel 2.11
...
)
...
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:
Code Block | ||||
---|---|---|---|---|
| ||||
{code:java}
import static org.apache.camel.component.hl7.HL7.messageConformsTo;
import static org.apache.camel.component.hl7.HL7.ack;
import ca.uhn.hl7v2.validation.impl.DefaultValidation;
...
// Use standard or define your own validation rules
ValidationContext defaultContext = new DefaultValidation();
from("direct:test1")
.onException(Exception.class)
.handled(true)
.transform(ack()) // auto-generates negative ack because of exception in Exchange
.end()
.validate(messageConformsTo(defaultContext))
// do something meaningful here
...
// acknowledgement
.transform(ack())
|
More Samples
In the following example we send a HL7 request to a HL7 listener and retrieves a response. We use plain String
types in this example:
Wiki Markup |
---|
{code} h3. More Samples In the following example we send a HL7 request to a HL7 listener and retrieves a response. We use plain {{String}} types in this example: {snippet:id=e2|lang=java|url=camel/trunk/components/camel-hl7/src/test/java/org/apache/camel/component/hl7/HL7MLLPCodecTest.java} |
In
...
the
...
next
...
sample,
...
we
...
want
...
to
...
route
...
HL7
...
requests
...
from
...
our
...
HL7
...
listener
...
to
...
our
...
business
...
logic.
...
We
...
have
...
our
...
business
...
logic
...
in
...
a
...
plain
...
POJO
...
that
...
we
...
have
...
registered
...
in
...
the
...
registry
...
as
...
hl7service
...
=
...
for
...
instance
...
using
...
Spring
...
and
...
letting
...
the
...
bean
...
id
...
=
...
hl7service
...
.
...
Our
...
business
...
logic
...
is
...
a
...
plain
...
POJO
...
only
...
using
...
the
...
HAPI
...
library
...
so
...
we
...
have
...
these
...
operations
...
defined:
Wiki Markup |
---|
{snippet:id=e2|lang=java|url=camel/trunk/components/camel-hl7/src/test/java/org/apache/camel/component/hl7/HL7RouteTest.java} |
Then
...
we
...
set
...
up
...
the
...
Camel
...
routes
...
using
...
the
...
RouteBuilder
...
as
...
follows:
Wiki Markup |
---|
{snippet:id=e1|lang=java|url=camel/trunk/components/camel-hl7/src/test/java/org/apache/camel/component/hl7/HL7RouteTest.java} |
Notice
...
that
...
we
...
use
...
the
...
HL7
...
DataFormat
...
to
...
enrich
...
our
...
Camel
...
Message
...
with
...
the
...
MSH
...
fields
...
preconfigured
...
on
...
the
...
Camel
...
Message.
...
This
...
lets
...
us
...
much
...
more
...
easily
...
define
...
our
...
routes
...
using
...
the
...
fluent
...
builders.
...
If
...
we
...
do
...
not
...
use
...
the
...
HL7
...
DataFormat,
...
then
...
we
...
do
...
not
...
gains
...
these
...
headers
...
and
...
we
...
must
...
resort
...
to
...
a
...
different
...
technique
...
for
...
computing
...
the
...
MSH
...
trigger
...
event
...
(=
...
what
...
kind
...
of
...
HL7
...
message
...
it
...
is).
...
This
...
is
...
a
...
big
...
advantage
...
of
...
the
...
HL7
...
DataFormat
...
over
...
the
...
plain
...
HL7
...
type
...
converters.
...
Sample
...
using
...
plain
...
String
...
objects
...
In
...
this
...
sample
...
we
...
use
...
plain
...
String
...
objects
...
as
...
the
...
data
...
format,
...
that
...
we
...
send,
...
process
...
and
...
receive.
...
As
...
the
...
sample
...
is
...
part
...
of
...
a
...
unit
...
test,
...
there
...
is
...
some
...
code
...
for
...
assertions,
...
but
...
you
...
should
...
be
...
able
...
to
...
understand
...
what
...
happens.
...
First
...
we
...
send
...
the
...
plain
...
string,
...
Hello
...
World
...
,
...
to
...
the
...
HL7MLLPCodec
...
and
...
receive
...
the
...
response
...
as
...
a
...
plain
...
string,
...
Bye
...
World
.
Wiki Markup |
---|
}}. {snippet:id=e1|lang=java|url=camel/trunk/components/camel-hl7/src/test/java/org/apache/camel/component/hl7/HL7MLLPCodecPlainStringTest.java} |
Here
...
we
...
process
...
the
...
incoming
...
data
...
as
...
plain
...
String
...
and
...
send
...
the
...
response
...
also
...
as
...
plain
...
String:
Wiki Markup |
---|
{snippet:id=e2|lang=java|url=camel/trunk/components/camel-hl7/src/test/java/org/apache/camel/component/hl7/HL7MLLPCodecPlainStringTest.java} {include:Endpoint See Also} |
Include Page | ||||
---|---|---|---|---|
|