Cameleer

Cameleer / Use cases / HL7 over MLLP

Healthcare integration

HL7 v2 over MLLP, FHIR, and an acknowledgement that means it

A hospital gateway receives ADT and lab messages from the HIS over MLLP, reads the patient id with a terser path, posts the message to the EHR and acknowledges after delivery. The route is Camel YAML; the runtime is one native binary that fits next to the other software on the gateway.

AA / AEacknowledgement after the EHR accepted the message, not before
R4–R5FHIR R4, R4B, R5 and DSTU3 through the fhir component
~10 MBof memory for a running route; a 20 MB container image
5redeliveries with a delay before the sender is told to resend

The tested route

From examples/edge/hl7-mllp-to-http.camel.yaml, which the test suite runs against an embedded EHR mock. ADT messages are forwarded; other types are acknowledged and dropped.

- route:
    id: hl7-to-ehr
    errorHandler:
      defaultErrorHandler:
        redeliveryPolicy:
          maximumRedeliveries: 5
          redeliveryDelay: "{{env:RETRY_DELAY_MS:2000}}"
    from:
      uri: "mllp://{{env:MLLP_HOST:0.0.0.0}}:{{env:MLLP_PORT:2575}}"
      steps:
        - filter:
            simple: "${header.CamelMllpEventType} == 'ADT'"
            steps:
              - setHeader:
                  name: X-Patient-Id
                  hl7terser: "PID-3-1"
              - setHeader:
                  name: X-Message-Control-Id
                  simple: "${header.CamelMllpMessageControlId}"
              - setHeader:
                  name: Content-Type
                  constant: application/hl7-v2
              - enrich:
                  uri: "{{env:EHR_URL:http://localhost:9000}}/hl7/v2?httpMethod=POST"

What happens on failure

  • The EHR call is retried five times with a delay; the MLLP connection waits.
  • If it still fails, the acknowledgement is AE: the sending system keeps the message and resends it later. Nothing is lost on the gateway.
  • Set CamelMllpAcknowledgementType in the route to force AA, AE or AR yourself, or turn autoAck off and build the ACK.

Components and languages used

  • mllp: MLLP framing, automatic HL7 acknowledgements, TLS, CamelMllp* headers.
  • hl7terser: read a field by path (PID-3-1, MSH-9-1).
  • hl7 data format: ER7 text to a structured value and back.
  • fhir and the fhirJson/fhirXml formats for the FHIR side.
  • http, kafka, sql for where the message goes next.

Patterns that healthcare routes need

needpatternin Cameleer
Deliver each message onceidempotent consumer on MSH-10 (the message control id)idempotentConsumer with an in-memory, JDBC or Redis repository
Convert v2 to FHIRread segments with the terser, build the resource, post ithl7terser headers, setBody with Simple or jq, fhir producer
Keep working when the EHR is downstore and forwarddead letter channel to a folder, a replay route: the edge page shows it
Fan out to several systemsmulticast with per-target error handlingmulticast, wireTap for an archive copy
Send HL7 and check the replyMLLP producerto: mllp://host:port; CamelMllpAcknowledgementType on the way out is AA, AE or AR
Auditevery message and acknowledgement to an append-only logwireTap to file, kafka or sql

Why not a JVM on the gateway?

What changes with one native binary

  • About 10 MB of memory for a running route, against hundreds for a JVM; the gateway can be a small box or a VM shared with other software.
  • Starts in milliseconds, so a restart after a power cut or an update is invisible to the sending system's MLLP retry.
  • Nothing to install: no JRE to patch. The image runs read-only, as non-root, on amd64 and arm64.
  • Routes are files in Git; cameleer validate checks them before deployment.

Where Apache Camel still fits better

  • You depend on HAPI's full HL7 object model or a Java terminology library in the route.
  • Your interface team works in a Java application server and wants the JVM's tooling.
  • You need a Camel component Cameleer does not have; the feature matrix lists what exists.

Common questions

Does Cameleer parse HL7 v2 messages?

Yes. The mllp component frames and acknowledges messages, the hl7 data format parses ER7 (pipe-delimited) text into a structured value and encodes it back, and the hl7terser language reads a field by path, such as PID-3-1.

Which FHIR versions does it support?

The fhir component talks to FHIR servers for R4, R4B, R5 and DSTU3: create, read, update, delete, search, history, transactions, operations, patch and validation. The fhirJson and fhirXml data formats parse and serialize resources and convert between the two encodings.

When is the MLLP acknowledgement sent?

After the route finishes. In the tested route the EHR call runs first, so the sender gets AA only when the message was delivered and AE when it still failed after the retries, and keeps the message to resend it. A route can set the acknowledgement type itself.

Is it an interface engine like Mirth Connect?

It is a routing engine with HL7 v2, MLLP and FHIR support: channels are routes in YAML files kept in Git, with Apache Camel's error handling, transformation and routing patterns. There is no visual channel editor or message browser.

Does MLLP support TLS?

Yes. The consumer accepts TLS connections and the producer connects with TLS when sslContextParameters or the global camel.ssl.* parameters are set.

Run it

Set the EHR URL, start the container, and point the sending system at port 2575.

export EHR_URL=https://ehr.example.org   # optional: MLLP_PORT (default 2575)
docker run --rm -p 2575:2575 --read-only -e EHR_URL \
  -v "$PWD:/routes:ro" pmsudhi/cameleer run /routes/hl7-mllp-to-http.camel.yaml