Ringholm-Logo Ringholm
 Whitepaper
Ringholm page header
Training    Services   |   Whitepapers    Blog    Events    Links   |   About us    Partners    Clients    Contact

Implementing Web Services in Dutch Healthcare

The contents of this whitepaper have been placed in the public domain.
See http://www.ringholm.com/docs/03030_en.htm for the latest version of this document.
Author: Marc de Graauw, Independent Consultant, Marc de Graauw IT.
Document status: Final, version 1.0 (2005-08-05)
Please send questions and comments to marc@marcdegraauw.com.


Summary

Healthcare in the Netherlands is moving rapidly towards an infrastructure where XML data will be exchanged over the Internet. This whitepaper discusses the implementation issues and pitfalls discovered during the implementation of web services, and more specifically SOAP and WSDL, in this large and complex environment.

1. Introduction

This section provides a brief introduction to NICTIZ and the Dutch healthcare situation, and a short introduction of HL7v3.

1.1 NICTIZ and Healthcare in the Netherlands

The Netherlands Institute for ICT in Healthcare (NICTIZ) is a coordinating organization for data exchange in the Dutch healthcare sector. One of the initial targets of NICTIZ is to provide healthcare providers with a nationwide electronic record of a patients medication history. The system will be operational in 2006. Huge savings can be made once such a medication record is available. Currently some 90.000 people (out of a population of 16 million) are hospitalized yearly due to wrong medication. This is one of the reasons why having online access to the medication history of a patient is seen as extremely important.

The Dutch government is dedicated to these developments as well: "The question is not whether the electronic medical record will become obligatory, but how", according to the Dutch Healthcare Minister in 2004, Mr. Hoogervorst. [SIG4]

Within the Dutch healthcare IT infrastructure, all messages are exchanged between a provider healthcare information system (HIS) and an healthcare information broker (HIB), which in turn may send the data contained in those messages to other healthcare parties. The information broker plays a vital role in queries for medication history. The information broker will be informed about the availability of medication related data whenever a system creates or updates prescription or medication supply related data. The information broker maintains a database which lists the parties where details of medication related data for a patient can be found.

When a healthcare provider wants to retrieve the medication history of a given patient, it sends a query with the patient id to the broker. The broker looks up all parties that have medication related information for the patient, collects the information, and sends it back to the requesting healthcare provider. The information broker doesn't contain any medical information itself, but acts as a registry of sources where this information is available. It also acts as an intelligent messaging intermediary, which can actively collect, sort and forward information.

1.2 HL7

The message format is HL7 version 3 (HL7v3), the international standard developed by Health Level Seven. HL7 standardizes UML based models which describe healthcare processes. The resulting message models can be automatically transformed into XML schema.

The HL7v3 Message Format itself consists of a payload of - in this case - medical data, along with several wrappers: the Transmission Wrapper and the Control Query Wrapper. The Transmission Wrapper contains constructs for message identification, addressing and reliability. As such it duplicates some of the features provided in the WS-* stack or ebXML Messaging.

In the Dutch national infrastructure for healthcare messaging the HL7v3 message is wrapped in SOAP and transported over secure HTTP via the Internet. HL7v3 is essentially a toolbox for the creation of message formats: a local authority such as NICTIZ has the ability to provide localized versions of the HL7v3 messages, and to generate localized XML Schema.

2. Choice of protocol standards

In terms of protocols some basic elements of the protocol stack were obvious: HL7v3, XML 1.0 and XML Schema. On top of this stack there are several options to support advanced services such as reliable messaging, security and addressing. This section details the rationale behind some of the choices that were made.

At the time the web services specification for NICTIZ started (mid 2003) the choices were limited. One option was ebXML Messaging (ebMS), a set of messaging standards developed jointly by OASIS and UN/CEFACT. A draft HL7 specification for the use of ebMS together with HL7v3 was already under construction. However, at the same time the entire set of ebXML specifications did not appear to have achieved the traction which was expected upon its release in 2001. Notably, Microsoft and IBM were not planning support for ebMS but working on their own stack of advanced services, such WS-ReliableMessaging. And on top of that, OASIS was developing a new WS-Reliability specification which seemed to compete with its own ebMS specification. The future of advanced web services was unclear to say the least, and very messy at worst.

NICTIZ has opted for an exchange model in which every exchange is between an healthcare information system (HIS) and a healthcare information broker (HIB). Since the HIBs are considered trustworthy, the security context was relatively simple, making SOAP over HTTPS a viable solution. Since HL7 itself provides addressing as well as reliability features, none of the advanced features of web services were necessary.

Given the insecurity on the future of web services in general, NICTIZ decided to adopt as little as possible of web services standards, thus avoiding "standard lock-in". This would make transition to another set of specifications, be it ebMS or the WS-* stack or something else, much easier. Only SOAP 1.1 and WSDL 1.0 were adopted. SOAP was a safe choice: all of the advanced services, ebMS as well as WS-* use SOAP, so adding SOAP to the NICTIZ stack would actually ease incorporation of those standards at a later date. WSDL was added to provide a description of the NICTIZ web services.

The Dutch requirements with regard to the use SOAP and WSDL were incorporated in the "Web Services Basic Profile", an HL7 document which describes how to implement SOAP and WSDL in combination with HL7v3 messages. This profile contains a good set of guidelines for interoperability. NICTIZ subsequently chose to require compliance with the WS-I Basic Profile, which means that all NICTIZ interactions are Basic Profile-compliant.


3. Reliability Issues

Reliability is an important requirement of NICTIZ, which could be provided by ebMS, HL7v3 reliability mechanisms or similar provisions in WS-Reliability or WS-ReliableMessaging. All mechanism are similar in nature.

Two options for reliability were evaluated: HL7 Accept Acknowledgements, and HTTP.

  1. HTTP. The HTTP 200 response can be used as an reliabilty mechanism: in the absence of HTTP 200 response, the Sender knows communication has failed and can try again.
  2. HL7 Accept Acknowledgements. The HL7v3 mechanism for reliability is relatively simple: after sending a message, a special message (the Accept Acknowledgement) is returned which contains the message id of the original message. This amounts to an explicit confirmation by the receiving application that it has received the message. If the sending application doesn't receive an Accept Acknowledgement, the message can be resent until an Accept Acknowledgement is received. HL7 Accept Acks are controlled by an attribute in the sent message: it can require the Receiver to send Accept Acks always, never, in case of errors only or in case of success only.

Example 1, reliability delegated to HTTP:
HL7 level: Sender sends Query to Receiver
Receiver send Response to Sender
WSDL level: <operation> with:
  <input> = Query
  <output> = Response
HTTP level: HTTP Request with Query
HTTP Response (status 200:OK) with Response

Example 2, reliability delegated to Accept Ack:
HL7 level: Sender sends Query to Receiver
Receiver send Response to Sender
WSDL level: <operation1> with:
  <input> = Query
  <output> = Accept Ack for Query
<operation2> with:
  <input> = Response
  <output> = Accept Ack for Response
HTTP level: HTTP Request with Query
HTTP Response (status 200:OK) with Accept Ack for Query
HTTP Request with Response
HTTP Response (status 200:OK) with Accept Ack for Response
In the current HL7 Web Services Profile an example is given like above Example 1, the HL7 Web Services Profile also makes an implicit choice for delegating reliability to HTTP at least in some cases. However, there are no guidelines in the HL7 Web Services Profile when to use which mechanism.

There are two different solutions to the reliability problems:

  • Bind the immediate HL7 application responses to HTTP response. No acceptAck is allowed for these cases - the response is an implicit acceptAck. Use accept acks in cases where no immediate HL7 application response is required.
  • Always use (allow use of) acceptAcks. No binding of HL7 response to HTTP Response. The HTTP Response is either an acceptAck or an empty HTTP 200:OK Response (or HTTP error).

The first alternative - to bind the immediate response to HTTP - will perform better as far as internet processing is concerned, since a HL7 request - response pair will map to single HTTP request - response pair. It is also easy to implement. The Sender will just have to make s single synchronous blocking call to its SOAP library, and get a single result message in return. These cases will get a WSDL portType like:

  <portType name="My_PortType_with_AcceptAck">
    <operation name="My_Request_with_AcceptAck">
      <input message="My_Request_Message"/>
      <output message="My_Response_Message"/>
    </operation>
  </portType>
This is described in the current HL7 Web Services Profile. A Sender will only need SOAP client functionality, not a SOAP server.This mechanism does not allow more than one reply to a single request (which HL7v3 by itself does allow). This could be repaired by sending multiple HL7 responses in a single HL7 batch response. In general the use of batched responses may mean responses will come slower (since the supplier will wait for a batch to fill). It will not be slower when a single source is queried, since the query has to run there anyway. In a NICTIZ context, where results from different suppliers are aggregated at an intermediary, it will take longer when results from several suppliers have to be integrated, which might cause the HIB to timeout the original request. As an example: if an hospital queries the HIB for a patients medication history, and the patient has only one known pharmacist with medical data, the response will be quick. Thje HIB can simply forward the pharmacist's response when it arrives. If there are several pharmacists with medical data on this patient, the HIB will have to integrate those responses in batches, and this will probably cause some delay.

The mechanism is also only applicable to idempotent requests: if the response to a request gets lost in transport, the Sender will have to resend the request. This means the second instance of the request must get the same response as the first. It turns out HL7v3 queries are not always idempotent: there are queries which are started by a request for an initial result set (say records 1- 20), and followed by requests for "the next" result set of the same query. If this next result set (say records 21 - 40) gets lost in transport, resending the request will be interpreted as a request for again the next result set (41 - 60), which means a part of the result set has gone missing. This may be considered a bug in the HL7v3 specifications, but nonetheless the HTTP-binding described above does not work in all HL7v3 cases. In the Dutch case this was solved by requiring all HL7 queries to be idempotent: receivers must store each messageId, and are required to respond with the same response to multiple incoming messages with the same MessageId (which are copies of each other).

Please note that a blocking HL7 application cannot meaningfully request an accept ack: this would unblock the application when it blocks to get the results, not the accept ack. Or stated otherwise, if Accept Acks are returned synchronously, the actual response is always sent asynchronously. The solution does also require each participant to act as both SOAP Server and SOAP client.

Ultimately the binding to HTTP responses was chosen for immediate queries, and the HL7 Accept Acknowledgement option for al other cases. The HL7 Accept Acknowledgement solution is very general and scalable. Each HL7 message is implemented as a WSDL portType with a single message as input and an acceptAck as output (or without the acceptAck, see discussion above). A single HL7 request - response pair will map to two HTTP request - response pairs, one for the HL7 request, the second for the HL7 response. The binding to HTTP for immediate queries is an optimization which makes this class of interactions simpler to implement, and in most cases, faster.

4. WSDL and Code Generation

Early prototypes of WSDL for HL7v3 medical queries, together with HL7v3 XML Schemas revealed several problems with tooling. One of the goals of the initial effort was to demonstrate the exchange of HL7v3 XML messages using SOAP in an environment with mixed development and runtime tools.

WSDL was generated based on the HL7v3 XML Schema, which in turn was used to generate code from the WSDL. Visual Studio.NET was the environment which was used to try this approach, which failed on several accounts. The code generated from the WSDL exposed several errors. For example, HL7v3 defines a type in XML Schema called "ON", which is a reserved word in Visual Basic, and consequently the generated code would not even compile. Several errors like this had to be fixed.

After solving these minor issues the real problems surfaced. The HL7v3 XML Schemas are very complex. Each upper level schema is comprised of several included schemas, which in turn again include schemas. One of the lowest level components are the HL7v3 vocabulary and datatype schemas. Generating code from WSDL will make programmatic constructs - in this case Visual Basic constructs - for everything included in the schemas. This is not likely to be the desired result. Not all of the HL7v3 vocabularies or datatypes are actually used, so the generated code contains too much useless clutter. The generated code is also hardly human-readable anymore. The plethora of generated programming constructs obscures what is happening in the code. The generated code is unlikely to provide the required functionality. When things get more complex than Fahrenheit-to-Celsius web services, generated code stubs will not be much use.

HL7 itself is a layered message format, so it is natural to process only part of the message in any particular application. For instance, processing of the HL7 Transmission Wrapper could occur in a HL7 Messaging Adapter, which passes the contents of this wrapper on to the next layer. Extracting the contents of the Transmission Wrapper as XML, and pass it on as XML to the next application is an obvious choice. The idea of using generated code from WSDL was abandoned in favor of hand-written code. WSDL is currently used for documentation purposes only.

4.1 WSDL Dynamic Response Issues

The type of HL7 response message is sometimes co-determined by the HL7 request message content. WSDL cannot handle this situation very well. HL7 has attributes whose value co-determines response type, such as responseModalityCode and acceptAckCode. Those are attributes whose value a Sender can set to different values, but whose value co-determines the Schema of a response. For example, the HL7 attribute acceptAckCode determines whether the response will be an Accept Acknowledgement or nothing. Specifically, if a HL7 message request an AcceptAck this would result in the following WSDL portType:

  <portType name="My_PortType_with_AcceptAck">
    <operation name="My_Request_with_AcceptAck">
      <input message="My_Request_Message"/>
      <output message="My_AcceptAck"/>
    </operation>
  </portType>
If the same message requests no Accept Ack this would result in the following portType:
  <portType name="My_PortType_without_AcceptAck">
    <operation name="My_Request_without_AcceptAck">
      <input message="My_Request_Message"/>
    </operation>
  </portType>
Optionally both operations can be combined into a single portType. But in each case, the sending application has to look into the HL7 Transmission Wrapper to decide which operation to invoke. There is no neat separation of WSDL/SOAP functionality from HL7 Transmission functionality. The attribute responseModalityCode determines whether the response will be a single result set or a batch of result sets - with a different Schema. WSDL requires a specific Schema for each message. Different schemas means, for WSDL, different messages. Different messages means different operations. This requires the WSDL operations to contain all possible combinations of request and response type. HL7 attributes like this make specific WSDL a) hard to write b) hard to understand. It already does if one uses acceptAckCode with values "AL" and "NE": every WSDL operation has to have two variants, one with and one without accept ack as output. If one adds responseModalityCode with values "B" and "R" there already are 4 variants of each WSDL operation.

This feature of HL7 also results in problems with the WS-I Basic Profile (Version 1.0a), which otherwise is a good set of guidelines for interoperability. The Basic Profile however has the following paragraph:

"R2710 The operations in a wsdl:binding in a DESCRIPTION MUST result in wire signatures that are different from one another.

The Profile defines the "wire signature" of an operation in a wsdl:binding to be the fully qualified name of the child element of the soap:Body of the SOAP input message it describes. ... In the document-literal case, ... the message signatures must be correctly designed so that they meet this requirement."

R2710 basically says each top element in an HL7 interaction must have a unique element name. If we look at the WSDL examples above, we can see two operations, where both incoming message share the same 'wire format' (as defined in the WS-I Basic Profile). This violates R2710, and therefore we have chosen to follow all of the WS-I Basic Profile except R2710.

4.2 WSDL design models

WSDL design leaves plenty of implementation choices. For HL7v3 messages, there are two possible models.

The first model is simple: an HIS sends a generic HL7 message to a HIB, and optionally gets a generic HL7 reply. The schemas in the WSDL will only describe the outer HL7 message wrappers (which are transport- and context-oriented), the real healthcare content will be described as "any" content in the schemas. A web services layer will forward the content to an HL7-aware layer, which will validate HL7 content, and hide all HL7 complexity from the web services layer (and vice versa).

Generic WSDL provides an operation with "HL7 Message In" and "HL7 Message Out". This portType can be used for any HL7v3 Message.

  <portType name="portHl7Message">
    <operation name="opHl7Message">
      <input message="ns:msgHl7MessageIn"/>
      <output message="ns:msgHl7MessageOut"/>
    </operation>
  </portType>
A generic schema is used with content "Any" for the HL7 message payload. Alternatively (and more sensibly) one could make a schema which does describe the outer HL7 wrappers and passes the medical payload to another HL7 application.
  <xs:schema targetNamespace="urn:hl7-org:v3">
    <xs:element name="hl7Message">
      <xs:complexType>
        <xs:sequence>
          <xs:any/>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
  </xs:schema>

The second option is making "real" WSDL descriptions for the actual healthcare interactions, for instance a HIS sends medication query, and gets a medication response from an HIB. This describes the actual web services provided much better, and might seem the obvious choice. It does however not allow for neat separation of layers: the web services layer has to be aware of HL7 content.

Specific WSDL describes the actual messages which are going back and forth, with associated schemas (WSDL schema references not shown):

  <portType name="Medical_Query_PortType">
    <operation name="Medical_Query">
      <input message=" Medical_Query_Request_Message"/>
      <output message=" Medical_Query_Response_Message"/>
    </operation>
  </portType>

From a WSDL point of view, these two solutions are completely different. From a SOAP point of view, they are however nearly the same, only the name of the top-level element is different. If we were to include a top-level wrapper as described in the previous section, the SOAP could even be the same.

At the time we thought the specific WSDL option would be the better one: it actually describes the web service, i.e. a medication query. However, the generic WSDL model allows for a neat separation of layers, in line with established web development patterns. Given the discussion above, the original decision may be challenged.

Generic WSDL fits much better with separation of layers: a web services layer will just cover basic web connectivity, and does not need to know anything about HL7 content. The procession of HL7 content is delegated to a separate HL7-aware layer. Given the complexity of HL7 content, it is not likely code generated on the basis of its schemas is much use. Simple code which does web connectivity at this layer is sufficient, and generic WSDL would fit this approach.

This would mean the WSDL-generated stub would need objects to handle SOAP, security, reliability etc. and just pass the content of the SOAP Body to the HL7-aware next layer. Such a model actually fits well with generic WSDL. If one uses a tool like VS.NET to generate code, one gets just one layer which should handle everything - or one has to completely overhaul the generated stub and restructure it to resemble something like the above layered model. Current developments within HL7 are in line with this approach. HL7v3 probably will define non-HL7-aware transport layers in future versions.

5. Conclusion

It is possible to build a reliable and secure framework for sending medical data over the Internet using only SOAP, standard HTTP mechanisms, and SSL (provided all transport nodes are reliable). No higher-level web services frameworks such as ebXML or WS-ReliableMessaging / WS-Reliability are needed. Given developments within HL7, a move to some or all of those web services frameworks can be expected in the future. If and when the situation with the multitude of web services reliability standards improves, such a move would be a step forward. HL7 poses a very interesting testcase for the lower web services stack (XML, XML Schema, SOAP and WSDL). Some weaknesses of WSDL are clearly exposed, such as the inflexibility in handling dynamic content. However, those weaknesses can be overcome, and web services seem to constitute a natural counterpart for HL7 messaging services over the Internet.

6. References

[SIG4] Signaal nr.4 NICTIZ 2004 http://www.nictiz.nl/
[HL7v3] HL7 Version 3 Standard, ballot #7, Health Level Seven Inc., 2004 http://www.hl7.org/
[Basis] Specificatie van de basisinfrastructuur in de zorg, versie 2.1, NICTIZ, 2004 http://www.nictiz.nl/

7. See also

HL7v3 and ebXML (blogpost) Part 1, Part 2 and Part 3.


About Ringholm bv

Ringholm bv is a group of European experts in the field of messaging standards and systems integration in healthcare IT. We provide the industry's most advanced training courses and consulting on healthcare information exchange standards.
See http://www.ringholm.com or call +31 33 7 630 636 for additional information.