Wednesday, 15 June 2011

Walkthrough using BizTalk HL7 Accelerator, Schemas and MLLP Adapter

This post will show you how to Setup BizTalk HL7 Projects, Create and use HL7 Schemas and basic configuration of MLLP Adapter.

Introduction:

  1. By this time you should be aware what HL7 Message is. If not, just Google it.


In BizTalk Server, there is a schema supporting each type of HL7 Message. These schemas can be found once you install BizTalk HL7 Accelerator. They will be available in the below path.

<drive>:\Program Files\Microsoft BizTalk 2010 Accelerator for HL7\Templates\Schemas\V2.X\2.5 or any 2.x



Each folder in the above has various HL7 Schemas required for your EAI Solution.

2. To test the HL7 Solution (from the developer aspect) a HL7 Simulator is required. For eg: 7Edit. Download a trail version of this software for testing the sample application in this post.

This Resultant HL7 Message from our EAI Solution will be sent to 7Edit via MLLP Adapter (MLLP is the protocol that is used to Transport HL7 Messages. It uses TCP/IP Internally).
7Edit in turn gives us an HL7 (not BizTalk) Acknowledgement (ACK) / Negative Acknowledgement (NACK).

3. The ACK / NACK given by this 7edit will be captured by the TwoWayAckReceivePort which is created automatically when you install BizTalk HL7 Accelerator.



Please note that this TwoWayAckReceivePort is must to receive that ACK/NACK. If this port is not present in your Admin Console, it means that you didn’t install HL7 Accelerator properly.
This TwoWayAckReceivePort has one receive loacation TwoWayAckReceiveLocation that is configured to use BTAHL72XReceivePipeline.

Sample Scenario:

1. In this Post we receive a HL7 ORU (Observation Result) Message of Version 2.5.

2. Convert that message to an ORU 2.4 Version message.

3. Add the necessary MSH Segment (Every HL7 Message should have a MSH Segment. This is like Header).

4. Send the resultant 2.4 version Message to 7Edit using MLLP Adapter.

5. 7Edit will give us ACK/NACK.

6. Capture the ACK Message.

Example:

1. The HL7 Schema that we are going to use here is ORU_R01_25_GLO_DEF.xsd & ORU_R01_24_GLO_DEF.xsd. Each HL7 Schema has 100s of nodes and each of these nodes is of a particular complex Type. These complex types are in turn available in three separate schemas datatypes_25.xsd, segments_25.xsd and tablevalues_25.xsd.

Normal Convention is to Create a separate project for these common schemas and reference the dll of these common schemas project in the actual project that uses the main schema ORU_R01_25_GLO_DEF.xsd

i) Create an Empty Solution.

ii) Add a Folder to it named Common (or anything else). Right click the Common and Select Add new Project.

iii) Select BTAHL7V25Common Project and Click Ok.



iv) Repeat and add BTAHL7V24Common Project.

Alternatively, you can create an Empty BizTalk Project and add the common schemas datatypes_25.xsd, segments_25.xsd and tablevalues_25.xsd by yourself. These schemas will be in the location  <drive>:\Program Files\Microsoft BizTalk 2010 Accelerator for HL7\Templates\Schemas\V2.X\2.5 or any 2.x

2. To the 2.5 Version of the common project, add the MSH schema MSH_25_GLO_DEF.xsd. You can find this one in <drive>:\Program Files\Microsoft BizTalk 2010 Accelerator for HL7\Templates\Schemas\V2.X\2.5 location.

This schema is required for HL7 Pipeline.

3. Add an Empty BizTalk Project to the main solution and add the ORU_R01_24_GLO_DEF.xsd and ORU_R01_25_GLO_DEF.xsd (<drive>:\Program Files\Microsoft BizTalk 2010 Accelerator for HL7\Templates\Schemas\V2.X\2.5\Observation Reporting\ORU) schemas. Resultant solution should be like below.

(Here the schemas come with Microsoft Namespace. Namespaces should be changed as required).



4. Add references of the two common Projects to the main project and try to build the solution. The solution should work fine.

5. Create a map between the V25 and V24 versions of the schemas.



6. Create an Empty Orchestration. Add a receive shape and a receive port to receive the messages of the type ORU_R01_25_GLO_DEF.xsd schema. Set the Activate to True.



7. Add a transform shape to the Orchestration and Use the map create in step 4 and convert the v25 Message to v24 Message (of type ORU_R01_24_GLO_DEF.xsd)



8. Now you have the 2.4 Version of ORU_R01_24_GLO_DEF Message.
This message as such is not sufficient to convert it into an HL7 Message. Every HL7 Message should have an MSH Segment.
Now we should convert the ORU_R01_24_GLO_DEF Message into a real HL7 Message.

9. Create a new Multipart Message with 3 Body Parts as below.

i) BodySegments -> MLLPAdapter.ORUSchemas.ORU_R01_24_GLO_DEF (Should be the Primary Body Part. Message Body Part Property should be set to True)
ii) MSHSegment -> BTAHL7Schemas.MSH_25_GLO_DEF (added in step 2)
iii) ZSegments -> System.String



Note that the names should be given in the same way as mentioned. Hl7 Pipeline will be using the same names.

10. Create a new message of the Multipart Type created in step 9 and add a Message Assignment shape to the Orchestration to Construct the MultiPart Message.



11. Add the following code in the Message Assignment Shape.

v24MultiPart.BodySegments = v24;
str = @"<MSH_25_GLO_DEF xmlns='http://microsoft.com/HealthCare/HL7/2X'>
    <MSH xmlns=''>
      <MSH.2_EncodingCharacters>^~\&amp;</MSH.2_EncodingCharacters>
      <MSH.3_SendingApplication>
        <HD.0_NamespaceId>MyHealthCareCompany</HD.0_NamespaceId>
      </MSH.3_SendingApplication>
      <MSH.4_SendingFacility>
        <HD.0_NamespaceId>MyHealthCareCompany</HD.0_NamespaceId>
        <HD.1_UniversalId>12</HD.1_UniversalId>
        <HD.2_UniversalIdType>L,M,N</HD.2_UniversalIdType>
      </MSH.4_SendingFacility>
      <MSH.5_ReceivingApplication>
        <HD.0_NamespaceId>MyReceivingCompany</HD.0_NamespaceId>
      </MSH.5_ReceivingApplication>
      <MSH.6_ReceivingFacility>
        <HD.0_NamespaceId>MyReceivingCompany</HD.0_NamespaceId>
      </MSH.6_ReceivingFacility>
      <MSH.7_DateTimeOfMessage>
        <TS.1>20110217203656+0530</TS.1>
      </MSH.7_DateTimeOfMessage>
      <MSH.9_MessageType>
        <CM_MSG.0_MessageType>ORU</CM_MSG.0_MessageType>
        <CM_MSG.1_TriggerEvent>R01</CM_MSG.1_TriggerEvent>
        <CM_MSG.2_MessageStructure>ORU_R01</CM_MSG.2_MessageStructure>
      </MSH.9_MessageType>
      <MSH.10_MessageControlId>19316405-a86e-4dfe-afff-542128d80bd6</MSH.10_MessageControlId>
      <MSH.11_ProcessingId>
        <PT.0_ProcessingId>P</PT.0_ProcessingId>
        <PT.1_ProcessingMode>A</PT.1_ProcessingMode>
      </MSH.11_ProcessingId>
      <MSH.12_VersionId>
        <VID_0_VersionId>2.4</VID_0_VersionId>
      </MSH.12_VersionId>
      <MSH.13_SequenceNumber>1</MSH.13_SequenceNumber>
      <MSH.15_AcceptAcknowledgmentType>AL</MSH.15_AcceptAcknowledgmentType>
      <MSH.21_ConformanceStatementId>
        <EI_0_EntityIdentifier>AA</EI_0_EntityIdentifier>
      </MSH.21_ConformanceStatementId>
    </MSH>
  </MSH_25_GLO_DEF>";

xmldoc.LoadXml(str);
v24MultiPart.MSHSegment = xmldoc;
v24MultiPart.ZSegments="";

v24MultiPart(BTAHL7Schemas.ParseError) = false;
v24MultiPart(BTAHL7Schemas.SegmentDelimiter2Char) = true;
v24MultiPart(BTAHL7Schemas.ZPartPresent) = false;
v24MultiPart(BTAHL7Schemas.MessageClass) = "MessageClass2X";
v24MultiPart(BTAHL7Schemas.MessageEncoding) = 65001;

Note:

i) v24MultiPart is the Multipart Message Constructed.
ii) Str and xmldoc are sting and XmlDocument Variables.
iii) V24 is message created out of the Map.
iv) A reference to the dll Microsoft.Solutions.BTAHL7.HL7Schemas (:\Program Files\Microsoft BizTalk 2010 Accelerator for HL7\Bin\) should be added.

12. Add a send shape to send the MultiPart message out.



13. Sign and Deploy the Application.

14. Create a new Receive Port and File Receive Location as shown below. Bind it to the Logical Receive Port of the Orchestration.



15. Create a new send port and set the Adapter to MLLP. Configure the Adapter as shown below. Bind this Send port to the Send port of the Orchestration.

Incase if you don’t find the Pipeline shown below in your project, it might have got installed in Default Application. You have to move it to your Application. This Pipeline is responsible for converting our Multipart message into a HL7 Message.



16. Configure 7Edit to receive the HL7 Message sent by the above step.
Open 7Edit, Click on Profiles -> Add Profiles and create a new profile as shown below.





17. Finally create a send port to receive the Acknowledgement Sent by the 7 Edit. This ACK / NACK will be received by the TwoWayAckReceivePort that is created automatically when you install BizTalk HL7 Accelerator.

So, create a send port with File Adapter and set the Filter Condition pointing to TwoWayAckReceivePort.





18. Start the Application. Drop an input file of ORU 25 type in the input folder. Sample File is below.

<ORU_R01_25_GLO_DEF xmlns="http://microsoft.com/HealthCare/HL7/2X">
    <PID_PatientIdentification xmlns="">
      <PID_1_SetIdPid>1</PID_1_SetIdPid>
      <PID_2_PatientId />
      <PID_3_PatientIdentifierList>
        <CX_0_IdNumber>7060106805</CX_0_IdNumber>
        <CX_4_IdentifierTypeCode>AM</CX_4_IdentifierTypeCode>
      </PID_3_PatientIdentifierList>
      <PID_5_PatientName>
        <XPN_0_FamilyName>
          <XPN_0_0_Surname>DOUGLAS</XPN_0_0_Surname>
        </XPN_0_FamilyName>
        <XPN_1_GivenName>KENNETH</XPN_1_GivenName>
        <XPN_6_NameTypeCode>B</XPN_6_NameTypeCode>
      </PID_5_PatientName>
      <PID_7_DateTimeOfBirth>
        <TS_0_Time>19600222</TS_0_Time>
      </PID_7_DateTimeOfBirth>
      <PID_8_AdministrativeSex>A</PID_8_AdministrativeSex>
    </PID_PatientIdentification>
    <PV1_PatientVisit xmlns="">
      <PV1_1_SetIdPv1>1</PV1_1_SetIdPv1>
      <PV1_2_PatientClass>U</PV1_2_PatientClass>
      <PV1_7_AttendingDoctor>
        <XCN_0_IdNumber>A123</XCN_0_IdNumber>
        <XCN_1_FamilyName>
          <XCN_1_0_Surname>Test</XCN_1_0_Surname>
        </XCN_1_FamilyName>
        <XCN_2_GivenName>Test</XCN_2_GivenName>
        <XCN_3_SecondAndFurtherGivenNamesOrInitialsThereof>T</XCN_3_SecondAndFurtherGivenNamesOrInitialsThereof>
      </PV1_7_AttendingDoctor>
      <PV1_17_AdmittingDoctor>
        <XCN_0_IdNumber>G21549</XCN_0_IdNumber>
        <XCN_1_FamilyName>
          <XCN_1_0_Surname>Rosenfeld</XCN_1_0_Surname>
        </XCN_1_FamilyName>
        <XCN_2_GivenName>David</XCN_2_GivenName>
        <XCN_7_SourceTable>MD</XCN_7_SourceTable>
      </PV1_17_AdmittingDoctor>
    </PV1_PatientVisit>
    <Observation xmlns="">
      <ORC_CommonOrder>
        <ORC_1_OrderControl>AF</ORC_1_OrderControl>
        <ORC_2_PlacerOrderNumber>
          <EI_0_EntityIdentifier>123</EI_0_EntityIdentifier>
        </ORC_2_PlacerOrderNumber>
        <ORC_3_FillerOrderNumber>
          <EI_2_UniversalId>P20005</EI_2_UniversalId>
        </ORC_3_FillerOrderNumber>
        <ORC_12_OrderingProvider>
          <XCN_0_IdNumber>A123</XCN_0_IdNumber>
          <XCN_1_FamilyName>
            <XCN_1_0_Surname>Test</XCN_1_0_Surname>
          </XCN_1_FamilyName>
          <XCN_2_GivenName>Test1</XCN_2_GivenName>
          <XCN_3_SecondAndFurtherGivenNamesOrInitialsThereof>T</XCN_3_SecondAndFurtherGivenNamesOrInitialsThereof>
        </ORC_12_OrderingProvider>
      </ORC_CommonOrder>
      <OBR_ObservationRequest>
        <OBR_1_SetIdObr>1</OBR_1_SetIdObr>
        <OBR_2_PlacerOrderNumber>
          <EI_0_EntityIdentifier>7060106805</EI_0_EntityIdentifier>
        </OBR_2_PlacerOrderNumber>
        <OBR_3_FillerOrderNumber>
          <EI_0_EntityIdentifier>1</EI_0_EntityIdentifier>
          <EI_1_NamespaceId>1</EI_1_NamespaceId>
          <EI_2_UniversalId>P145773</EI_2_UniversalId>
          <EI_3_UniversalIdType>DNS</EI_3_UniversalIdType>
        </OBR_3_FillerOrderNumber>
        <OBR_4_UniversalServiceIdentifier>
          <CE_0_Identifier>13130</CE_0_Identifier>
          <CE_1_Text>Test Report</CE_1_Text>
        </OBR_4_UniversalServiceIdentifier>
        <OBR_7_ObservationDateTime>
          <TS_0_Time>20060124120000+0530</TS_0_Time>
        </OBR_7_ObservationDateTime>
        <OBR_11_SpecimenActionCode>A</OBR_11_SpecimenActionCode>
        <OBR_15_SpecimenSource>
          <SPS_0_SpecimenSourceNameOrCode>
            <SPS_0_0_Identifier>ALL</SPS_0_0_Identifier>
            <SPS_0_1_Text>Urine</SPS_0_1_Text>
          </SPS_0_SpecimenSourceNameOrCode>
        </OBR_15_SpecimenSource>
        <OBR_16_OrderingProvider>
          <XCN_0_IdNumber>G21549</XCN_0_IdNumber>
          <XCN_1_FamilyName>
            <XCN_1_0_Surname>Rosenfeld</XCN_1_0_Surname>
          </XCN_1_FamilyName>
          <XCN_2_GivenName>David</XCN_2_GivenName>
          <XCN_7_SourceTable>MD</XCN_7_SourceTable>
          <XCN_12_IdentifierTypeCode>AN</XCN_12_IdentifierTypeCode>
        </OBR_16_OrderingProvider>
        <OBR_21_FillerField2>Hello</OBR_21_FillerField2>
        <OBR_22_ResultsRptStatusChngDateTime>
          <TS_0_Time>20060221102000+0530</TS_0_Time>
        </OBR_22_ResultsRptStatusChngDateTime>
        <OBR_25_ResultStatus>Y</OBR_25_ResultStatus>
        <OBR_27_QuantityTiming>
          <TQ_0_Quantity>
            <TQ_0_0_Quantity>1</TQ_0_0_Quantity>
          </TQ_0_Quantity>
        </OBR_27_QuantityTiming>
      </OBR_ObservationRequest>
      <ObservationResults>
        <OBX_ObservationResult>
          <OBX_1_SetIdObx>1</OBX_1_SetIdObx>
          <OBX_2_ValueType>AD</OBX_2_ValueType>
          <OBX_3_ObservationIdentifier>
            <CE_0_Identifier>123</CE_0_Identifier>
            <CE_1_Text>RxGuardian</CE_1_Text>
          </OBX_3_ObservationIdentifier>
          <OBX_5_ObservationValue>Hello</OBX_5_ObservationValue>
          <OBX_7_ReferencesRange>1-2</OBX_7_ReferencesRange>
          <OBX_8_AbnormalFlags>LL</OBX_8_AbnormalFlags>
          <OBX_11_ObservationResultStatus>C</OBX_11_ObservationResultStatus>
          <OBX_15_ProducerSId>
            <CE_2_NameOfCodingSystem>C4</CE_2_NameOfCodingSystem>
          </OBX_15_ProducerSId>
        </OBX_ObservationResult>
      </ObservationResults>
    </Observation>
  </ORU_R01_25_GLO_DEF>

19. You can observer that 7Edit receives the file and sends an Acknowledgement.



20. The ACK will then be received by the send port you created in step 17.

Now try testing this by yourself by modifying some of the steps and see what kind of errors you get. For eg - in step 9, try giving different names to Multipart message and see. This way you will be able to learn more.

Hope this is helpful. Post if you need the source code.

- Shiv
Web Counters

2 comments:

  1. Hi Shiv,

    Thank you for your intersting tutorial.
    I followed the described steps and got the solution running. However, there is no output in the 7Edit receiver tab, though, when querying the BTS Admin console, the message status is set as "completed". Am I missing something? Also, it would be great if you post the source code, !

    Thanks,

    Alex

    ReplyDelete
  2. Hi Shiv,

    Are you available for Biztalk support work? I'm looking for someone to help me with my project. Please contact me if you are with your rate for a day's support on:

    emailfromshiv@jadsent.com

    Regards,

    Colin

    ReplyDelete