Sei sulla pagina 1di 4

Acknowledgments and Negative

Acknowledgments (Part 1)
The Biztalk engine has the notion of publishing system level (positive)
Acknowledgments (ACK’s) which indicate a successful message transmission and
Negative Acknowledgments (NACK’s) which indicate the suspension of a message;
these are extremely powerful and can be used for handling the outcomes of
asynchronous operations in the engine. For example, consider the scenario whereby
an Orchestration transmits a one-way message over HTTP, the Orchestration will
publish the message to the Message Box which will route it to the appropriate send
port. The transmission of the message is completely decoupled from the
Orchestration publishing to the Message Box, so the Orchestration has no notion of
whether the transmission actually succeeded or not, instead the Orchestration only
knows whether the message was successfully published to o the Message Box.
Perhaps the back end web server was down which caused the message to be
suspended by the Biztalk engine. The Orchestration would have no way to determine
the message was never delivered without some higher level message exchange in
the form of a business Acknowledgment. Enter ACK’s and NACK’s.

If an Orchestration port is marked with Delivery Notification = Transmitted, and


the Send shape in the Orchestration is in a synchronized scope, the Orchestration will
wait until it either receives an ACK or a NACK for the message that was transmitted.
In the case that the message was successfully transmitted, the engine will publish an
ACK ensuring that it is routed back to that Orchestration instance, once the
Orchestration receives the ACK it will leave the scope and continue processing. If
however the transmission failed and the message was suspended, the engine will
publish a NACK which again will be routed back to the Orchestration instance, the
Orchestration will throw a DeliveryFailureException which can of course be caught
and handled as appropriate in the Orchestration.

ACK’s are published when the Messaging Engine successfully transmits a message
over the ‘wire’ and the system context property “AckRequired” is written on the
message that was sent and it is set to true. Providing the port in the Orchestration is
mark as above the context property is automatically written by the engine so thee is
no need to worry about setting it. NACK’s are published when ever the engine
suspends a message. Both ACK’s and NACK’s have the following system context
properties promoted which can therefore be used in filter expressions for routing:

AckType: set to ACK or NACK


AckID: set to the message ID of the message that this ACK/NACK is for
AckOwnerID: set to the instance ID that this ACK/NACK is for
CorrelationToken: flowed from the message to the ACK/NACK
AckSendPortName: the name of the send port that this message was being sent
over
AckOutboundTransportLocation: the outbound url that this message was being
sent over
AckReceivePortName: the name of the receive port that the message was received
over
AckInboundTransportLocation: the inbound url that the message was received
over
In addition all of the message context properties from the message that is being
ACK’d / NACK’d are demoted (i.e. if they were previously promoted they will not be
promoted on the ACK/NACK) and flowed and from the message to the ACK/NACK.
ACK messages do not have any message parts, but of course the message context
has a lot of important meta-data. NACK’s on the other hand as well as having all the
useful meta-data in the form of context properties, have a message body part the
content of which is a SOAP Fault, the format the SOAP Fault can be seen below, it
should be noted that the exception message from the exception that the adapter
raised is in the SOAP Detail section in the ErrorDescription element:

<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP:Body>
<SOAP:Fault>
<faultcode>Microsoft BizTalk Server Negative
Acknowledgment</faultcode>
<faultstring>An error occurred while processing the
message, refer to the details section for more
information</faultstring>

<faultactor>C:\Foo\DeliveryNotification\out\%MessageID%.xml</faultactor
>
<detail>
<ns0:NACK Type="NACK"
xmlns:ns0="http://schema.microsoft.com/BizTalk/2003/NACKMessage.xsd">
<NAckID>{BD6682EE-1741-4856-8CC7-
B2EE36B7874E}</NAckID>
<ErrorCode>0xc0c01c10</ErrorCode>
<ErrorCategory>0</ErrorCategory>
<ErrorDescription>The FILE send adapter cannot
open file C:\Foo\DeliveryNotification\out\{505A3211-9081-4720-827B-
A0DE2BD124FD}.xml for writing.</ErrorDescription>
</ns0:NACK>
</detail>
</SOAP:Fault>
</SOAP:Body>
</SOAP:Envelope>

In the case of an Orchestration port marked as delivery notification required, the


DeliveryFailureException that is thrown on a transmission failure is deserialized from
the SOAP Fault that is contained within the NACK message body, this is of course
transparent to the Orchestration. The Orchestration may get at the exception
message string that was thrown by the adapter by casting the
DeliveryFailureException to a SoapException and then accessing the InnerXml from
the SOAP Detail section, this is shown below:

// Cast the DeliveryFailureException to a SoapException…


System.Web.Services.Protocols.SoapException se =
(System.Web.Services.Protocols.SoapException)e.InnerException;
System.Diagnostics.Trace.WriteLine(se.Detail.InnerXml);
Returns the following Xml fragment…
<ns0:NACK Type="NACK"
xmlns:ns0="http://schema.microsoft.com/BizTalk/2003/NACKMessage.xsd">
<NAckID>{BD6682EE-1741-4856-8CC7-B2EE36B7874E}</NAckID>
<ErrorCode>0xc0c01c10</ErrorCode>
<ErrorCategory>0</ErrorCategory>
<ErrorDescription>The FILE send adapter cannot open file
C:\Foo\DeliveryNotification\out\{505A3211-9081-4720-827B-
A0DE2BD124FD}.xml for writing. </ErrorDescription>
</ns0:NACK>

The publication of ACK’s/NACK’s is a little bit special in that if there are no active
subscriptions for them, the ACK/NACK will be discarded. The ACK/NACK is published
atomically with the appropriate message, for example, the suspension of a message
and the publication of its NACK are in the same transaction within the engine,
similarly the publication of an ACK is performed in the same transaction as the
deletion of the message from the application queue. Further the engine does not
suspend ACK’s/NACK’s.

If the processing of a request-response message exchange pair fails after the receive
adapter has successfully submitted the request message and the message is
subsequently suspended, a NACK will be routed back to the waiting two-way receive
adapter, the receive adapter may then transmit the fault message back to the client.
Of course this means that the client would receive a SOAP Fault, what if the client
doesn’t understand SOAP Faults? For these scenarios the SOAP Fault maybe mapped
changing the format to one that the client is expecting and can handle. Also, once
the initial request message is accepted, a processing failure anywhere in the engine
resulting in the message being suspended will result in the NACK being routed back
to the adapter as its response.

By now you are hopefully starting to appreciate the power of ACK’s and NACK’s,
aside from the Orchestration delivery notification and the request-response scenarios
above there are many scenarios where they are extremely useful. For example,
suppose we have a scenario whereby we use a specific send port to transmit PO’s
over a million dollars while all other PO’s are transmitted using a different send port.
We could use a filter expression on a send port to route any NACK’s published for
messages that are suspended whilst being transmitted on that send port which could
subsequently be processed by some backend system.

Alternatively, an Orchestration with a direct binding to the Message Box could be


built to receive all NACK’s and subsequently perform some processing to handle the
failure based on where the failure happened. Which brings me nicely to Part 2! In
Part 2 I’ll describe how such a generic NACK Handler Orchestration may be built
which could be used to handle suspended messages, for example moving those
messages from the Biztalk applications suspended queue to some out of band
application that could handle those failures, along with a sample NACK Handler I'm
currently developing, so stay tuned for Part 2 in the near future.
BizTalk 2004 Delivery Notification and NACK Sample
Posted on Monday, August 02, 2004 10:23 PM
Did anyone else read Kevin Smith’s blog on ACK/NACK and run out to try it? Well, I sure did and found it
a little more time consuming then I expected. I have put together a sample that shows how to catch the
SOAP exception and get access to the error message. I hope that after looking at this sample Kevin’s
excellent post on NACK’s will make a little more sense. It did for me.

DOWNLOAD: Get the sample here!

Set-up is easy, just unzip the SampleNACK folder and put it on your C: drive. Then, build and deploy the
SampleNACK project. You will need to manually create a Send Port. I set up a File Send Port going to
c:\some_location_that_does_not_exist. Set retries to 0. To run it, drop the StartFile.xml message into
c:\SampleNACK\In. Your NACK will show up in c:\SampleNACK\Out. Do not forget to look inside the
expressions shapes inside the Orchestration for comments. If all else fails, read the ReadMe.txt file.

CRITICAL: Getting at the HTTP error using Delivery Notification will not work for transport type of HTTP or
SOAP due to an “issue”. For more information please see Microsoft KB840008.

Key Take Home Points:

- Delivery Notification is not available on Early Bound Ports.

- Must import System.Web.Services to cast the SOAP exception

- Set Send Port retries to 0

- Must use a Synchronized scope

Under the covers:

Ok, so you ask what is BizTalk doing inside the little Delivery Notification property? Keep in mind this is my
interpretation.

When a message is sent through a send port with Delivery Notification set to transmitted, a correlation set
is initialized. A correlation token is assigned to the outbound message. A subscription is started based on
this correlation token. This token is stored in the context property of the ACK/NACK and promoted. When
the ACK/NACK is returned, it is routed back to the calling Orchestration. You get all this just by setting a
little property to “Transmitted”! Cool!

Take Away: Delivery Notification is an easy way to catch exceptions as long as you understand how to get
at the error message.

Potrebbero piacerti anche