HL7 Programming using HAPI - Sending HL7 Messages

This is part of my HL7 article series. Before we get started on this tutorial, have a quick look at my earlier article titled “A Very Short Introduction to the HL7 2.x Standard” for quick introduction to the HL7 2.x standard. One of my earlier tutorials in this series titled "HL7 Programming using Java" gave you a foundational understanding of HL7 2.x message transmission, reception and message acknowledgement. I then introduced you to a Java library called "HAPI" and showed you an example of how a HL7 message can be easily created using the library in my tutorial titled "HL7 Programming using HAPI - Creating HL7 Messages". In this tutorial, we will build on the previous tutorial and look at how we can transmit a HL7 message once we have assembled one to a remote system using the HAPI library.

Tools for Tutorial

“Every human is an artist. The dream of your life is to make beautiful art.” ~ Don Miguel Ruiz

Feature Overview

Most HL7 systems communicate messages with one another using the Minimum Lower Layer Protocol (often shortened to “MLLP”). MLLP can be simply considered a wrapper protocol on top of the TCP/IP protocol since the communicating systems need to be able to recognize the start and the end of each message (i.e. headers and trailers) as TCP/IP data is simply a stream of continuous bytes. MLLP typically uses non-printable characters to serve as wrapping characters around the core HL7 message information exchanged between these systems. If one were programming a HL7 system from scratch, then you will need to be familiar with many aspects of network programming such as sockets to accomplish the task of coordinating the steps require to establish TCP/IP communications between the two systems involved. Luckily, HAPI abstracts that for you and provides with some helpful classes to enable message exchange. The following are some of the features provided for HL7 message communication by HAPI:

  • Transmit HL7 messages over MLLP protocol
  • Transmit HL7 messages through a serialized file, email, etc
  • Transmit HL7 messages through HTTP (and HTTPS) using the HoH specification (stands for "HL7 over HTTP")
  • Transmit HL7 messages over a Restful Web Service Interface (using the HAPI HL7 FHIR Tooling)

Message Transmission - Overview and HAPI HL7 Test Panel Setup

In the previous tutorial, we saw the we could easily encode a HL7 message for serialization to print to the program console. The job of serialization was handled by a special class called Pipe Parser which is one of the many types of parser classes that HAPI supports. This parser enables the use of pipe delimiter characters during the message encoding and decoding process. Another type of parser that is available in the library is the XML Parser which helps encode and decode the HL7 message in XML format. HAPI provides many such useful classes to enable the programmer to handle the message processing in multiple ways. In this tutorial, we will construct a message and transmit the HL7 message to a HL7 listener running on our own machine. Rather than building something from scratch we will use an extremely helpful testing tool provided by the authors to test HL7 connectivity.

Setting up the HAPI Test Panel is very easy. Simply download the TestPanel compiled Jar file or the compliable source code. Please ensure that you have a suitable Java runtime installed on your machine (should be included in your JDK if you downloaded it previously). Then launch the test panel executable jar file. Since we are transmitting the HL7 message, we need to set up a listener. Create a new HL7 MLLP listener by adding a new one using the bottom left panel as shown in the screen capture below, choose the default port number the test panel suggest or enter a port number that does not conflict with any existing applications and hit the "Start" button. If the listener turns green in color, then you have successfully enabled a HL7 listener on your computer. See screen capture below that shows the HAPI Test Panel running on my computer.

HAPI Test Panel Setup

    package com.saravanansubramanian.hapihl7tutorial;

    import ca.uhn.hl7v2.DefaultHapiContext;
    import ca.uhn.hl7v2.HapiContext;
    import ca.uhn.hl7v2.app.Connection;
    import ca.uhn.hl7v2.app.Initiator;
    import ca.uhn.hl7v2.model.Message;
    import ca.uhn.hl7v2.model.v24.message.ADT_A01;
    import ca.uhn.hl7v2.parser.Parser;

    public class HapiSendMessageSimpleExample {

        private static final int PORT_NUMBER = 52463;// change this to whatever your port number is

        // In HAPI, almost all things revolve around a context object
        private static HapiContext context = new DefaultHapiContext();
            
        public static void main(String[] args) throws Exception {

            try {

                // create the HL7 message
                // this AdtMessageFactory class is not from HAPI but my own wrapper
                // check my GitHub page or see my earlier article for reference
                ADT_A01 adtMessage = AdtMessageFactory.createMessage("A01");

                // create a new MLLP client over the specified port
                Connection connection = context.newClient("localhost", PORT_NUMBER, false);

                // The initiator which will be used to transmit our message
                Initiator initiator = connection.getInitiator();

                // send the previously created HL7 message over the connection established
                Parser parser = context.getPipeParser();
                System.out.println("Sending message:" + "\n" + parser.encode(adtMessage));
                Message response = initiator.sendAndReceive(adtMessage);

                // display the message response received from the remote party
                String responseString = parser.encode(response);
                System.out.println("Received response:\n" + responseString);

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }
Sending message:
MSH|^~\&|Our System|Our Facility|Their Remote System|Their Remote Facility|20180630141413||ADT^A01^ADT_A01|123420180630141413|P|2.4
EVN|A01|20180630141413
PID|||378785433211||Mouse^Mickey||||||123 Main Street^^Lake Buena Vista^FL^^USA
PV1||O|Some Point of Care^^^Some Treatment Facility Name|ALERT||||99999999^Smith^Jack^^^^^^^^^^456789||||||||||||||||||||||||||||||||||||20180630141413

Received response:
MSH|^~\&|Their Remote System|Their Remote Facility|Our System|Our Facility|20180630141413.72-0600||ACK^A01|1301|P|2.4
MSA|AA|123420180630141413

HAPI Test Panel Message Reception

By running the code shown above, you should be able to send a HL7 ADT message to the listener and receive a message acknowledgement back. Message acknowledgement is a complex topic in itself and I will cover that in more detail in a separate tutorial on building HL7 listeners using the HAPI library. For now, just note that the HAPI Test Panel provides a nice breakdown of the message exchange activity showing the received message as well as the acknowledgment message that was transmitted back to our Java client. You can select the received or sent message in the Test Panel and "Edit" it to see a nice tree structure breakdown of the various constituents of these messages if you wanted to verify whether the information was transmitted correctly. A screen capture of this functionality is shown below.

HAPI Test Panel Message Tree Breakdown

Sending Multiple Messages

In many health information systems, the HL7 messages are often created and then serialized to a file for transmission later. This serialized file is then FTP'ed or transmitted over a file sharing network to a separate system capable of communicating using sockets with the remote party. There are two variations involved with this approach one of which is Batching which enables you to send multiple messages in a single file using a special envelope consisting of special file and batch headers. Batching is a complex topic in itself and I will cover that in a separate tutorial. However, the scenario I am referring to here is how to handle reading and sequential transmission of a series of HL7 messages contained in a file. Please see an example of how you can handle such a scenario below. I have also included the test file in my GitHub page here. Running the code below should enable to transmit the messages to the HAPI Test Panel if you have it configured using the instructions that were provided earlier. Screenshot of the HAPI Test Panel showing the transmitted messages that were received by the listener is shown below the source code listed here.

“We may encounter many defeats but we must not be defeated.” ~ Maya Angelou

    package com.saravanansubramanian.hapihl7tutorial;

    import java.io.FileReader;
    import java.io.IOException;
    import ca.uhn.hl7v2.DefaultHapiContext;
    import ca.uhn.hl7v2.HapiContext;
    import ca.uhn.hl7v2.app.Connection;
    import ca.uhn.hl7v2.model.Message;
    import ca.uhn.hl7v2.util.Hl7InputStreamMessageIterator;

    public class HapiSendMultipleMessagesExample {

        // In HAPI, almost all things revolve around a context object
        private static HapiContext context = new DefaultHapiContext();
        
        // change this to whatever your port number is
        private static final int PORT_NUMBER = 52463;

        public static void main(String[] args) throws Exception {

            try {

                FileReader reader = new FileReader("c:\\hl7testfiles\\FileWithLotsOfHl7Messages.txt");
                
                //create an iterator to read through the HL7 messages in the file
                Hl7InputStreamMessageIterator messageIterator = new Hl7InputStreamMessageIterator(reader);
                
                Connection connectionWithServer = null;
                
                while (messageIterator.hasNext()) {
                    
                    if (connectionWithServer == null) {
                        boolean useSecureTlsConnection = false;
                        connectionWithServer = context.newClient("localhost", PORT_NUMBER, useSecureTlsConnection);
                    }
                    
                    try {
                        Message nextMessage = messageIterator.next();
                        Message messageResponse = connectionWithServer.getInitiator().sendAndReceive(nextMessage);
                        System.out.println("Response received from server was " + messageResponse.encode());
                    } catch (IOException e) {
                        e.printStackTrace(); //in real-life, you need to handle these exceptions 
                        connectionWithServer.close();
                        connectionWithServer = null;
                        
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }

HAPI Test Panel Sending Multiple Messages

This concludes a quick overview and tutorial on using HAPI HL7 library for message transmission using the MLLP over TCP/IP. There are a lot of additional classes in the HAPI library that enable you to control the behavior of the MLLP and socket connectivity over and beyond what was shown in this tutorial. You can for instance send a message to the server through one port and configure the client to receive the message response through a different port. I will let you explore these features on your own. However, we will cover other features including message reception, parsing and validating in subsequent tutorials. See you then!