•  

    Blog

    17


    sep

    Send Port Group and Delivery Notifications

    I was recently asked to assist one of our customers with a problem they were experiencing with one of their BizTalk interfaces. They had created an orchestration that was sending a message using a logical port set to “Specify Later”, which was bound to a physical Send Port Group containing multiple Send Ports.

     

    The error message I was faced with was: “The instance completed without consuming all of its messages. The instance and its unconsumed messages have been suspended.”

     

    After checking the orchestration I quickly found the cause of the error: The Delivery Notification setting of the logical port in the orchestration had been set to “Transmitted”. This meant that after sending the message, the orchestration expects exactly one (N)ACK message back to determine whether the message had been received successfully. Because a Send Port Group with multiple Send Ports was being used, multiple (N)ACK message were being received (one for each Send Port) while only a single (N)ACK was expected by BizTalk. Since, after the first message is received, there are no instances/subscribers remaining for the other incoming (N)ACK responses, this resulted in zombie messages.

     

    Obviously the first thing I tried was searching for a solution online, hoping that someone had already solved this problem. After coming across a discussion that said that this was impossible I just had to see for myself.

     

    One of the ways to approach this issue would be by simply using multiple send shapes in the orchestration and stop using the Send Port Group all together. In this case this was not an option however, since one of the requirements for this interface was that it should be very easy to add and remove locations where the file would be send to, as destinations for the file change regularly. The administrators in charge of maintaining the interface preferred to keep using the Send Port Group instead of having to change and redeploy the orchestration for every new Send Port. At the same time, receiving the delivery notification for each outgoing message was also a key requirement.

     

    So I had to come up with an approach in which I would cover all requirements, which basically meant that I had to keep using the Send Port Group. This meant that I could not use the out-of-the box Delivery Notification setting on the logical port in the orchestration, so we had to recreate this functionality. Fortunately this specific part had been done before and is described in this excellent blogpost by Bruno Câmara: http://www.agilior.pt/blogs/bruno.camara/archive/2008/04/17/4344.aspx.

    In short, this is done by setting the promoted property BTS.AckRequired on the outgoing message to true, initializing the BTS.CorrelationToken to new guid and creating receive shapes for the (N)ACK message. By using correlation sets for these promoted properties the (N)ACK message is received in the orchestration. After receiving the (N)ACK message in the orchestration we can check if it’s an ACK or NACK message and handle it accordingly.

     

    However, simply recreating the Delivery Notification functionality would not be enough; we had to make sure the orchestration would receive every Delivery Notification message. To do this I used the Delivery Notification functionality in a loop. I created a function to retrieve the number of Send Ports currently present and bound in the Send Port Group using WMI to determine the amount of iterations for the loop.

     

    The final solution in the orchestration ended up looking like this:

    blogpim_sendportgroups_1

    The orchestration sends the Output message, which is then picked up by the Send Port Group and sent to any number of locations. The orchestration uses a custom function to determine the number of Send Ports in the Send Port Group and uses this as a parameter in the Loop expression. In the Loop the Delivery Notification messages are received, if a NACK message is received the error message is logged.

     

    After running the interface, the Tracked Message Events for the orchestration now show that multiple Delivery Notifications have been received:

    blogpim_sendportgroups_2

    By using this solution we only had to modify and redeploy the interface once, leaving the administrators with the ability to add and remove Send Ports to and from the Send Port Group without the need to go into Visual Studio and deploying a new version of the orchestration, all while avoiding zombie messages!

     

    And finally, here is the code used to retrieve the number of Send Ports in a Send Port Group:

    }
    public static int GetNumberOfSendPortsInSendPortGroup(string spgName)
    
    {
    int numberOfSendPorts = 0;
    
    BtsCatalogExplorer root = new BtsCatalogExplorer();
    root.ConnectionString = "Integrated Security=SSPI;database=BizTalkMgmtDb;server=.";
    
    foreach (SendPortGroup sendPortGroup in root.SendPortGroups)
    {
    if (sendPortGroup.Name == spgName)
    {
    foreach (SendPort sendPort in sendPortGroup.SendPorts)
    {
    if (sendPort.Status == PortStatus.Started || sendPort.Status == PortStatus.Stopped)
    {
    numberOfSendPorts = numberOfSendPorts + 1;
    }
    }
    
    break;
    
    }
    }
    
    return numberOfSendPorts;
    

    17 september 2015