One thing that makes working with HL7 messages in BizTalk a bit different from working with other standards like EDIFACT and X12 is that the HL7 assembler and disassembler relies on multipart messages for separating the header segments, body segments and extension segments (Z segments).
This makes it a lot easier to use a BizTalk map to create any header segments. Unfortunately this also means that we need orchestrations, even if we are not orchestrating any request response messages. Orchestrations tend to add a lot of complexity to BizTalk integrations, especially if no message orchestration is used. Orchestrations are also hard to make reusable and we typically end up creating an orchestration for every integration.
It is also not always a good thing that headers are created in a BizTalk map. Imagine we have a scenario where we receive an XML message with an envelope that should be mapped and sent with HL7 and the MSH header segment should be based on the envelope from the incoming message. A common way of handling XML envelopes in BizTalk is having the XML Disassembler remove the envelope and promote the elements of interest. But doing so makes the envelope elements inaccessible to the map. Creating a map for the envelope is usually not an option since the envelope can contain many different type of messages and BizTalk uses namespace + root node for identifying the message.
What we would want to do is to send an HL7 message from BizTalk and base the MSH header segment on properties from the envelope of the incoming message by promoting them on recieve and demoting them on send. Having a generic pipeline component creating the message parts instead of an orchestration helps keeping the integration simple and easy to maintain. The message body would be created with an ordinary non multipart map executed on the send port.
There is nothing special going on here just out of the box ordinary XML Envelope handling in BizTalk.
The first thing to do is to strip the envelope from the message and promote all properties that we want to use in the outgoing message.
To achieve this we need to create the schemas of the incoming message. One Envelope schema and one schema for the actual message.
Make sure to make set the schema to an Envelope schema
And set the body xpath to the body node.
Create the body schema
Then create a property schema containing a property for every MSH field we want to set.
Now edit the envelope property to promote each element to the corresponding MSH field, i.e. sender is promoted to the MSH31 context property and recipient is promoted to the MSH51 property. Set up a Receive port and a Receive location with the XML Receive pipeline.
Just create an ordinary map with the incoming message body as input and the HL7 body segment schema as output.
Create a new send port with the newly created map as outbound map.
If we try to run this as is through the HL7 assembler it won’t work since the assembler expects to find three message parts, MSHSegment, BodySegments and Z Segments. So we need to create a pipeline component that can create the MSH segment based on the previously promoted properties and create the message parts, this is where the magic happens.
To create the MSH segment we are going to use property demotion. For this to happen we need to setup property promotion from the BizTalk MSH schema to the property schema we created previously.
To create an instance of the MSH schema and demote the MSH context properties to it I am going to use the same technique I used in a previous blog post
What this method does is take a parameter for the DocumentSpecName of the BizTalk MSH schema used. It then creates an instance of schema and iterates through all defined properties and demotes them from context. The new XML is then added to a new message part.
Z segments are not used in this scenario so we just set it to an empty string (it must still exists).
The Execute method of the component is quite simple. It just uses the above methods to create the segments and add it to the outbound message.
The part.Charset = “utf-8” part is very important. Without this national characters like åäö won’t work. The casing of the charset is also important.
So what have we gained here? First of all we have gotten rid of any orchestration, which always feels good :). This pipeline component has no dependencies to any specific schemas which makes it easy to reuse in any integration where we want to send HL7 messages as long we can promote any header data to a property schema. The source code for this component is available here