Export (0) Print
Expand All

Web Services Enablement for Healthcare HL7 Applications - Web Services Basic Profile Reference Implementation

 

Mauro Regio
Microsoft Corporation

August 2005

Applies to:
   Enterprise Architecture
   Infrastructure Architecture
   Solution Architecture
   Web Services
   Healthcare HL7 Applications
   Factories

Summary: This document intends to provide designers and developers of Healthcare Solutions with a reference architecture/implementation that enables information exchange among Healthcare applications on a Web Services Platform, in conformance with HL7 specification and Web Services Profiles.

The paper deals with enabling applications to interface with the Web Service Infrastructure, designing Web Services following a Contract First Approach, automating code production based on formal specification of Message Types and Application to Application Interactions that are also relevant even outside the specific Healthcare scope. (50 printed pages)

Contents

Introduction
HL7 Modeling Concepts
Architecture
Developing HL7 Web Service Adapters
Sample Application
Conclusion
Microsoft and HL7
References
Appendix A

Introduction

Today, due to business and legal demands—like the Healthcare Insurance Portability and Accountability Act (HIPAA) in the United States—healthcare organizations are fully realizing the urgency to integrate their businesses. Unfortunately, most of the health information systems are still proprietary and often only serve one specific department within a healthcare business. This represents a significant obstacle to business integration. To complicate matters, a patient's health information may be spread out over a number of different organizations that do not collaborate, creating negative implications on care provisioning, quality, and costs.

We cannot solve this problem without flexible, yet standardized, definitions of the healthcare business and without leveraging a cost-effective, open, and interoperable communication infrastructure among Healthcare information systems.

Health Level Seven (HL7) is one of several American National Standards Institute (ANSI) accredited Standards Developing Organizations, operating in the healthcare arena worldwide. ("Level Seven" refers to the highest level of the International Standards Organization's (ISO) communications model for Open Systems Interconnection (OSI) —the application level.) Traditionally engaged in modeling clinical and administrative data, the most recent version, HL7 version 3.0, is extending its reach to various healthcare business domains such as pharmacy, medical devices, and imaging.

HL7 version 3 represents an important evolution of the widely-used 2.X versions. Version 3 is an improvement because it uses a rigorous modeling methodology, based on a comprehensive Reference Information Model (RIM), leaving very little undefined and therefore offering a standardized specification that is very precise and testable. This provides the ability to certify vendor conformance to the standard.

Given a specific healthcare domain, HL7 version 3 specifications define the relevant use case scenarios, the roles of various software systems that collectively will support those scenarios, the admissible interactions among applications, and the nature of the information (messages) exchanged.

The HL7 standard also specifies suitable messaging infrastructures, such as Web services, that can be adopted to carry HL7 messages, and provides prescriptive guidance (profiles) about how a transport should be used to ensure interoperability among applications. Enabling HL7 applications with Web services implies first, designing proper architectures and second, providing implementations that satisfy HL7 Web services profiles. (Please note that only the HL7 Web Services Basic profile [HL7WSP] is in scope for this document.)

Healthcare solution providers have to leverage HL7 standard definitions, as a pre-defined set of requirements, in architecting and designing interoperable applications. Architects also need to envision software components that will connect applications to the messaging infrastructure chosen. This requires a thorough understanding of the responsibilities of the application and/or the communication infrastructure. Finally, implementations must satisfy the transport specific constraints provided by HL7 profiles.

Under these assumptions that applications know HL7 version 3.0, can handle XML data and messages, and can natively interoperate with a Web services infrastructure, this paper will show how HL7 specifications can be effectively used to design and develop a reference implementation for applications conforming to the HL7 Web Services Basic Profile.

This document will also present a reference implementation of a HL7-specific scenario developed with Microsoft Visual Studio and Microsoft Web Services Enhancements (WSE) on top of the Microsoft .NET Platform.

HL7 Modeling Concepts

Although describing HL7 Standard Specifications structure and tools is outside the scope of this document, in this section we will introduce a few key HL7 modeling concepts and artifacts that are relevant to our discussion, abstracted from Ballot 7 of HL7 Version 3 specification [BALLOT 7].

Reference Information Model

For a given healthcare domain, an HL7 version 3 specification is based on the Reference Information Model (RIM), a common and underlying modeling framework, and includes artifacts like: Use Case Models, Information Models, Interaction Models, Message Models, and Implementable Message Specifications.

HL7's RIM is a static model of healthcare information representing the aspects of the healthcare domain undertaken so far by HL7 standards development activities. The HL7 version 3 standard development process defines the rules used to derive domain-specific information models from the RIM and to refine these models into HL7 message specifications, finally generating XML schema definitions (XSD) associated with a particular Message Type.

Various tools are provided to the standards developer by HL7 to support that process. For example, the RIM content itself is stored in a custom repository, and it's available to standards and application developers who want to access modeling information and/or create additional tools.

Message Structure

Interactions among HL7 applications happen through message exchanges. Thus, the standard provides a substantial level of functionality in provisioning envelopes supporting message exchange between applications. HL7 message envelopes are called wrappers, initially modeled by defining classes and relationships in the RIM. These specifications are then used to create the XML schema for the message wrappers, following a process outlined in HL7 Message Development Framework depicted in Figure 1.

ms954603.hl7webservapps01(en-us,MSDN.10).gif

Figure 1. HL7 Message Development FrameworkExcerpt from HL7 V3 Ballot 7 [BALLOT]

All HL7 messages are embedded into a Transmission Wrapper, whose goal is to support the Transmission (and Acknowledgement) of messages among applications. Important parts of the wrapper are elements like: Message Identifier, Message Creation Time, Interaction Identifier, Sender and Receiver Applications Identifiers, Accept Acknowledge Code, and Message Sequence Numbers (optional). It's important to clarify that HL7 messages should be thought of as being exchanged among Logical HL7 Applications; that is, specific software applications or components (like "Order Entry") that act on behalf of organizational or administrative entities (like "Westside Hospital Registration"). So, Sender and Receiver concepts should not be seen as part of a specification at the Transport level.

For example, the Accept Acknowledge Code specifies if an Application Level Acknowledgement should be returned to the application that sent a message, or if a more Transport-oriented receipt (called Accept Acknowledge) is required.

Sender applications use the Control Act Wrapper to communicate receiving information about the event that triggered the exchanged message. Unlike the Transmission Wrapper, the Control Act Wrapper's structure (schema) depends on the particular Interaction and Message Type. Not surprisingly, Control Act Wrappers are required for every message but Accept Acknowledge ones.

Transmission and Control Act Wrappers are used as envelopes for the Message Body (see Figure 2).

Together, the Control Act Wrapper and the HL7 Message Body constitute the complete semantics of HL7 Messages.

ms954603.hl7webservapps02(en-us,MSDN.10).gif

Figure 2. HL7 Abstract Message Structure

Interaction

An HL7 interaction is an association among a specific transfer of information: a trigger event that initiates the message transfer, and the applications that send and receive the message. In HL7 a Trigger Event is the precise set of conditions that leads to a transfer of information between applications, and it represents a real-world event, such as the placing of a laboratory order or the registration of a patient.

At the conceptual level, an interaction represents a unique, one-way transfer of information, and it specifies:

  • Which types of applications send/receive a given Message Type.
  • How a system knows when to send a particular Message Type.
  • What is the Message Type used for that interaction.

At a practical level, it's important to understand that the interaction's dynamics can be much more sophisticated than a "simple" one-way transfer of information, depending on what is specified in the message's Transmission and Control Wrappers. In fact, the communication level can employ various communication patterns, including (but not limited to): Send Message Payload—No acknowledgement, Send Message Payload with Accept Acknowledgement, Send Request Message with Application Acknowledgement (Immediate or Deferred), and so on.

Application Role

ms954603.hl7webservapps03(en-us,MSDN.10).gif

Figure 3. Interaction DiagramExcerpt from HL7 V3 Ballot 7

Every application in HL7 belongs to a specific Application Role. Such a role represents the application's responsibilities in terms of which services the application needs to provide to other applications, or which messages the application sends in order to request a specific service.

Within a certain interaction, one Application Role is also assigned responsibility for sending information (we may think of this Application Role as an application client)—the Sender—and one Application Role is assigned responsibility to receive—the Receiver (this Application Role behaves like an application server)—that interact and undertake the appropriate responses.

Storyboard

Concepts like Message Type, Interaction, and Application Role all come together in an HL7 Storyboard, which is used to specify use cases relevant to any healthcare domain in scope with HL7 standardization activity.

A Storyboard consists of a short narrative description of its purpose and an Interaction Diagram showing—at the application level—the progression of Interactions between the Application Roles. The Interaction diagram, like the one in Figure 3, specifies the parties (that is, the Application Roles) involved in relevant Interactions, the Message Types for the information to be exchanged, and the expected sequence of information exchange.

As is evident from Figure 3, each and any modeling concept an artifact in HL7 has both a descriptive Name (Laboratory Observation Order Global Placer, for example) and a Unique Identifier (POLB_AR002900, for example) built following a pretty straightforward yet structured naming convention. For example, all the entities specified in the Laboratory domain use the "POLB" prefix. Storyboard names use the "ST" prefix, while the "AR" and "IN" prefixes are used for Application Roles and Interactions identifiers.

So, as shown in Figure 3, both Laboratory_Observation_Order_Global_Placer (POLB_AR002900) and Laboratory_Observation_Order_Global_Fulfiller (POLB_AR002942) participate in the Interaction named Laboratory_Observation_Order_Activate_Fulfillment_Request (or POLB_IN002120). While the first Application Role is the Sender of a message request, the second one is the Receiver, in fact the service provider.

It's important to notice that, although not directly shown in the Interaction diagram, navigating HL7 RIM, starting from the Interaction Identifier (POLB_IN002120), allows retrieval of the Message Type (XML schema) for the message that has to be exchanged when that Interaction takes place.

Architecture

Based on the key HL7 modeling concepts just introduced, we can now more precisely define HL7 application "Web enablement." These are the design and implementation of software components supporting Application Roles in fulfilling their Sender's and/or Receiver's responsibilities as part of an Interaction execution, using a Web services communication infrastructure conforming to the HL7 Web Services Basic Profile.

This section outlines the relevant architectural abstraction levels and perspectives, and specifies architecture components' responsibilities for HL7-compliant systems.

From an architectural standpoint, it's very important to notice that HL7 Applications, the Web services infrastructure, and the Transport are at different abstraction levels, as depicted in Figure 4.

In order to send a HL7 Message, HL7 Sender Applications need to prepare them accordingly to the Interaction's business rules, Message Type definition, and Communication Patterns, indicating the HL7 message recipient and—optionally—if any Acknowledgment is required or not, and then "pass them to" the underlying Web Services Infrastructure. The Web Service Infrastructure, in turn, will use the services provided by the Transport layer to transfer the message to the destination end point on the network.

On the Receiver side, the message will be handled symmetrically by components at various abstraction layers, finally delivering the HL7 Message to the receiving HL7 Application.

At the application level, sending/receiving HL7 Messages and interfacing with Web services infrastructure are two distinct set of functionalities. Of course, that is true for both Sender and Receiver Applications.

In the architecture shown in Figure 4, we abstract those two sets of functionalities within an HL7 Sender/Receiver: Business Logic and Web Services Adapter components. (It needs to be stressed that the Business Logic's scope here is within HL7 applications performing their role of Sender and/or Receiver of information; that is, it supports a specific communication pattern. The application level Business Logic, the generation of the message, and/or the provisioning of a specific service in response to a request are out of scope.)

As far as the HL7 Message exchange is concerned, Business Logic tasks include:

  • Sender Side
    • Create an XML representation of a specific HL7 Message Type that includes Body, Control Wrapper, and Transmission wrapper.
    • Pass that message to the Web Service Adapter for its transmission to the Receiver Application.

    ms954603.hl7webservapps04(en-us,MSDN.10).gif

    Figure 4. Reference Architecture

  • Receiver Side
    • "Retrieve" the HL7 Message received by the Web Service Adapter, and unfold the Transmission Wrapper, Control Wrapper, and Message Body from the received XML Message.
    • Verify the HL7 Message satisfies the business rules and constraints for that Interaction.
    • Check if the Sender Application required an Application Level Acknowledge (HL7 Message Type MCI) and—in that case—send that message.

Web Service Adapters functions mostly deal with message dispatching and possibly with acknowledgements. So, they would include:

  • Sender Side
    • Read the Transmission Wrapper of received HL7 Messages to determine how to reach the ultimate recipient (for example Receiver Application) on the Web Services Infrastructure, configuring the SOAP Envelope accordingly.
    • Based on HL7 Message Type, application configuration and policies (for example, security) prepare a SOAP message, containing the HL7 XML message as a SOAP body part, to be sent over the Web Services infrastructure.
    • Pass the SOAP Message to the Web service proxy for transmission on the wire.
    • Get ready to receive and—optionally—store related Accept or Application Level acknowledgement messages from the Receiver, whenever requested by the Sender.
  • Receiver Side
    • Receive the SOAP message from the Web service Stub.
    • Verify the received SOAP message satisfies application configuration and policies constraints (for example, security).
    • Possibly store the received message in a persistent form of memory.
    • Optionally, unfold the HL7 XML message from the SOAP message and check schema compliance for the received HL7 Message with the expected HL7 Message type.
    • Verify if any communication (Accept) level acknowledgement needs to be performed, and in that case prepare an appropriate message to be sent to the original Message Sender.
    • Pass the HL7 Message to the Receiver Application.

It is important to understand that the HL7 Communication Pattern chosen to implement the dynamics of a particular HL7 Interaction affects Web Service Adapters' functionalities, their architecture, and how they "use" the lower level Message Exchange Patterns (MEP) natively supported by Web Services Infrastructure.

For example, when HL7 communication pattern "Send Message Payload—No Acknowledgements" is used, Senders simply send a one-way message to Receivers. In other words, the Communication Pattern can be mapped into the One-Way Message Exchange Pattern. In this case, the Web Service Adapters have to simply embed generic Web services Proxy and Stub components whose respective role is to Send and Receive SOAP messages over the Web Services Infrastructure.

If the chosen HL7 communication pattern requires a synchronous acknowledge, like in "Send Message Payload Requiring Accept Acknowledge—Immediate" or "Send Message Payload Requiring Application Acknowledge—Immediate," the Sender sends a message to the Receiver expecting an immediate answer from it, carrying either an Accept or Application level Acknowledge. In this case, the Web service Proxy/Stub architecture still works. However, these Communication Patterns should be mapped into Request/Response Message Exchange Patterns, rather than the One-Way transfers. As we will see in next chapter, this will also affect the way Operations are defined in Web services contract specifications, such as WSDLs.

If the Communication Patterns employed require a deferred response from the Receiver, like "Send Message Payload Requiring Accept Acknowledge—Deferred" or "Send Message Payload Requiring Application Acknowledge—Deferred," the Proxy/Stub couple in the Adapters' architecture needs to be "duplicated." One Proxy/Stub couple is necessary to support the transfer of the Message (from Sender to Receiver), and another one is required to send the Acknowledge message back from the Receiver to the Sender. For the transfer of the single message, both couples may use either the One-Way or Request/Response Message Exchange Pattern on the Web Services Infrastructure.

It's important to notice that the HL7 version 3 Messaging Infrastructure Specification defines other, more sophisticated communication patterns that intertwine the message transfer (dispatching/acknowledgement) with its application level handling (check/response). For example, a Sender may send an HL7 Message Payload requiring immediate Application Level Acknowledgement. However, the Sender may also declare that it can handle an Application Response instead of an Application Acknowledgement to the original message.

At the adapter level, all these cases can—and should—be implemented as multiple One-Way or Request/Response Message Exchange Patterns. At the same time, the responsibility to carry on the application-to-application collaboration should be relinquished to the application's Business Logic.

While we declared this is outside the scope of this paper, in a real implementation, Adapters' architecture would also need to address application integration and interoperability issues; for instance, if the application business logic was not able to interact directly with a Web services environment or it was built on a platform different than the one on which the Adapters are implemented.

Developing HL7 Web Service Adapters

In principle, especially when the scope is limited to supporting the HL7 Web Services Basic Profile, developing HL7 Web services is not very dissimilar to that of a generic Web Service. In practice, the availability of RIM's standardized models, message types' specification, communication patterns, and Web Services Profiles affect the process quite a bit.

At a high level, here are the steps that need to be done in order to effectively develop HL7 Web Service Adapters.

  1. Message and Data Type Design—Developing a Web service in a message-oriented environment like HL7 has to start with designing messages that need to be exchanged, data types used, and their specification within a XSD schema. This activity fully benefits from Message and Data Types specification tools made available by HL7 that automate XSD schema generation.
  2. Adapter Pattern Choices—The next step in creating the Web Service Adapter is to choose which Adapter architectural pattern best suits the HL7 Communication Pattern specified in the message type obtained in Step 1. This step would determine, for example, if one (and only one) set of Proxy/Stub components is necessary.
  3. HL7 Web Service Contract Development—From a generic perspective, the next step in creating a message-oriented Web Service can be either the definition of its contract, in a standardized machine-readable language called Web Service Description Language (WSDL), or the development of its implementation in a programming language that supports Web services standards.

    The separation between the service's contract (interface) and its implementation is a fundamental characteristic of the Web service paradigm. The service contract specifies the service's semantics; that is the "what" the service is all about versus the implementation specific details, or the "how" a certain service is built.

    Web service contract and implementation may be developed in any order. More interestingly, once a WSDL-based contract representation is available, the Web service's skeleton implementation can be automatically generated. This approach is known as Contract First Web Service Development. Conversely, a contract can be automatically (and completely) derived from a Web service implementation.

    Unfortunately, although simple and complete, the implementation-driven approach may introduce interoperability problems [CF-INT], because implementations are built on a specific Web services platform, for example Microsoft .NET, and the tools used to generate WSDL contracts are also platform-specific and might introduce platform-specific elements, especially data types, in generated WSDL contracts.

    More importantly, the contract-first approach is always preferable to the implementation-driven one when formal specification of the service is already available, like in the case of the HL7 specifications. Further, having the abstract specification of the service available (as expressed in HL7 Interactions) and a prescriptive guidance for its transformation in a Web services contract (i.e. rules of HL7 Web Services Basic Profile) allows us to automatically transform that Interaction specification into a WSDL contract. We will discuss this more in detail in the next section.

  4. Generate implementation of Web Service Stub and Proxy—Once the WSDL contract is finished, it is possible to create the Web service Stub and Proxy using tools offered by the development platform, like WSDL.exe utility. We will discuss this in more detail in the Web Services Code Generation section.
  5. Develop the Adapter Business Logic—This step builds on the code generated in the previous step, adding the logic necessary to support the Adapter functionalities described in the Architecture section.

HL7 Web Services Contract Development

A generic WSDL contract specifies a Web Service Name and the Ports through which that Web service can communicate with client applications. A Port specifies the Location where that service is available on the network. Each Port also specifies a Binding between the group of Operations (portTypes) available on that Port and the Transport Protocol that client and server should use to communicate on that Port. portTypes represent the various interfaces exposed by the Web service. Operations in turn are the interface's methods; they define the input message used by the client to request the service and, optionally, the output messages used by the server to respond to the service invocation. Message formats are based on Types definitions (XML schema) also included in the WSDL contract.

The prescriptive guidance contained in the HL7 Web Services Basic Profile mostly focuses on how to expose and interact with functionalities provided by HL7 applications. That is, it defines standardized Web service contracts, and how to package the XML representation of a HL7 message in a SOAP message.

Most of the profile provides very prescriptive guidance on how to build a WSDL contract. And, given the particular Application Role, the Interactions that need to be supported by that Application Role, and the Message Types, it's relatively easy to build a WSDL contract by simply applying the rules (Assertions) provided by the profile.

However, few areas of the profile, like PortTypes, Binding, and Service, leave some open space for interpretation and therefore need further discussion here.

PortTypes

The Basic Profile mandates four assertions that must be satisfied for a PortType:

  1. HL7-WS220—A PortType named {Application Role Artifact Id}_PortType is declared.
  2. HL7-WS221—A request/response operation consists of two interactions, which are linked by an Interaction-based Trigger Event.
  3. HL7-WS222—A one-way operation is made for each interaction that does not lead to an Interaction-based Trigger Event.
  4. HL7-WS223—Each operation is given a unique name {Application Role Artifact Id}_{Operation Name}.

Implementation of assertions WS220 and WS223 is straightforward. As an example, below is a WSDL segment with the part of the PortType section for the Laboratory_Observation_Order_Activate_Fulfillment_Request Application Role, where the input and output elements have been intentionally omitted.

Code Example 1. PortType Section

<portType name="POLB_AR002942_PortType">
   <operation name=
"POLB_AR002942_Laboratory_Observation_Order_Activate_Fulfillment_Request">
         <input ..."/>
         <output ..../>
   </operation>
</portType>

Completing the specification of operations requires defining which Message Exchange Pattern to implement, being either One-Way, Request/Response, or a combination of them based on the HL7 Communication Pattern chosen to transfer a particular Message Type and the guidance provided by the profile.

When using a simple One-Way message exchange pattern, you need to declare a one-way operation in the WSDL contract. For example, the following WSDL fragment provides an example of the PortType section for the "Laboratory Observation Event Global Tracker" Application Role, where the operation POLB_AR004922 (namely "Laboratory Observation Event Activate Notification") has been implemented as a one-way operation.

When an HL7 Immediate Acknowledge response is requested, this requires a Request/Reply message exchange pattern that can be implemented with a Request/Response operation in WSDL. Simply stated, a Request/Response operation contains two messages: an input message and an output message. Both of them need to be specified in the WSDL contract. For example, both of the operations "Laboratory Observation Event Preliminary Notification" and "Laboratory Observation Event Complete Notification" in POLB_AR004922 implement a Request/Response pattern, where the Response Message is an Application Level Acknowledge (MCCI_MT00300).

When an HL7 Deferred Acknowledge response is requested, it requires a Request/Reply message exchange pattern. However, in this case, it must be implemented as a pair of One-Way messages. Therefore, only a one-way operation will be defined in each WSDL contract (that is, one each on the original Sender and Receiver).

Code Example 2. Request/Reply Message Exchange Pattern Defined in WSDL Contract

<portType name="POLB_AR004922_PortType">
   <operation name="POLB_AR004922_Laboratory_Observation_Event_
Activate_Notification">
      <input message=
         "hl7:POLB_AR004922_Laboratory_Observation_Event_
Activate_Notification_POLB_IN004110.Message"/>
   </operation>
   <operation name="POLB_AR004922_Laboratory_Observation_Event_
Preliminary_Notification">
      <input message=
         "hl7:POLB_AR004922_Laboratory_Observation_Event_Preliminary_
Notification_POLB_IN004310.Message"/>
      <output message=
         "hl7:POLB_AR004922_MCCI_MT00300.Message"/>
   </operation>
   <operation name="POLB_AR004922_Laboratory_Observation_Event_
Complete_Notification">
      <input message=
         "hl7:POLB_AR004922_Laboratory_Observation_Event_
Complete_Notification_POLB_IN004410.Message"/>
      <output message=
         "hl7:POLB_AR004922_MCCI_MT00300.Message"/>
      </operation>
</portType>

Of course, all messages used in specifying operations are previously declared in the Message section of WSDL contract.

Binding

Once Operations and PortTypes are defined we can specify their binding to one or more transports. HL7 Basic Profile's adoption of SOAP is articulated in the following four assertions:

  1. HL7-WS230—A Binding named {Application Role Artifact Id}_Binding is declared.
  2. HL7-WS231—A soap:operation/@soapAction attribute with value urn:hl7-org:v3/{Application Role Artifact Id}_{Operation Name} is provided.
  3. HL7-WS232—HL7 WSDL uses the SOAP Binding.
  4. HL7-WS240—SOAP messages for HL7 use document/literal style.

Code Example 3 is a WSDL fragment that implements these assertions for the "Laboratory Observation Event Global Tracker" Application Role, where the last two operations support a request/response, as defined in the previous PortType example.

Code Example 3. Binding Specification in WSDL Contract

<binding name="POLB_AR004922_Binding" type="hl7:POLB_AR004922_PortType">
   <soap:binding style="document" 
transport="http://schemas.xmlsoap.org/soap/http"/>
      <operation name="POLB_AR004922_Laboratory_Observation_Event_
Activate_Notification">
      <soap:operation soapAction="hl7:POLB_AR004922_POLB_IN004110"/>
         <input>
            <soap:body use="literal"/>
         </input>
      </operation>
      <operation name="POLB_AR004922_Laboratory_Observation_Event_
Preliminary_Notification">
         <soap:operation soapAction="hl7:POLB_AR004922_POLB_IN004310"/>
         <input>
            <soap:body use="literal"/>
         </input>
         <output>
            <soap:body use="literal"/>
         </output>
      </operation>
      <operation name="POLB_AR004922_Laboratory_Observation_Event_
Complete_Notification">
         <soap:operation soapAction="hl7:POLB_AR004922_POLB_IN004410"/>
         <input>
            <soap:body use="literal"/>
         </input>
         <output>
            <soap:body use="literal"/>
         </output>
      </operation>
</binding>

Service

Finally, the Web service is declared within the contract and the following assertions establish how that should happen accordingly to HL7 Basic Profile:

  1. HL7-WS250—A service named {Application Role Artifact Id}_Service is declared.
  2. HL7-WS251—A port named {Application Role Artifact Id}_Port is declared.

For example, the service POLB_AR004922 is defined here, even if the specific service's location has not been provided.

Code Example 4. Declaring the Web Service

<service name="POLB_AR004922_Service">
   <port name="POLB_AR004922_Port" binding="hl7:POLB_AR004922_Binding">
      <soap:address location="http://servicelocation/POLB_AR004922"/>
   </port>
</service>

The service location is not specified when the WSDL contract is designed. That is deferred to when the service stub code is created.

Automate Contracts Development

Of course, creating HL7 WSDL Contracts should, and indeed can, be automated. This eliminates coding and errors.

In fact, the assertions contained in the HL7 Web Services Basic Profile lead to a generic WSDL contract template, where the variable parts are functions of the Application Role that contract should support, as well as the identifiers and description of Messages that the Application Role can receive and process.

That information is contained in HL7 RIM, or better, in a repository based on a relational database where the whole RIM is stored. This repository is available to all HL7 members.

With that repository in hand and an understanding the nature of assertions contained in HL7 profiles, writing the WSDL contract becomes as easy as writing an XSLT transformation on the WSDL templates mentioned previously, or developing an add-in for the specific development environment used by the application developer, for example Microsoft Visual Studio.

The add-in approach is preferable because it is more flexible and can be extended to encompass and automate the code generation for Proxies and Stubs of the defined Web services or, more generally, for the various components that constitute the Web Services Sender and Receiving Adapters.

Code Example 5 is a full WSDL contract example, automatically generated from the HL7 RIM repository, for the Application Role POLB_AR004922, namely the "Laboratory Observation Event Global Tracker" of Figure 3, assuming that all the Communication Patterns are mapped into One-Way Message Exchange Patterns. Note how XML comments have been used to highlight the Basic Profile assertions within the WSDL for documentation purposes.

Code Example 5. Automatically-generated WSDL Contract Example

<?xml version="1.0" encoding="utf-8"?>
<!--HL7-WS203) The targetNamespace
 of the WSDL MUST be "urn:hl7-org:v3"-->
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
 xmlns="http://schemas.xmlsoap.org/wsdl/"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:hl7="urn:hl7-org:v3" targetNamespace=
"urn:hl7-org:v3" name="POLB_AR004922"> 
   <!--HL7-WS204) Names (as opposed to Id's)
 of Artifacts SHOULD be included in XML comments wherever appropriate-->
   <documentation>WSDL implementation of Laboratory Observation Event
 Global Tracker (POLB_AR004922)</documentation>

   <types>
      <!--HL7-WS205) XML Schema's MUST be included with an XML Schema <include>
 inside a <schema> element in the WSDL <types> section-->
      <xsd:schema elementFormDefault="qualified"
 targetNamespace="urn:hl7-org:v3" xmlns:tns="
urn:hl7-org:v3">
         <!--HL7-WS206) The schema for each Interaction this Application
 Role participates in is included-->
         <xsd:include schemaLocation="POLB_IN004110.xsd"/>
         <xsd:include schemaLocation="POLB_IN004310.xsd"/>
         <xsd:include schemaLocation="POLB_IN004410.xsd"/>
         <!--HL7-WS207) A unique element name MUST be declared
 for each message in the storyboard-->
         <!--           The elements MUST be named {Application
 Role Artifact Id}_{Operation Name}_{Interaction Artifact Id}.Message. -->
         <xsd:element
            name ="POLB_AR004922_Laboratory_Observation_Event_
Activate_Notification_POLB_IN004110.Message"
            type ="tns:POLB_IN004110.Message"/>
         <xsd:element
            name ="POLB_AR004922_Laboratory_Observation_Event_
Preliminary_Notification_POLB_IN004310.Message"
            type ="tns:POLB_IN004310.Message"/>
         <xsd:element
            name ="POLB_AR004922_Laboratory_Observation_Event_
Complete_Notification_POLB_IN004410.Message"
            type ="tns:POLB_IN004410.Message"/>
      </xsd:schema>
   </types>

   <!--HL7-WS210) Each message in the HL7 storyboard becomes a WSDL
 <message>-->
   <!--HL7-WS211) Each message is named {Application Role
 Artifact Id}_{Operation Name}_{Interaction Artifact Id}-->
   <!--HL7-WS212) Parts are named "body". Since each SOAP Body
 is fully described by a single Schema, using named parts
 is superfluous-->
   <message name="POLB_AR004922_Laboratory_Observation_Event_
Activate_Notification_POLB_IN004110.Message">
      <documentation>POLB_IN004110 Laboratory Observation Event
 Activate, Notification)</documentation>
      <part name ="body" element="hl7:POLB_AR004922_Laboratory_Observation_Event_
Activate_Notification_POLB_IN004110.Message"/>
   </message>
   <message name="POLB_AR004922_Laboratory_Observation_Event_
Preliminary_Notification_POLB_IN004310.Message">
      <documentation>POLB_IN004310 Laboratory Observation Event
 Preliminary Notification)</documentation>
      <part name ="body" element="hl7:POLB_AR004922_Laboratory_Observation_Event_
Preliminary_Notification_POLB_IN004310.Message"/>
   </message>
   <message name="POLB_AR004922_Laboratory_Observation_Event_
Complete_Notification_POLB_IN004410.Message">
      <documentation>POLB_IN004410 Laboratory Observation Event
 Complete, Notification)</documentation>
      <part name ="body" element="hl7:POLB_AR004922_Laboratory_Observation_Event_
Complete_Notification_POLB_IN004410.Message"/>
   </message>

   <!--HL7-WS220) A PortType named {Application Role
 Artifact Id}_PortType is declared-->
   <portType name="POLB_AR004922_PortType">
      <!--HL7-WS221) A request/response operation consists
 of two interactions, which are linked by an Interaction Based
 Trigger Event-->
      <!--HL7-WS222) A one-way operation is made for each interaction
 that does not lead to an Interaction Based Trigger Event-->
      <!--           (Note: Trigger Events may be unspecified,
 in which case the operations have to be discovered
 by other means.) -->
      <!--HL7-WS223) Each operation is given a unique name
 {Application Role Artifact Id}_{Operation Name}-->
      <operation name="POLB_AR004922_Laboratory_Observation_Event_
Activate_Notification">
         <input message="hl7:POLB_AR004922_Laboratory_Observation_Event_
Activate_Notification_POLB_IN004110.Message"/>
      </operation>
      <operation name="POLB_AR004922_Laboratory_Observation_Event_
Preliminary_Notification">
         <input message="hl7:POLB_AR004922_Laboratory_Observation_Event_
Preliminary_Notification_POLB_IN004310.Message"/>
      </operation>
      <operation name="POLB_AR004922_Laboratory_Observation_Event_
Complete_Notification">
         <input message="hl7:POLB_AR004922_Laboratory_Observation_Event_
Complete_Notification_POLB_IN004410.Message"/>
      </operation>
   </portType>

   <!--HL7-WS230) A Binding named {Application Role Artifact Id}
_Binding is declared. -->
   <binding name="POLB_AR004922_Binding" type="hl7:POLB_AR004922_PortType">
      <!--HL7-WS232) HL7 WSDL uses the SOAP Binding
 described in WSDL 1.1 Chapter 3-->
      <soap:binding style="document"
 transport="http://schemas.xmlsoap.org/soap/http"/>
      <!--HL7-WS223) Each operation is given a unique name
 {Application Role Artifact Id}_{Operation Name}-->
      <!--We assumed One Way operations, not Request/Response-->
      <operation name="POLB_AR004922_Laboratory_Observation_Event_
Activate_Notification">
         <soap:operation soapAction="hl7:POLB_AR004922_POLB_
IN004110"/>
         <input>
            <soap:body use="literal"/>
         </input>
      </operation>
      <operation name="POLB_AR004922_Laboratory_Observation_Event_
Preliminary_Notification">
         <soap:operation soapAction="hl7:POLB_AR004922_POLB_
IN004310"/>
         <input>
            <soap:body use="literal"/>
         </input>
      </operation>
      <operation name="POLB_AR004922_Laboratory_Observation_Event_
Complete_Notification">
         <soap:operation soapAction="hl7:POLB_AR004922_POLB_IN004410"/>
         <input>
            <soap:body use="literal"/>
         </input>
      </operation>
   </binding>

   <!--
   <service name="POLB_AR004922_Service">
      <port name="POLB_AR004922_Port" binding="hl7:POLB_AR004922_Binding">
         <soap:address location="http://servicelocation/POLB_AR004922"/>
      </port>
   </service>
   -->
</definitions>

Web Services Code Generation

Once you create the WSDL contract definition for an Application Role, you can automatically generate the code for the Web service Stub and Proxy using the WSDL.exe tool provided with the Microsoft .NET development platform. Of course, two executions are required to create code components—in the chosen programming language—for both the service and its client. Also, you must specify the <namespace> parameter to define and refer to the Service in the proper HL7 namespace, as indicated by the HL7 Web Services Basic Profile.

As an example, here is a code fragment that implements the Service Stub for the Application Role "Laboratory Observation Order Global Fulfiller" POLB_AR002942.

Note   Bolded code represents place holders to be specified in a later example.

Code Example 6. Service Stub Implementation Example

 [...]

// 
// This source code was auto-generated by wsdl, Version=1.1.4322.2032.
// 
namespace LIS {
    using System.Diagnostics;       using System.Xml.Serialization;
    using System;          using System.Web.Services.Protocols;
    using System.ComponentModel;       using System.Web.Services;
    
    /// <remarks/>
    [System.Web.Services.WebServiceBindingAttribute(Name="POLB_
AR002942_Binding", Namespace="urn:hl7-org:v3")]
    [WebService(Namespace="urn:hl7-org:v3")]
   public class POLB_AR002942_Service : System.Web.Services.WebService 
   {        
        /// <remarks/>
      [System.Web.Services.WebMethodAttribute()]
      [System.Web.Services.Protocols.SoapDocumentMethodAttribute(
            "hl7:POLB_AR002942_POLB_IN002120", OneWay=true,
 Use=System.Web.Services.Description.SoapBindingUse.Literal,
             ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
      public  void    POLB_AR002942_Laboratory_Observation_Order_
Activate_Fulfillment_Request(
         [System.Xml.Serialization.XmlElementAttribute(
         "POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_POLB_IN002120.Message",          
         Namespace="urn:hl7-org:v3")] POLB_IN002120Message
         POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_POLB_IN002120Message)
      {
      }
        
        /// <remarks/>
        [System.Web.Services.WebMethodAttribute()]
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute
("hl7:POLB_AR002942_POLB_IN002121", OneWay=true,    
         Use=System.Web.Services.Description.SoapBindingUse.Literal,
         ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
        public  void POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_No_App_Ack
         ([System.Xml.Serialization.XmlElementAttribute(
         "POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_No_App_Ack_POLB_IN002121.Message",    
         Namespace="urn:hl7-org:v3")] POLB_IN002121Message
         POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_No_App_Ack_POLB_IN002121Message)
      {
      }
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(Namespace=
"urn:hl7-org:v3")]
    public class POLB_IN002120Message {
        /// <remarks/> 
      [System.Xml.Serialization.XmlAnyElementAttribute()]
 public System.Xml.XmlElement[] Any;
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(Namespace=
"urn:hl7-org:v3")]
    public class POLB_IN002121Message {      
        /// <remarks/> 
      [System.Xml.Serialization.XmlAnyElementAttribute()]
 public System.Xml.XmlElement[] Any;
    }
}

In this code segment, please note the class definition for the Web service, POLB_AR002942_Service, based on the specification of the corresponding HL7 Application Role, contains two methods: POLB_AR002942_Laboratory_Observation_Order_Activate_Fulfillment_Request

and

POLB_AR002942_Laboratory_Observation_Order_Activate_Fulfillment_Request_No_App_Ack,

ready to receive the two One-Way messages […] POLB_IN002120 and […] POLBIN002121, using a SOAP Literal style.

In the same fragment, the two classes POLB_IN002120Message and POLB_IN002121Message have been created. Those two classes are fundamentally representations —in the programming language—of the message and data types defined within the Types section of the WSDL contract.

It must be noted that, in this example, we defined both XML message types as "Any." In other words, we really did not assign those messages any type. That has been done intentionally to keep the stub code example short and more readable. We will refer to this approach as "Untyped" in the rest of the document.

In fact, if we had inserted the full and correct XSD schema for related HL7 Message Types in the WSDL contract, the code generated would be much more lengthy and complex, since all the message elements and type declarations would have been expanded there into corresponding classes (types) in the used programming language.

Those classes would be defined in the context of each and any generated Service Namespace, which would make them unique entities, in the object model of the application, even when they would refer indeed to the same HL7 Data Type as declared in the contract. So, the same HL7 Message elements or data types used in different messages might end up being translated into different classes in the code generated, which would require a significant amount of manual coding and thus reduce the benefits of automated code production.

Interestingly enough, neither the Web services Proxy nor the Stub need to know the complete structure of the HL7 message they need to deal with. Actually, at the Proxy and Stub level there may be no need—and there should not be—to manipulate the content of HL7 Messages, but mostly to package/un-package them into SOAP messages and transfer to/receive from the Web services infrastructure. The advantage of declaring Message Types as "Any" at this level is that Stubs and Proxies have a much smaller code footprint than if using the HL7 Message Type.

Where some handling of the HL7 message is required at the Stub/Proxy level, for instance to deal with generating synchronous responses and/or addressing and routing from Sender and to Receiver applications, we can use a less radical approach than the Untyped one, yet more practical than the Fully-Typed one.

In fact, we can use a fixed Message Type for HL7 messages that only exposes the Transmission Wrapper and the fixed elements of the Control Act Wrapper, encapsulating the variable part of Control Wrapper and the Body of the message in an opaque way (that is, only these elements are declared "Any"). We will call this approach the "Surrogate" Message Type approach. Code Example 7 is a schema fragment for a Message Type called MCCI_MT000100.Message defined following the Surrogate Message Type approach, while a full schema is attached in Appendix A.

Code Example 7. HL7 Message Surrogate Type Schema Fragment

<!--Embedded in Transmission Wrapper...
[...]
--> 
<xs:complexType name="MCCI_MT000100.ControlActProcess">
   <xs:sequence>
      <xs:any namespace="##other" processContents="lax"
 maxOccurs="unbounded"/>
   </xs:sequence>
   <xs:attribute name="type" type="Classes" default="ControlAct"/>
   <xs:attribute name="classCode" type="ActClass"/>
   <xs:attribute name="moodCode" type="x_ActMoodIntentEvent"/>
   <xs:attribute name="templateId" use="optional">
      <xs:simpleType>
         <xs:list itemType="oid"/>
      </xs:simpleType>
   </xs:attribute>
   <xs:attribute name="typeID" use="optional">
      <xs:simpleType>
         <xs:list itemType="oid"/>
      </xs:simpleType>
   </xs:attribute>
   <xs:attribute name="realmCode" use="optional">
      <xs:simpleType>
         <xs:list itemType="cs"/>
      </xs:simpleType>
   </xs:attribute>
   <xs:attribute name="nullFlavor" type="cs" use="optional"/>
</xs:complexType>

<!--Transmission Wrapper continues...
[...]
--> 

Code example 8 is a portion of the service Proxy code generated using the WSDL.exe tool when using the Surrogate Message Type approach. The reader should compare with the analogous bolded section presented in Code Example 6.

Code Example 8. Service Proxy Code Generated for the Surrogate Message Type

// 
// This source code was auto-generated by wsdl, Version=1.1.4322.2032.
// 
//[...] <-code omitted here
    
    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(TypeName="MCCI_MT000100.
Message", Namespace="urn:hl7-org:v3")]
    public class MCCI_MT000100Message {
        
        /// <remarks/>
        public II id;
        
        /// <remarks/>
        public TS creationTime;
        
        /// <remarks/>
        public ST securityText;
        
        /// <remarks/>
        public MessageversionCode versionCode;
        
        /// <remarks/>
        public II interactionId;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("profileId")]
        public II[] profileId;
        
        /// <remarks/>
        public MessageprocessingCode processingCode;
        
        /// <remarks/>
        public MessageprocessingModeCode processingModeCode;
        
        /// <remarks/>
        public MessageacceptAckCode acceptAckCode;
        
        /// <remarks/>
        public INT sequenceNumber;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("attachmentText")]
        public ED[] attachmentText;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("attentionLine")]
        public MCCI_MT000100AttentionLine[] attentionLine;
        
        /// <remarks/>
        public MCCI_MT000100ControlActProcess controlActProcess;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("receiver")]
        public MCCI_MT000100Receiver[] receiver;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("respondTo")]
        public MCCI_MT000100RespondTo[] respondTo;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("sender")]
        public MCCI_MT000100Sender[] sender;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        [System.ComponentModel.DefaultValueAttribute(Classes.Message)]
        public Classes type = Classes.Message;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string[] templateId;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string[] typeID;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute(DataType="token")]
        public string[] realmCode;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute(DataType="token")]
        public string nullFlavor;
    }

When used in Proxies/Stubs generated from multiple WSDL contracts, the class MCCI_MT000100Message representing the generic HL7 message in the Proxy/Stubs code will be the same and it will still allow Proxy/Stub to consume the elements of the Transmission Wrapper of which they need to have visibility.

At the same time, by using traditional class inheritance techniques, we can inherit the subclass from the generic envelope to constrain it to each and any specific HL7 Message Type. So, we can leverage the advantages previously outlined without compromising our ability to fully use HL7 specification in the implementation.

Sample Application

A reference implementation has been built for the application scenario shown in Figure 3, involving the interaction between two systems: the Hospital Information System (HIS) and the Laboratory Information System (LIS).

  • The HIS consists of two sub-systems, Ordering and Reporting, for which application and Web services have been developed.
  • Similarly, the LIS consists of a Web service, which receives orders from the HIS Ordering System, and the business logic that sends Acknowledgements back to either the HIS Ordering or Reporting System.
  • Here, the Communication Pattern exchange used in this scenario corresponds to "Send Message Payload—with Accept Acknowledgement—Immediate," previously described.
  • To keep the implementation of the business logic simple, while allowing some user interaction with the sample application, two Windows client applications have been developed.

The HIS client application sends order requests to the LIS Web service and displays the receipt acknowledgements of the orders sent. Its user interface (UI) allows the user to Send an Order (the Send button), for which a globally unique identifier (GUID) is automatically generated by the Client Application. The HIS Client UI also displays when the HIS system receives Accept Acknowledge, Confirmation, and Result communication by the LIS system (using three check boxes: OrderAck, ActiveConf, and Result).

ms954603.hl7webservapps05(en-us,MSDN.10).gif

Figure 5. User Interface for Hospital Information System

Similarly, the LIS Client interface allows users to generate the Laboratory_Observation_Order_Activate_Confirmation message (pushing the Send Activate Confi button) and the Laboratory_Observation_Event _Complete_Notification or Result (Send Result button) messages, and send those messages to the HIS Web service, receiving Accept Level Acknowledgements for both of them (acknowledgements are also shown using the Activation Ack and Result Ack check boxes).

ms954603.hl7webservapps06(en-us,MSDN.10).gif

Figure 6. User Interface for Laboratory Information System

The architectural diagram in Figure 7 shows the software components developed in accordance with the architectural discussion presented in previous sections of the document. In this case the Business Logic creates test messages, according to HL7 schema required for the particular interaction, but using a test XML body. At both ends, the Web Services Adapters stores messages in local message queues for the Business Logic to grab.

The following is a step-by-step breakdown of a typical workflow for exchanging HL7 messages in the context of the sample scenario:

  1. When activated by a User Interface signal from HIS Client, the HIS Business Logic generates an Order identifier and constructs the POLB_IN2120Message by creating an XMLDocument and adding the HL7 payload along with the Order ID.
  2. The Business Logic sends the POLB_IN2120Message (Send Order) message to the Adapter, which invokes the LIS service through its Proxy (POLB_AR002942 Service Proxy).

    ms954603.hl7webservapps07(en-us,MSDN.10).gif

    Figure 7. Sample Scenario Architecture

  3. On the Laboratory Side, the POLB_AR002942 Service Stub receives the SOAP message and makes it available to the LIS Web Service Adapter.
  4. The LIS Adapter extracts the HL7 message (Order) from the SOAP message and optionally validates the encapsulated HL7 payload from the SOAP message according to HL7 Message Type schema.
  5. The LIS Adapter stores the HL7 message (Order) in the related Message Queue.
  6. If required, it prepares the Order acknowledgement by constructing a XML document and attaching a predefined response Accept Acknowledge.
  7. The LIS Business Logic retrieves incoming HL7 Messages (Orders) from the Orders Queue and signal the LIS Client when a new message has arrived.
  8. The LIS Client updates the UI accordingly.

The workflows for Order Notifications and for Order Results would be very similar, and we won't expand them here.

For this sample application, we have chosen to use the "Untyped" approach mentioned previously, instead of having to deal with the complexity of generating a full blown HL7 Message Type. A trace of a message exchange is shown in Figure 8, which also shows how the HL7 Message is contained into the SOAP message Body (as requested by HL7 Web Services Basic Profile).

While using Message Queues APIs is pretty straightforward, we can leverage our knowledge of which HL7 Application Roles and Interactions we have to support and of the solution architecture to simplify and even automate the production of this part of Web Service Adapters code.

Click here for larger image.

Figure 8. SOAP Trace for Laboratory Order Message

In fact, we can build tools that for given Application Roles and Interactions, automatically generate the code necessary to create the required Message Queues and to store incoming messages. This is the approach used to build the Web Services Adapter code that interfaces with the Message Queue used in this sample application.

Code Example 9 lists an excerpt of this code. Here, HL7MSgQueueManager is a helper class that provides, among other things, Message Queue creation and retrieval functionalities. In that code segment, the class member m_AppRoleQueues is an array used to store handlers for all the Message Queues created, one per each message received by a Web Service Adapter representing a particular Application Role (note this includes the Accept and Application Level Acknowledgements, as well).

Code Example 9. HL7 Message Queue Manager

namespace HL7WebServicesAdapter {
  using System;
  using System.Messaging;
    
  public class HL7MsgQueueManager {
        
      /*FamANDAssem*/ internal System.Messaging.MessageQueue[]
 m_AppRoleQueues;
        
      /*FamANDAssem*/ internal MessageQueue HL7QueueCreate
(string stQueueName) {
          string stMsgQueuePath;
          System.Messaging.MessageQueue aPriQueue;
          stMsgQueuePath = (".\\Private$\\" + stQueueName);
          if (System.Messaging.MessageQueue.Exists(stMsgQueuePath)) {
              // Return existing Queue.
              aPriQueue = new MessageQueue(stMsgQueuePath);
          }
          else {
              // Create a new Private NonTransactional Queue.
              aPriQueue = System.Messaging.MessageQueue.Create(stMsgQueuePath,
 false);
              aPriQueue.Label = stQueueName;
          }
          return aPriQueue;
      }       
        /*FamANDAssem*/ internal MessageQueue HL7QueueGet
(string stQueueName) {
            string stMsgQueuePath;
            System.Messaging.MessageQueue aPriQueue;
            stMsgQueuePath = (".\\Private$\\" + stQueueName);
            if (System.Messaging.MessageQueue.Exists(stMsgQueuePath)) {
                // Return existing Queue.
                aPriQueue = new MessageQueue(stMsgQueuePath);
            }
            else {
                // Return Nothing.
                aPriQueue = null;
            }
          return aPriQueue;
      }
  }
}

A HL7 Web Service Adapter that wants to use these functions needs to inherit from that base class and create one Message Queue for each Interaction (or Message). This can be easily done, as shown in Code Example 10. As you can see, we used a simple naming convention derived from the HL7 specification to generate the names for the Message Queues: {Application_Role_ID}_{Interaction_ID}. (The code in Examples 9 and 10 may seem a bit verbose. That is partly due to the fact that code has been automatically generated using .Net Platform CodeDom.)

Code Example 10. Queue Manager for Application Role POLB_AR002942

namespace HL7WebServicesAdapter {
    using System;
    using System.Messaging;
    
    
    public class HL7MsgQueueManager_POLB_AR002942 : HL7MsgsQueueManager {
        
        private HL7MsgQueueManager_POLB_AR002942() {
            // Allocate queue manager array with necessary number
 of elements, i.e. queues
            m_AppRoleQueues = new System.Messaging.MessageQueue[2];
            m_AppRoleQueues[0] = this.HL7QueueCreate("POLB_AR002942_
POLB_IN002120");
            m_AppRoleQueues[1] = this.HL7QueueCreate("POLB_AR002942_
POLB_IN002121");
        }
        
        private MessageQueue HL7QueueGet_POLB_AR002942_POLB_IN002120() {
            HL7QueueGet_POLB_AR002942_
POLB_IN002120 = this.HL7QueueGet("POLB_AR002942_POLB_IN002120");
        }
        
        private MessageQueue HL7QueueGet_POLB_AR002942_POLB_IN002121() {
            HL7QueueGet_POLB_AR002942
_POLB_IN002121 = this.HL7QueueGet("POLB_AR002942_POLB_IN002121");
        }
    }
}

Once instantiated into the Web Service Adapter, HL7MsgQueueManager_POLB_AR002942 provides easy and structured access to all the necessary queues for the Application Role POLB_AR002942.

The complete and current version of the sample application, some of the tools for automated code generation (of WSDLs and Queue Adapters), and an open workspace for collaborative development and discussion on this topic is available on the gotdotnet Web site.

Conclusion

The HL7 vision is to create an infrastructure for interoperability in the healthcare domain. HL7 uses the reference information model (RIM) to derive domain specific information models and refine them into HL7 message specifications, ultimately generating XML schema definitions (XSD) associated with a particular Message Type. Because they are interoperable by design, these concepts allow us to model domains on them. Instead of focusing only on technical questions about interoperability, we can look at the HL7 specification and understand how to build the applications, including their roles, collaboration patterns, and messages.

Moving from theory to practice, HL7 doesn't tell us how to architect and design solutions, but when Web services are used, the reference architecture proposed in this paper may be a relevant starting point.

A key concept of the architecture is the Web Services Adapter. You can think of these Adapters as an intermediate application layer between the business logic/application logic and Web Services communication infrastructure. Because of their importance, we spent some time investigating how to build adapters that are conformant with the HL7 specification or, even better, that can be automatically developed starting from that.

We also stressed the importance of using the contract-first development approach (WSDL first) as a way to ensures conformity with HL7 and maximize interoperability among different platforms.

Finally, we provided a sample application that can be used as a reference implementation, and a shared development environment where HL7 Solution Providers can access and extend that implementation.

Microsoft and HL7

Microsoft is a longstanding member of the healthcare development domain, involved with HL7 for ten years and a Healthcare Information and Management Systems Society (HIMSS) member since 2002.

Microsoft contributes to HL7 standard development; for example, as a proponent of Web Services Implementation Profiles.

At the same time, Microsoft is enabling solution developers to adopt HL7, supporting HL7 in its technology platform, such as Biztalk Accelerator for HL7.includes HL7 v2.x messaging, and extends on Biztalk native support of HL7 version 3.0 [BTS].

References

Appendix A

Message Type schema for MCCI_MT000100.

Code Example 11. Proxy Code Generated for Application Role

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<xs:schema targetNamespace="urn:hl7-org:v3" elementFormDefault=
"qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
   xmlns="urn:hl7-org:v3" xmlns:voc="urn:hl7-org:v3:voc"
 xmlns:hl7="urn:hl7-org:v3" xmlns:msg="urn:hl7-org:v3:mif"
   xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <xs:include schemaLocation="../dt/datatypes.xsd" />
   <xs:include schemaLocation="../voc/voc.xsd" />
   <xs:include schemaLocation="../rim/rim.xsd" />
   <!--
**************************************************
***************************************************************
* XML schema for message type .
* Generated by XMLITS version 1.1, Copyright (C) 2002, 2003
 by Health Level 7, Inc.
*
* Copyright (c) 2002, 2003, Health Level Seven. All rights reserved.
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*  1. Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*  2. Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*  3. All advertising materials mentioning features or use
 of this software
*     must display the following acknowledgement:
*       This product includes software developed by Health Level Seven.
*  THIS SOFTWARE IS PROVIDED BY HEALTH LEVEL SEVEN, INC. AND CONTRIBUTORS
 "AS IS" AND
*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
*  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 FOR A PARTICULAR PURPOSE
*  ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
 BE LIABLE
*  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 OR CONSEQUENTIAL
*  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
*  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
*  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY
*  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 OF THE POSSIBILITY OF
*  SUCH DAMAGE.
*
****************************************************
****************************************************************
-->
   <xs:include schemaLocation="COCT_MT040203.xsd" />
   <!--<xs:include schemaLocation="POLB_CA002121.xsd"/>-->
   [...]
   -->
   <xs:element name="Message" type="MCCI_MT000100.Message" />
   <xs:complexType name="MCCI_MT000100.Message">
      <xs:sequence>
         <xs:element name="id" type="II" />
         <xs:element name="creationTime" type="TS" />
         <xs:element name="securityText" type="ST" minOccurs="0" />
         <xs:element name="versionCode" type="Message.versionCode"
 minOccurs="0" />
         <xs:element name="interactionId" type="II" />
         <xs:element name="profileId" type="II" minOccurs="0"
 maxOccurs="unbounded" />
         <xs:element name="processingCode" type="Message.processingCode" />
         <xs:element name="processingModeCode"
 type="Message.processingModeCode" />
         <xs:element name="acceptAckCode" type="Message.acceptAckCode" />
         <xs:element name="sequenceNumber" type="INT" minOccurs="0" />
         <xs:element name="attachmentText" type="ED" minOccurs="0"
 maxOccurs="unbounded" />
         <xs:element name="attentionLine" type=
"MCCI_MT000100.AttentionLine" minOccurs="0" maxOccurs="unbounded" />
         <xs:element name="controlActProcess"
 type="MCCI_MT000100.ControlActProcess" />
         <xs:element name="receiver" type="MCCI_MT000100.Receiver"
 minOccurs="0" maxOccurs="unbounded" />
         <xs:element name="respondTo" type="MCCI_MT000100.RespondTo"
 minOccurs="0" maxOccurs="unbounded" />
         <xs:element name="sender" type="MCCI_MT000100.Sender" minOccurs="0"
 maxOccurs="unbounded" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes" default="Message" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
   <xs:complexType name="MCCI_MT000100.AttentionLine">
      <xs:sequence>
         <xs:element name="keyWordText" type="SC" minOccurs="0" />
         <xs:element name="value" type="ST" minOccurs="0" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes" default="AttentionLine" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
   <xs:complexType name="MCCI_MT000100.ControlActProcess">
      <xs:sequence>
         <xs:any namespace="##other" processContents="lax"
 maxOccurs="unbounded" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes" default="ControlAct" />
      <xs:attribute name="classCode" type="ActClass" />
      <xs:attribute name="moodCode" type="x_ActMoodIntentEvent" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
   <xs:complexType name="MCCI_MT000100.Receiver">
      <xs:sequence>
         <xs:element name="telecom" type="TEL" minOccurs="0" />
         <xs:element name="device" type="MCCI_MT000100.Device"
 maxOccurs="unbounded" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes"
 default="CommunicationFunction" />
      <xs:attribute name="typeCode" type="CommunicationFunctionType" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
   <xs:complexType name="MCCI_MT000100.Device">
      <xs:sequence>
         <xs:element name="id" type="II" />
         <xs:element name="name" type="EN" minOccurs="0"
 maxOccurs="unbounded" />
         <xs:element name="desc" type="ED" minOccurs="0" />
         <xs:element name="existenceTime" type="IVL_TS" minOccurs="0" />
         <xs:element name="telecom" type="TEL" minOccurs="0"
 maxOccurs="unbounded" />
         <xs:element name="manufacturerModelName" type="SC" minOccurs="0" />
         <xs:element name="softwareName" type="SC" minOccurs="0" />
         <xs:element name="agencyFor" type="MCCI_MT000100.Agent"
 minOccurs="0" />
         <xs:element name="location" type="MCCI_MT000100.LocatedEntity"
 minOccurs="0" maxOccurs="unbounded" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes" default="Device" />
      <xs:attribute name="classCode" type="EntityClass" />
      <xs:attribute name="determinerCode" type="EntityDeterminer" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
   <xs:complexType name="MCCI_MT000100.Agent">
      <xs:sequence>
         <xs:element name="representedOrganization"
 type="MCCI_MT000100.Organization" minOccurs="0" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes" default="RoleHeir" />
      <xs:attribute name="classCode" type="RoleClass" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
   <xs:complexType name="MCCI_MT000100.Organization">
      <xs:sequence>
         <xs:element name="id" type="II" />
         <xs:element name="name" type="EN" minOccurs="0"
 maxOccurs="unbounded" />
         <xs:element name="telecom" type="TEL" minOccurs="0"
 maxOccurs="unbounded" />
         <xs:element name="roleName" type="COCT_MT040203.NotificationParty"
 minOccurs="0" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes" default="Organization" />
      <xs:attribute name="classCode" type="EntityClass" />
      <xs:attribute name="determinerCode" type="EntityDeterminer" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
   <xs:complexType name="MCCI_MT000100.LocatedEntity">
      <xs:sequence>
         <xs:element name="location" type="MCCI_MT000100.Place"
 minOccurs="0" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes" default="RoleHeir" />
      <xs:attribute name="classCode" type="RoleClass" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
   <xs:complexType name="MCCI_MT000100.Place">
      <xs:sequence>
         <xs:element name="id" type="II" />
         <xs:element name="name" type="EN" minOccurs="0"
 maxOccurs="unbounded" />
         <xs:element name="telecom" type="TEL" minOccurs="0"
 maxOccurs="unbounded" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes" default="Place" />
      <xs:attribute name="classCode" type="EntityClass" />
      <xs:attribute name="determinerCode" type="EntityDeterminer" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
   <xs:complexType name="MCCI_MT000100.RespondTo">
      <xs:sequence>
         <xs:element name="telecom" type="TEL" minOccurs="0" />
         <xs:element name="entityRsp" type="MCCI_MT000100.EntityRsp"
 maxOccurs="unbounded" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes"
 default="CommunicationFunction" />
      <xs:attribute name="typeCode" type="CommunicationFunctionType" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
   <xs:complexType name="MCCI_MT000100.EntityRsp">
      <xs:sequence>
         <xs:element name="id" type="II" />
         <xs:element name="name" type="EN" minOccurs="0"
 maxOccurs="unbounded" />
         <xs:element name="telecom" type="TEL" minOccurs="0"
 maxOccurs="unbounded" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes" default="EntityHeir" />
      <xs:attribute name="classCode" type="EntityClass" />
      <xs:attribute name="determinerCode" type="EntityDeterminer" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
   <xs:complexType name="MCCI_MT000100.Sender">
      <xs:sequence>
         <xs:element name="telecom" type="TEL" minOccurs="0" />
         <xs:element name="device" type="MCCI_MT000100.Device"
 maxOccurs="unbounded" />
      </xs:sequence>
      <xs:attribute name="type" type="Classes"
 default="CommunicationFunction" />
      <xs:attribute name="typeCode" type="CommunicationFunctionType" />
      <xs:attribute name="templateId" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="typeID" use="optional">
         <xs:simpleType>
            <xs:list itemType="oid" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="realmCode" use="optional">
         <xs:simpleType>
            <xs:list itemType="cs" />
         </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="nullFlavor" type="cs" use="optional" />
   </xs:complexType>
</xs:schema>

Code Example 12. Message Type Schema

Proxy code generated for Application Role POLB_AR002942 when all messages exchange are using Message Type schema defined as in MCCI_MT000100.

// 
// This source code was auto-generated by wsdl, Version=1.1.4322.2032.
// 
namespace HIS {
    using System.Diagnostics;
    using System.Xml.Serialization;
    using System;
    using System.Web.Services.Protocols;
    using System.ComponentModel;
    using System.Web.Services;
    
    
    /// <remarks/>
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Web.Services.WebServiceBindingAttribute(Name="
POLB_AR002942_Binding", Namespace="urn:hl7-org:v3")]
    [System.Xml.Serialization.XmlIncludeAttribute(typeof(CS))]
    public class POLB_AR002942_Service :
 System.Web.Services.Protocols.SoapHttpClientProtocol {
        
        /// <remarks/>
        public POLB_AR002942_Service() {
            this.Url = "http://localhost/LIS/POLB_AR002942";
        }
        
        /// <remarks/>
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute
("hl7:POLB_AR002942_POLB_IN002120", OneWay=true,
 Use=System.Web.Services.Description.SoapBindingUse.Literal,
 ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
        public void POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request([System.Xml.Serialization.XmlElementAttribute
("POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_POLB_IN00" +
"2120.Message", Namespace="urn:hl7-org:v3")] MCCI_MT000100Message
 POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_POLB_IN002120Message) {
            this.Invoke("POLB_AR002942_Laboratory_Observation_Order_
Activate_Fulfillment_Request", new object[] {
                        POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_POLB_IN002120Message});
        }
        
        /// <remarks/>
        public System.IAsyncResult BeginPOLB_AR002942_Laboratory_Observation_Order_
Activate_Fulfillment_Request(MCCI_MT000100Message POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_POLB_IN002120Message, System.AsyncCallback
 callback, object asyncState) {
            return this.BeginInvoke("POLB_AR002942_Laboratory_Observation_
Order_Activate_Fulfillment_Request", new object[] {
                        POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_POLB_IN002120Message}, callback, asyncState);
        }
        
        /// <remarks/>
        public void EndPOLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request(System.IAsyncResult asyncResult) {
            this.EndInvoke(asyncResult);
        }
        
        /// <remarks/>
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute
("hl7:POLB_AR002942_POLB_IN002121", OneWay=true,
 Use=System.Web.Services.Description.SoapBindingUse.Literal,
 ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
        public void POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_No_App_Ack([System.Xml.Serialization.XmlElement
Attribute("POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_No_App_Ac" +
"k_POLB_IN002121.Message", Namespace="urn:hl7-org:v3")]
 MCCI_MT000100Message POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_No_App_Ack_POLB_IN002121Message) {
            this.Invoke("POLB_AR002942_Laboratory_Observation_Order_
Activate_Fulfillment_Request_No_App_Ac" +
"k", new object[] {
                        POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_No_App_Ack_POLB_IN002121Message});
        }
        
        /// <remarks/>
        public System.IAsyncResult
 BeginPOLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_No_App_Ack(MCCI_MT000100Message
 POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_No_App_Ack_POLB_IN002121Message, System.
AsyncCallback callback, object asyncState) {
            return this.BeginInvoke("POLB_AR002942_Laboratory_Observation_
Order_Activate_Fulfillment_Request_No_App_Ac" +
"k", new object[] {
                        POLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_No_App_Ack_POLB_IN002121Message}, callback,
 asyncState);
        }
        
        /// <remarks/>
        public void EndPOLB_AR002942_Laboratory_Observation_Order_Activate_
Fulfillment_Request_No_App_Ack(System.IAsyncResult asyncResult) {
            this.EndInvoke(asyncResult);
        }
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(TypeName=
"MCCI_MT000100.Message", Namespace="urn:hl7-org:v3")]
    public class MCCI_MT000100Message {
        
        /// <remarks/>
        public II id;
        
        /// <remarks/>
        public TS creationTime;
        
        /// <remarks/>
        public ST securityText;
        
        /// <remarks/>
        public MessageversionCode versionCode;
        
        /// <remarks/>
        public II interactionId;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("profileId")]
        public II[] profileId;
        
        /// <remarks/>
        public MessageprocessingCode processingCode;
        
        /// <remarks/>
        public MessageprocessingModeCode processingModeCode;
        
        /// <remarks/>
        public MessageacceptAckCode acceptAckCode;
        
        /// <remarks/>
        public INT sequenceNumber;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("attachmentText")]
        public ED[] attachmentText;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("attentionLine")]
        public MCCI_MT000100AttentionLine[] attentionLine;
        
        /// <remarks/>
        public MCCI_MT000100ControlActProcess controlActProcess;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("receiver")]
        public MCCI_MT000100Receiver[] receiver;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("respondTo")]
        public MCCI_MT000100RespondTo[] respondTo;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("sender")]
        public MCCI_MT000100Sender[] sender;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        [System.ComponentModel.DefaultValueAttribute(Classes.Message)]
        public Classes type = Classes.Message;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string[] templateId;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string[] typeID;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute(DataType="token")]
        public string[] realmCode;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute(DataType="token")]
        public string nullFlavor;
    }


Show:
© 2014 Microsoft