by community-syndication | Jul 30, 2004 | BizTalk Community Blogs via Syndication
A while ago, I blogged about pipeline components and what you need to pay attention to. Stephen, in reply to this, was wondering (see his comment) how tracking came into play. And… to be honest – I didn’t have a clue! Only recently I managed to get the answer.
It turns out that Stephen’s question actually was really valuable in helping me understand how exactly things work underneath… So, here’s my – somewhat delayed – response and comments to his question.
Assume that your pipeline component screws up and that tracking before the pipeline, is enabled. What happens?
- if the message’s body stream is seekable:
- if the message’s body stream is *not* seekable:
In both cases, the message ends up suspended. The body might be in the suspended message if the body stream was seekable, otherwise not. (You should always have the context.)
For example: in the case of HTTP, the stream will not be seekable and the body will not be tracked nor suspended in case of a fatal pipeline component failure. (Note: the client will not get an HTTP either!)
So, the only advise I can give is: *never* screw up in your pipeline component :-)))
by stephen-w-thomas | Jul 30, 2004 | Stephen's BizTalk and Integration Blog
This is a challenge to overcome in BizTalk 2004. It seems that the message never hits the Send Pipeline and as far as I can tell no error is written to HAT. The only place this error is written to is the Event Log. But this is ok if you are using MOM or something else to watch the event log.
The messages will be Suspended inside HAT and marked as resumable.
CRITICAL: Note that this is not the case if a map fails on the Receive Port. These messages are non-resumable.
by stephen-w-thomas | Jul 29, 2004 | Stephen's BizTalk and Integration Blog
Microsoft released a new version of the product documentation on July 28th.It is available for download at: http://go.microsoft.com/fwlink/?linkid=20616
by stephen-w-thomas | Jul 28, 2004 | Stephen's BizTalk and Integration Blog
I just wanted to take a second to get everyone on the same page since these properties are VERY important in BizTalk.
If you are a solo developer or you have never renamed a root node, then you may not understand the importance of these properties.First off, what are they?
Node Name: This is the name that is displayed inside Visual Studio for the root node in the schema and for each field element in a property schema.
Root Node Type Name: Basically, this is what BizTalk will call your root node. This does not have to be the same as the Node Name, thus the potential for confusion.
The root node will default to the same name as your root node name when you first create the node or when you rename the root node by changing the Node Name property. But, it is possible to change the Root Node Type Name, either by accident or on purpose, to something else that is non-meaningful to anyone.
Ok, but how will this really effect me? BizTalk sets a message context property called BTS.MessageType. This is a concatenation of the document namespace and Root Node Name. This message type property will show up in HAT and can also cause problems when working with non-unique root nodes with no namespace, but that is a whole other post.
What purpose does this serve? This will allow you to have two schemas with no namespace or the same namespace and the same root node name, but different root node type name. The benefits of this may not be obvious, but it will allow you to set the message type property inside the pipeline. This is required if you want to use the message for routing, mapping, or inside a strongly typed orchestration.
If you do have two messages with no or the same namespace and the same root node type name you may get the follow error at runtime:
There was a failure executing the receive pipeline: "Microsoft.BizTalk.DefaultPipelines.XMLReceive" Source: "XML disassembler" Receive Location: "d:\bt\in\*.xml" Reason: The disassembler cannot retrieve the document specification by using this type: "Root123". Either the schema is not deployed correctly, or more than one schema is deployed for the same message type.
The same holds true for schemas name and type name on the file properties of a schema. The schema name has a Type Name property that is used inside the BizTalk Type Picker to reference that schema. If this name gets changed on accident, it may become difficult for other developers to reference your schema.
CRITICAL: Unlike the Root Node, the file Type Name property will NOT change if the schema is renamed.
Take Away: Be mindful of the Type Name properties on the file and root node level and double check them to make sure they are set correctly.
by stephen-w-thomas | Jul 28, 2004 | Stephen's BizTalk and Integration Blog
Greeting and welcome to my BizTalk Blog.
I guess you might want to know a little about who is going to be writing this blog. Before working with BizTalk Server, I ran my own retail internet business selling toys and display cases on the net. Ok, that does not sound very exciting or technical but I did all the web site development along with all the order packing, phone answering, receiving, etc. Oh, I guess I should back up a little more and should mention that before that I was working for International Paper in a paper mill as a Process Engineer. I went to the University of Iowa and have a Chemical Engineering degree. And, No, we do not grow potatoes in Iowa.
I have been working with BizTalk Server since February 27th 2001. I remember that date well… since that was my first day in Seattle on a new project and the next day we were shaken up by the 6.8 earthquake. Who knew Seattle was on a fault line?I have spent over 2 years working with BizTalk 2000 and 2002. I have been working exclusively with BizTalk 2004 since I got my hands on the Beta in early July 2003. I started on first BizTalk 2004 project in August 2003 working (or trying to work with) the Beta.
Now, after RTM, I am working on my 3rd BizTalk project.What do I hope to achieve with my Blog? Good question. I hope to post simple solutions to common, complex problems. Like working with LARGE files (1GB+), using XPath and C# inside the mapper, custom pipelines, orchestration throttling, batching, de-batching, and the list goes on and on.
My approach is always consistent: Make it as simple as possible with little custom code!
by community-syndication | Jul 23, 2004 | BizTalk Community Blogs via Syndication
Okay, according to the stats, you guys stopped reading when I posted the convoy topic, but, well, I’ll keep throwing stuff at you and hope you enjoy it.
This is the first installment of the bizTalk pub/sub infrastructure talk. I have met lots of people who are confused about this (some of them are on my team). So the short answer is yes, BizTalk processing is built on top of a sql based pub/sub infrasctructure which you know as the messagebox. The longer answer involves explaining how you interact with it since BizTalk does not tout itself as a pub/sub product or really expose a lot of views into its pub/sub nature (except for the subscription viewer which is a good demonstration of why I am not a UI developer J ). I will attempt to give you a quick insight into pub/sub in BizTalk. Maybe one day I will take all this stuff I am writing, fancy it up and make it into chapters in a book or something, but given that I write code not prose, it’s doubtful.
There are really two components which together make the BizTalk pub/sub infrastructure. The database portion is known as the MessageBox. The other portion is what the engines internally use to interact with the MessageBox and is called the MessageAgent. This piece abstracts away all of the guts of the messagebox from the engines (things like multi-messagebox are understood by the agent, but the engines do not need to worry about it). This is probably a bit more than you needed. So in a pub/sub system, well, there are really three things you need to describe: publishers, subscribers, and events (or messages) which flow through the system.
Publishers. Who are the publishers in your BizTalk system? There are only really 3 publishers in a BizTalk system. Receive ports are publishers. They pick up data from somewhere based on the adapter and the URI, and then pass it through a pipeline and maybe a map and then eventually give it to the messageagent and say “Publish this for me, please.” (our engines are very polite and always say please). To clear up confusion, data is persisted to the messagebox after the pipeline and after the map, not before. (There is one exception to this involving MSMQt and large messages but you really don’t need to care about that) Send shapes in a schedule are publishers. They also give the message to the message agent and say “Please publish this for me. Thank you.” There are also a couple of other random points like the response portion of a solicit-response sendport. It does a publish. Also when an orchestration execs (not calls. Call is inline and synchronous) another orchestration, it publishes a message too. It is a bit confusing, I know because you are saying to yourself, “In my orchestration I bind my send action to a specific sendport. What do you mean it publish?”. I will get to that shortly.
Subscribers: Who are my subscribers? Orchestrations are subscribers. Any receive action in an orchestration maps to a subscription. The orchestration subscriptions are made up of the filter expression on the activate receives and the correlation sets on the subsequent receives (you can see them in your subscription viewer in the sdk\utilities directory). There are two types of subscriptions which I like to talk about … activation subscriptions and instance subscriptions (sometimes correlation subscriptions). Activation subscriptions start a new instance of a service. These are the subscriptions in your orchestration which you mark as Activate = true. Instance subscriptions, or correlation subscriptions, are subscriptions which route messages to already running instances. They are created after the orchestration instance starts once the necessary correlation sets have been initialized. It gets tricky with convoy semantics, but I don’t think I can really explain that in a quick blog like this. Let’s just say that I get tricky and in a parallel activation convoy, they’ve got a little activation and a little instance subscription in them. Send ports are subscribers. Send port subscriptions are always activation subscriptions. There is one exception to this and that is ordered delivery sendports. I’ll let you in on a secret. We do ordered delivery in sendports just like you try to build it in your schedules. We use a convoy. So MSMQt sendports are inherently on a convoy, so they are that weird blend. Other subscribers are the response portion of a request / response receive port. We use some internal correlation sets to make sure that the response gets back to the correct nt service for things like HTTP so that we can send the response on the open connection. Another example of a subscriber is when you do delivery notification. We actually create an internal subscription for the notification and use an internal correlation set to get it back to the correct orchestration instance. Hmmmmmm. What else. Oh yeah. About the confusion over direct binding to a sendport. All sendports subscribe to messages sent directly to them (you can see this in the subscription viewer) based upon a property called their TransportId which is an internal bts property. This way we can force send messages from the orchestration to the sendport. That’s the basics of it.
Events: Events or messages are just your messages. The MessageBox and MessageAgent do not care at all about what is in your message. We never look at the contents. To us, it is an opaque blob. We care only about the structure of it … how many parts and what there names are … and the properties associated with the message in its context. There are two basic types of properties on the context: written properties and promoted properties. They are both streamed out to the database when the context is persisted. The only difference is that promoted properties are used to route on. If someone subscribes to “foo = 3” and you promote foo with a value of 3 then your message will go to the subscriber. Anyone can promote anything (almost) at anytime as long as the property is defined in a property schema. If it is not defined in a property schema, you will get an error when you try to promote it. One thing many people don’t know is that the routing layer supports multi-valued properties (ie VT_ARRAY | VT_??), Our native components won’t promote anything like this, but you can do it in a custom pipeline component. You cannot reference these properties from within a schedule because orchestrations do not support multi-valued properties, but if you just want to route it there, and you have repeating elements, this could work for you.
There is really only one big gotcha in the routing layer that you have to avoid. Do not create a lot of sendports subscribing to the exact same thing without using a Distribution List (SendPort Group). If you create 100 sendports and all of them subscribe to A=5 & B=4 your performance will be worse than if you were to create one sendport group with that filter expression and then add all of the sendports to it. This is very important. If you do it the bad way, you will see some performance degradation and increased CPU utilization on your master messagebox for routing. Just giving you a heads up. It probably won’t happen till you have a whole lot, but it is just not a good practice to get into. Basically if you have more than say 8 sendports subscribing to the exact same thing, use a sendport group.
Hope this has given you a bit of insight. Apparently there are people out there reading this. Sorry it is not all official and beautiful, but, well, hopefully it is something.
Lee
by community-syndication | Jul 22, 2004 | BizTalk Community Blogs via Syndication
Here’s another blog from the Biztalk product group that is well worth keeping an eye on, Eldar is a Program Manager for the Biztalk engine team, so I’m sure we’ll be seeing some great blogs from him.
by community-syndication | Jul 12, 2004 | BizTalk Community Blogs via Syndication
CONVOYS
From the BizTalk Documentation:
When a group of correlated messages could potentially be received at the same time, a race condition could occur in which a correlation set in a particular orchestration instance must be initialized by one of the messages before the other messages can be correlated to that orchestration instance. To ensure that all of the correlated messages will be received by the same orchestration instance, BizTalk detects the potential for such a race condition and treats these messages as a convoy.
Since I helped proofread the docs (and write this paragraph), I figure I can cut and paste some of them. I spent a while at teched talking to my friend Marty about convoys and what they really are so lets see if we can get this message broadcast out there. Convoy processing is not a feature of BizTalk which you should be looking at and saying, “hmmmmm. I wonder how I can use this convoy thing.” A convoy is “something we support”. Convoy is a term which we use to describe a class of application protocols, specifically it is a set of application protocols which have a race condition as described above. Let’s take an example. Say you are a hospital and want to have a service which handles all information about each patient. For a given patient you have three types of messages, an admittance message, status messages, and a discharge message. If you look at your protocol, you will have built a service which just receives. Now let’s think about what could happen. Let’s say you send the patient admittance message and it goes through the system using maybe a synchronous protocol like HTTP. That means when you get the 202 back, you know the message has been delivered. But what if the BizTalkServer host which is actually supposed to process the message hasn’t started yet (ie the nt service is stopped). Maybe you had a power outage, maybe some intern decided to “hit this button”, who knows. So the orchestration instance which is supposed to handle all messages for patient X has not physically started. The message is in the database (MessageBox) and if you look in HAT you will see the orchestration is marked as ready to run, but it can’t start cause there is no where for it to start. Now lets say you send a patient update. Let’s think about what BizTalk could be doing (okay actually is doing) to support general correlation. So when a message initializes a correlation set, the service instance which the message is delivered to has the responsibility of communicating to the underlying pub/sub system (the MessageBox) that it is now expecting subsequent messages which will follow the same correlation set (based upon what other receive actions you have with follow the same correlation set). In a simple conversation style protocol (ie, you say “Hi”, I respond by saying “Howz it goin’”, and then you start talking), I can create all required subscriptions for subsequent messages when I do the next send which follows that correlation set. The protocol indicates that the original sender will not send any more messages until he gets the response back from me acknowledging the start of our conversation. There is no race. I transactionally create the subscriptions at the same time as sending the next message which acknowledges our conversation so you can’t possibly send a message which I am not ready for. Again, there is no race here. Now lets look back at my original convoy scenario. As you can see, the service instance which will handle all data for that patient does not communicate back to the sender. Heck, it might not even really know who the sender is. So there is this race, since you cannot depend on the service instance to be created and have a chance to turn around and create the subscription before subsequent messages are sent. *We solve this*. When you think of convoys, I want you to not think of BizTalk features, but rather think of your application / business protocols and say, “Hey that’s a convoy. That’s alright though, BizTalk will detect it and handle it and it will just work.” Convoy is not something you try to use, it is something you just end up using because that is how your business works and we support it. To give you a bit of insight, what happens is that our compiler will detect this race condition and communicate it down to the messagebox at enlistment time. Normally enlistment just creates the activation subscriptions (subscriptions which start the new instances), but in this case it will actually create some sort-of templated subscriptions and link them together around this convoy set. Hence, when the first message comes in, the data which coincides with the convoy set is pulled and we essentially complete the templated subscriptions so that any subsequent messages which match those subscriptions and have the same convoy set properties will go to the newly created instance, even if it hasn’t started yet.
So what is the real difference between a parallel and sequential convoy? Okay, well there are a number of restrictions imposed by the orchestration runtime which basically require your protocol to make sense, but if you want to know the real guts of it, all it really is is telling the pub/sub infrastructure which of these templated subscriptions can initialize the convoy and which require it to already be filled. So if you think about, when the first message comes to the activation subscription, it has to fill out the convoy set for its specific data. Then subsequent messages which match other subscriptions will find there data already filled and so go to the right place. Somehow the pub/sub layer needs to know which of the templated subscriptions can actually initialize the convoy set based on the message values and which of the subscriptions simply requires the values to have already been filled. So for a parallel convoy, any subscription can activate the convoy. For a sequential convoy, only the first receive action can activate the convoy. If a message comes for the second receive before the first, it will fail routing. Again, this is just a feature of your business protocol. If you know what order the messages are required to come in, then you can have a sequential convoy. If the messages can come in any order, you might have a parallel convoy. It is really that simple.
Sorry this isn’t the most well formatted blog, but I felt like I have been slacking (okay I have been slacking) and wanted to get you some more stuff to fill your head with. In my defense, I decided two and ½ weeks ago to do an Olympic distance triathlon and so had to try and pack training into 1 ½ weeks (especially after rolling my ankle last Monday. For those of you concerned, I finished and did pretty well for a guy who only trained for a week and a half (www.racecenter.com/hagglake).
Adendum to my last posting on zombies. I looked into it and discussed it with a coworker of mine and I was wrong about the “virtual zombies”. The orchestration engine does some trickery and ends up causing me to create full-fledged zombies, so if a schedule is going to complete in the “Completed with discarded messages” state, the zombie wmi event will always be thrown. Sorry for the brief bit of confusion around that.
Possible topics for next time, more convoys, when to use mappings, or my favorite, a discussion on the rising cost of rotisserie chicken in the cafeteria. Perhaps a tournament challenge to guess the price each week with winner getting the question of his/her choice answered (I am not a disgruntled employee, I can handle 25 cents, it is just a running joke between myself and some co-workers).
Thanks
Lee
Further reading: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sdk/htm/ebiz_prog_orch_iljk.asp
by community-syndication | Jul 7, 2004 | BizTalk Community Blogs via Syndication
There are several QFEs for BizTalk 2004 that you may want to know about, in case you
encounter the situations described below.
Situation: You attempt to create or edit Receive or Send ports within
the BizTalk Explorer in Visual Studio, and CPU consumption hits 100%. Memory
consumption climbs until the IDE crashes with an OutOfMemoryException.
Fix: Ask PSS for the hotfix associated with KB870619 (also known
as hotfix 1185)
Situation: You have a CDATA section in an inbound xml document within
an orchestration. The CDATA section contains flat file data, with vital trailing
(or leading) whitespace. After you execute a transform in your orchestration,
the CDATA designation is stripped (although the flat data is still there) – and the
leading/trailing whitespace is now lost. Curiously, using the “Test Map” feature
(by right-clicking on a map in the solution explorer) doesn’t exhibit this behavior.
Fix: Ask PSS for the hotfix associated with KB841563
Situation: You have a scope shape, and scope timeouts aren’t working
as expected. Specifically, for blocking calls in an expression shape within
the scope (like a DCOM call, etc.) where the timeout is being exceeded, you see 100%
CPU consumption in the BizTalk service and the orchestration never terminates.
Fix: Ask PSS for the hotfix associated with KB811250. (Note:
this problem may have been addressed in the fix rollup released in April – I’m not
sure what the ordering was here.)
by community-syndication | Jul 3, 2004 | BizTalk Community Blogs via Syndication
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.