The MLLPServer
The MLLPServer is a single server program that can set up a number of TCP/IP server threads where each serves one port in turn in a multi-threaded fashion.
The servers are configured from a single XML configuration file such as the following:
<mllp>
<server id="v2echo">
<port number="7001"/>
<backlog value="10"/>
<reader class="org.regenstrief.xhl7.HL7XMLReader"/>
<writer class="org.regenstrief.xhl7.HL7XMLWriter"/>
<transformerFactory class="net.sf.saxon.TransformerFactoryImpl"/>
<transform href="file:deep-identity-transform.xsl"/>
<error href="file:v2error.xsl"/>
</server>
<server id="v2echoxml">
<port number="7002"/>
<backlog value="10"/>
<reader class="org.regenstrief.xhl7.HL7XMLReader"/>
<transformerFactory class="net.sf.saxon.TransformerFactoryImpl"/>
<transform href="file:deep-identity-transform.xsl"/>
<error href="file:v2error.xsl"/>
</server>
<server id="v3echo">
<port number="7003"/>
<backlog value="10"/>
<transformerFactory class="net.sf.saxon.TransformerFactoryImpl"/>
<transform href="file:deep-identity-transform.xsl"/>
<error href="file:v2error.xsl"/>
</server>
<server id="sslv2echo">
<port number="7005"/>
<backlog value="10"/>
<reader class="org.regenstrief.xhl7.HL7XMLReader"/>
<writer class="org.regenstrief.xhl7.HL7XMLWriter"/>
<serverSocketFactory class="javax.net.ssl.SSLServerSocketFactory"/>
<transformerFactory class="net.sf.saxon.TransformerFactoryImpl"/>
<transform href="file:deep-identity-transform.xsl"/>
<error href="file:v2error.xsl"/>
</server>
</mllp>
In this example configuration, four servers are being defined that listen on port 7001, 7002, 7003, and 7005. They all use SAXON as their XSLT engine. The reader tag sets an XMLReader, which is normally used to set the HL7XMLReader, however, any other XMLReader can be used. All the action occurs in the XSLT transform. The transform can:
- transform the message and pass it on to one or more receivers
- process the message with a database or in some other way
Once a client makes a connection, a handler thread serves this connection until the client closes the connection. The connection can typically remain up for a long time with thousands of messages being transmitted. The MLLP protocol delineates the boundary of messages sent by the client and regulates when the server can send a response.
Notice that each port can handle many connections (the backlog value has nothing to do with limiting the number of established connections to a port.) It's a very common mistake in HL7 related TCP/IP programming to assume that a port can only server a single client. Not here :-)
The error tag specifies a transform that is called if the normal transformation fails either because the input is invalid or because of any other processing error signified by an exception thrown.
SSL Connections
SSL is supported in a very basic way but fine way. If you specify a <serverSocketFactory class="..."/> element in the server configuration, that java.net.ServerSocketFactory? is instantiated with getDefault(). Most likely you will specify the class="javax.net.ssl.SSLServerSocketFactory" here, as shown in the example. You will have to set system Properties to configure keystore and truststore.
- javax.net.ssl.keyStore
- javax.net.ssl.keyStorePassword
- javax.net.ssl.trustStore
- javax.net.ssl.trustStorePassword
For example, start the server as follows:
java -Djavax.net.ssl.keyStore=test.jks \
-Djavax.net.ssl.keyStorePassword=changeit \
-Djavax.net.ssl.trustStore=test.jks \
-Djavax.net.ssl.trustStorePassword=changeit \
org.regenstrief.xhl7.MLLPServer file:mllp.xml
and the test client as follows:
java -Djavax.net.ssl.trustStore=test.jks
-Djavax.net.ssl.trustStorePassword=changeit
org.regenstrief.xhl7.MLLPClient -s localhost 7005
[For reference check out: http://www-106.ibm.com/developerworks/java/library/j-customssl]
