biztalkbiztalk-2010hl7btahl7

BizTalk 2010 - Create acknowledgements


Information:

The incomming message is of type HL7. I'm using in the receive pipeline the "Flafile-Disassembler" and not the "BTAHL7 2.x Disassembler" pipeline component, because the HL7-Schema has is a bit modified and the BTAHl7 disassembler split the message (multipart messages) and we don't want; And we don't want to use orchestration.

Questions:

How can I create acknowledgements in a receive pipeline in BizTalk 2010, without using "BTAHL7 Disassembler" (without spliting --> multipart messages approach)?

Or, it's possible to prevent splitting the message in the BTAHL7 Disassembler pipeline component?

a positive ACK would be enough.

Thanks.


Solution

  • As @boatseller says, you cannot prevent the HL7 Disassembler from creating multi-part messages.

    For your other question: you can create a custom pipeline component to send back the HL7 acknowledgement, and then just use your own flat file schema (with the out-of-the-box flat file disassembler pipeline component).

    1. Use a two-way receive port.

    This should work using a two-way port, even with the MLLP adapter, but you need to validate and test everything and understand that Microsoft may or may not support using the MLLP adapter without the HL7 2.X disassembler pipeline or using BizTalk in the manner suggested below.

    2. Correlate the request and response.

    You'll need a custom pipeline component in the receive location's pipeline to make BizTalk create a subscription for the response. Use the Pipeline Component Wizard to get a head start creating the component.

    In the Execute method of your custom pipeline component class (which you get from implementing the IComponent interface), write something akin to the below code.

    public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(Microsoft.BizTalk.Component.Interop.IPipelineContext pc, Microsoft.BizTalk.Message.Interop.IBaseMessage inmsg)
    {
        const string sysPropertyNamespace = "http://schemas.microsoft.com/BizTalk/2003/system-properties";
        var epmToken = inmsg.Context.Read("EpmRRCorrelationToken", sysPropertyNamespace);
        var correlationToken = epmToken != null
                                        ? (string) epmToken
                                        : Guid.NewGuid().ToString();
        inmsg.Context.Promote("EpmRRCorrelationToken", sysPropertyNamespace, correlationToken);
        inmsg.Context.Promote("RouteDirectToTP", sysPropertyNamespace, true);
        return inmsg;
    }
    

    The use or the EpmRRCorrelationToken and RouteDirectToTP properties for request-response message processing without an orchestration is documented in this MSDN blog post.

    3. Create and Send the Acknowledgement

    You can use another custom pipeline component inside your send pipeline to manually create the acknowledgement based upon the input message, perhaps with some additional pipeline component configuration that is read at runtime.

    Like the first custom pipeline component, you can implement the IComponent interface's Execute method. Code like this should work:

    public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(Microsoft.BizTalk.Component.Interop.IPipelineContext pc, Microsoft.BizTalk.Message.Interop.IBaseMessage inmsg)
    {
        string msgOut;
        var bodyPart = inmsg.BodyPart;
        if (bodyPart == null) 
            return inmsg; // Maybe throw an exception instead?
        var inboundStream = new ReadOnlySeekableStream(bodyPart.GetOriginalDataStream());
        inboundStream.Position = 0;
    
        using (var reader = new StreamReader(inboundStream))
        {
            var builder = new StringBuilder();
            // Read the input stream's first line - this should be the MSH segment:
            var firstLine = reader.ReadLine();
            // TODO: read search/replacement values from pipeline configuration
            // TODO: make a better ACK header than this
            builder.AppendLine(firstLine.Replace("ADT^A01", "ACK")); 
            // Construct your acknowledgement segment, preferably without hardcoding it here:
            builder.AppendLine("MSA|AA|ADT^A01");
            msgOut = builder.ToString();
        }
    
        // Write out the output
        var outputStream = new VirtualStream();
        var writer = new StreamWriter(outputStream, Encoding.Default);
        writer.Write(msgOut);
        writer.Flush();
        outputStream.Seek(0, SeekOrigin.Begin);
    
        inmsg.BodyPart.Data = outputStream;
    
        pc.ResourceTracker.AddResource(inboundStream);
        pc.ResourceTracker.AddResource(outputStream);
    
        return inmsg;
    }
    

    Other than handling the inline TODOs and adding in more null checking, that should be a fairly complete solution, though your mileage may vary, especially when it comes to returning a valid HL7 acknowledgement message.

    Bonus. Why not use an orchestration?

    This was asked in a comment to the question, and here are a few reasons for using custom pipeline components instead of an orchestration:

    1. Orchestrations are slow. Microsoft, in their own Optimizing Orchestration Performance article, says that you should avoid using orchestrations when possible. Orchestrations increase latency and response times because they require extra roundtrips to the BizTalk MessageBox database and additional processes and threads be spun up on the BizTalk server.
    2. Acknowledgments return faster. HL7 integrations typically use accept/receipt acknowledgements. Many systems will not send additional messages until the last-sent message is acknowledged. So if you have to wait for an orchestration to spin up, read the input, construct the ACK output, return the ACK to the port, and then send the ACK back, you will greatly slowdown processing. Yes, this is similar to #1, above, but it is important to understand.
    3. Orchestrations make your solution more failure-prone. An orchestration is another point of failure. If you have to take your ACK-producing orchestration or its associated host instance(s) offline, then you have lost your ability to receive messages. A great benefit to BizTalk is its ability to isolate the different parts of an integration solution, enabling high availability and increased reliability. When your decoupled receive port's pipeline components return the acknowledgement after simply publishing the inbound message to the BizTalk message box, your receipt of messages can continue, even when your internal systems/components are down.