Eric’s BizTalk 2004/2006 Blog

My BizTalk Experiences using Flat Files, InfoPath, BAM, BRE, BAS, HL7, HIPAA, WSS.

October 2, 2006

Case of the missing CR

Filed under: BizTalk, HL7 — eric @ 5:48 am

There are certain cases where a sending application will not send the ending CR as part of the HL7 message.

The HL7 parser will complain at not finding the ending CR, because it continues to look for it past the EB.

The resolution is simply to leave the CR blank in the adapter configuration and the adapter will work as expected.

Gotta tip your hat to the guys at MS for that bit of functionality!

September 13, 2006

System.OutofMemoryException when processing large files

Filed under: BizTalk, HL7, HIPAA — eric @ 1:50 pm

A client I have been working at has a very large message (150 mb message) that needs to be passed through BizTalk from the results of a stored procedure.

I was continually getting System.OutofMemoryException in the event log.

I read through this article and also this one both sites options did not appeal to me.

Another option is to use custom XSLT instead of the code inside of the map (which seems to stream the entire message into memory).

The solution is actually very easy:

  1. Create your map
  2. Inside of the mapper, create all of your links, functiods and everything
  3. Validate the map
  4. Take the XSLT that is generated and add it to your project
  5. In the mapper grid, point to the xslt (by following these instructions)
  6. Deploy it

It does not process the file very quickly, but it does not error, and I get the output.

August 29, 2006

MS-HUG - what a wonderful event!

Filed under: BizTalk, HL7, HIPAA — eric @ 8:46 pm

I just attended the first (of I am sure) many HiMSS conferences. I am kicking myself for not going to them sooner. I got to meet a few friends that I have been in contact with, and other fellow bloggers, well I wouldn’t call him just a blogger, but that is another discussion. I also met with some guru’s that offered a lot of insight!

There were great sessions for a whole spectrum of Health Care Professionals, from developers to IT Pros, to management for both the partners and more importantly customers. There were a lot of great things that partners had presented and even more cool things that Microsoft has in store. I did enjoy the other perks that were offered to the attendees, especially the sessionitis I seemed to come down with!

I was very interested in the Connected Health Framework (CHF) and will be blogging about my experiences with my take on best ways to implement the CHF to add additional value to the development life cycle. I don’t think that the CHF is readily available (at least I could not find it), however, as soon as it is published, I will be adding a few entries to my blog.

There are great things going on, and I am glad that I got to be an attendee there. Hopefully I can meet up with you again next time.

August 26, 2006

Inner exception: Multi-part message has body part ‘BodySegments’, expected body part ‘MSHSegment’.

Filed under: BizTalk, HL7 — eric @ 1:23 pm

I am not sure how many times I have come across this error. I finally had a few moments to actually troubleshoot this error.

The reason for this message is that the orchestration is expecting as the first message part being the MSH segment, whereas it actually finds the BodySegments component. The orchestration then attempts to pick up the message, which is where it errors.

The key to getting this issue resolved is the order that you create the multi-part message.

I know I have made this mistake multiple times, I create the multi-part message type, and renamed the MessagePart_1 to BodySegments, since the IsBodyPart property was already set to true, I then would create the MSHSegment and ZSegments.

This would cause me headaches because the orchestration picking up the message would create the error.

Looking at the code, you have to create the message parts in the correct order. In the Type window, you see the parts in alphabetical order.
Multi Part Messages

However, behind the scenes, it remembers the order that it was created. I have the following excerpt of the odx that shows what is going on behind the scenes: The ADT_A02Type is correct, whereas the ADT_A03Type is incorrect.
orchestrationcode.JPG

So make sure that you create the parts in the correct order and you will not have a problem. If they are created in the wrong order, the only solution I have used is to delete the multi-part message and recreate it again.

By the way, this is only an issue on message that are inbound, outbound messages, the pipeline component is intelligent enought to put things together (even if they are defined in the wrong order), it is the orchestration that consumes the message that is finicky.

August 22, 2006

Single HL7 ACK or NAK, either from the pipeline or from the application

Filed under: BizTalk, HL7 — eric @ 1:16 am

One question I have been asked often is how to only produce one acknowledgement from within BizTalk. This is a common requirement of many HL7 applications, only to recieve one ACK. If there is an error, you want the pipeline component to create the NAK and then send back the NAK, otherwise, you want to create the ACK/NAK (depending on BizTalk logic) that represents whether BizTalk was able to process the correctly formatted HL7 message.

The first thing is to configure the Accelerator to generate the NAK only on errors:
IE Config
Notice that in HL7 1.3 there is a check mark box for Routing ACKs to send Pipeline. Having this check mark box binds the ack that is generated in the receive pipeline to the original message. (This is the standard behavior in the HL7 1.0 accelerator.) I am leaving this checked so it can be set up simarly in the 2004 version. If this box is not checked, the ACK is not bound to its orignal message and the dependency for both messages to have a destination is broken, so ACK or Messages can find themselves in the Message box with no place to go.

You want to have MSH 15 set to NE (Never) and MSH 16 to ER (Error), so you will only create an application error if there is structural errors. If you set MSH 15 to anything but NE, you will get an ACK of CA and also a possible Application NAK, which normally the sending application is not expecting. So this setting will only cause a possible one NAK to be produced (if there is only an error).

Then you need to configure your orchestration to only accept good HL7 messages. In your receive port, you need to set the following properties:
Receive Port Properties
Where there is a HL7 property to only activate when there are no parse errors. If this is not set, orchestrations will spin up if there are messages that are invalid (the HL7 receive pipeline will drop the bad HL7 message as a text blob and the orchestration will pick it up, and will immediately become suspended).

This is in 1.0 and 1.3, this functionality has been expanded to all BizTalk parsing in 2006 using the ErrorReport… context properties.

The last thing that needs to be done is to set up a port that will drop the HL7 messages off if there is an error. Because we have enabled the ack to be sent on the request-response port, for the NAK to be sent, we need to have a place for the bad HL7 message. I have created a seperate HL7 port using the Default.PassThru pipeline and writing it out at %MessageID%”.txt. The filter I use is the following:
Bad Mllp Data Port
If we do not set up this port, and there is an error parsing the data, the messages (NAK and original HL7 message) get stuck in the Message Box because there is no place for the bad message to go.

Using the Sample ADT^A03.txt and Sample Bad ADT^A03.txt in this solution, you can create a two-way receive port and one Bad HL7 Dump port you can test the configuration and see that only one HL7 ACK/NAK is created. This is a very simple orchestration that creates the HL7 ACK, but it is here in the orchestration is where you would create the MSA 1 ‘AA’ or ‘AE’ depending on your business logic.

August 19, 2006

MLLP Receive Test Tool

Filed under: BizTalk, HL7 — eric @ 12:08 pm

In an effort to expand on this entry, while testing, there are many times where I have to use the mllpreceive.exe to capture data.

I have made it easy by adding right click functionality.

I created a batch file called Receive.bat with the following contents:

MLLPRECEIVE.EXE /P 12000 /SPLIT /SB 11 /EB 28 /CR 13 /D %1

I then went into Tools -> folder options and choose File Types and chose Folder (not File Folder) and choose Advanced. In the Action I put mllp and the Application used to perform this action I type “{path}Receive.bat” “%1″

Now when I want to receive message and put them in a particuar folder, I right click on the folder, choose mllp from within Explorer, and a dos window comes up with the correct folder that will be the location of where the data will be written to.

August 9, 2006

Line Feed <0a> in HL7 data when not defined in MLLP Port

Filed under: BizTalk, HL7 — eric @ 5:30 am

A friend emailed me asking why he was getting a <0d><0a> in his HL7 data when he defined in his Send Port, the following:
Port Properties
You would expect that the data would be:

MSHSegment<0d>PIDSegment<0d>…

But he was getting

MSHSegment<0d><0a>PIDSegment<0d><0a>…

In the message assignment of the multi-part message before you send the data out, if you want only <0d> and not <0d><0a>, you need to set the following context property to false. In the tutorials, you are instructed to put true.

OutgoingMsg(BTAHL7Schemas.SegmentDelimiter2Char)=false;

Although I already mentioned it, OutgoingMsg(BTAHL7Schemas.MSH1)=124; is the decimal value of the | character

August 4, 2006

Looping in HL7 Messages

Filed under: BizTalk, HL7 — eric @ 9:18 pm

I can’t remember how many times I have read entries posted on the various forums asking how to get looping correct in the HL7 messages. A couple of friends have asked how I have done it, so I thought that I would post how you do it.

The real issue is that the looping does not follow the necessary structure defined in the HL7 schemas. The source records in many cases need to match with sequence group (which is not possible in the BizTalk mapper). In the following example, after mapping out some sample data, I manually ran the map, and this is the result I received for the ORU_R01:
mappersample.JPG
but this will not work, because OBR 4.1 does not repeat and will cause the BTAHL7 ASM will throw errors, for this and a LOT of other non-conforming message structures.

In the mapper, what I really need is highlighted in RED:

Fake Mapping
So I reverted to XSLT to do what I needed to be done. I did all of the mapping, afterwards, I right clicked the map and chose Validate Map, and opened up the TestMap_xslt.xml in a text editor.

I then edited the xslt and moved around/deleted the xsl:for-each select=”Order” tags, and also some of the tags. I then saved the document as XSLTMap.xslt.I created a new map (XSLTMap.btm), defined the input schema and the output schema, clicked on the grid and chose Custom XSLT Path and browsed to the xslt file I just created (XSLTMap.xslt). I then tested it against the xml document and made sure that it looked correct.

In the orchestration I created a construct shape, and created 3 maps that defined all three message parts (compared to how the tutorial works, as I don’t really like to hard code stuff in a message assignment shape). I did have to assign some context properties in a message assignment shape, and then sent it off.

I ended up getting the following error:
Alternate Error Number: 301
Alternate Error Description: XmlReader not positioned at root elment of ‘ORU_R01_231_GLO_DEF’
Alternate Encoding System: HL7-BTA

The issue ended up being that in my custom xslt, there is the following tag: omit-xml-declaration=”no”

This caused the BodySegments message part to look like this at the beginning of the message:
xmlheader.JPG
So in the xslt, it is necessary to make sure that the omit-xml-declaration=”yes”

Here is the example (BizTalk 2004) that transforms the following XML message:
Original XML

And transforms it in the correct repeating structure to:

MSH|^~\&|Sender||Receiver||||ORU^R01|1234567|D|2.3.1
OBR||||^ServiceID_1
NTE|||Note_1
OBX||AD|^Text_1||||||||C
NTE|||Comment_1~Comment_2
OBX||CE|^Text_2||||||||D
NTE|||Comment_3~Comment_4
OBX||CF|^Text_3||||||||F
NTE|||Comment_5~Comment_6
OBX||CK|^Text_4||||||||I
NTE|||Comment_7
CTI|^^Id_1
OBR||||^ServiceID_2
NTE|||Note_2
OBX||CN|^Text_5||||||||N
NTE|||Comment_8~Comment_9
OBX||CP|^Text_6||||||||O
NTE|||Comment_10
CTI|^^Id_2

So in order to keep the correct looping, you need to be a little XSLT savy, but after playing with it for a little bit, you should be able to get your output correct.

The solution has the initial mapping called TestMap.btm, the results of that map:HL7Msg_MisAlligned_BodySegments.xml, the final map: XSLTMap.btm, the trigger xml:Data.xml, along with the 2XCommon and 231Common projects.

I checked with some friends at Microsoft to confirm that this is the only solution for the looping dilemma but it looks like there is light at the end of the tunnel (I will post the official documentation as soon as I know):

This is a known issue in the BizTalk mapper which impacts mapping HL7 v2.x schemas.

I’m happy to report some good news on this.  A DCR, to allow the BizTalk mapper to preserve order for repeating segments in the XSLT generation process, has been accepted this week to be included in BizTalk Server 2006 R2.  In the meantime, we are documenting a process that requires generating an XSLT with the BizTalk mapper, then manually inserting a loop in the XSLT around the nodes in the sequence where the order needs to be preserved.

Redmond Conferences

Filed under: BAM, BizTalk, HL7, HIPAA, InfoPath, SharePoint, BRE, SQL — eric @ 1:14 pm

I am heading up to Redmond for a couple of conferences:
mshug_techforum_masthead.gif
and
soabp_header.jpg

Let me know if you are going, it would be great to meet you! 

July 31, 2006

HL7 ACK or NAK configuration

Filed under: BizTalk, HL7 — eric @ 11:47 pm
A recent post was asking how to set up a two-way port with an orchestration to create acknowledgements.
  • What we did is in the configuration tool, we set the properties for the MSH 3.1 to the following:
    mllp config
    so that the pipeline component will only auto generate a NAK in case of a bad message.
  • We did not want a CA generated stated that we got the message (with or without data errors), we just wanted to know if it was valid or not, hence MSH15=NE.
  • The MSH 16=ER, we only wanted it to create an NAK if there were errors.
  • Then in the orchestration we have a filter only looking for BTAHL7Schemas.ParseError==false (so only good HL7 messages trigger the orchestration).
  • Then in the orchestration we create our positive ACK (setting MSA 2 to AA) and send it back; completing our two-way port in the orchestration.
  • We also have a Dump send port that is filtered on BTAHL7Schemas.ParseError==true and the pipeline is set to DefaultPipelines.PassThruTransmit (since the HL7 DASM could not successfully parse it, it still resides in its text blob form), where the original HL7 message could be looked at futher for troubleshooting purposes and not have a suspended message in the message box.
  • We also promoted the MSA 2 and created a filter where we could capture the autogenerated NAK (MSA_2!=”AA”). This allowed us to look at both the bad message and a copy of the NAK that was sent back to the originating system.

This fulfills our requirements to send back an ack, but then the ack gets generated either by the pipeline component (NAK) or by our orchestration (ACK).

I want to thank my friends in Portugal for encouraging me to clarify this blog entry.
Next Page »