Friday, November 2, 2007

BizTalk Delivery Notification

I have recently had some requirements that required me to use the BizTalk Delivery Notification feature of Send Ports. In case you didn't know, Delivery Notification "Gets or sets the field to request that the adapter will send delivery notification back, whether transmission is successful. " source

Basically, what I am trying to do is ensure that my message is sent to it's destination prior to the rest of the orchestration executing. If the message is not sent successfully, I want the orchestration to stop processing so that an "Ops guy" can take a look into the situation without losing the message.

My Requirements

I need to deliver a file to a Unix system where it will be consumed by our ERP system. Since some of the files may be large, it may take seconds or even minutes for the file to be completely written. Our ERP system essentially needs to know when it is "safe" to consume the the file. Once the data file, from here on in I will refer to it as the "work" file as it needs to be delivered to a "work" folder, is written a "signal" file is to be written to the "sig" folder. This is the ERP's trigger to pick up the work file. When writing the sig file, we use the same name as the work file, except we append ".sig" onto the end. This way the ERP knows which file to pick up in the work folder.


So what I need to do is ensure that the "work" file has been successfully written before the "sig" file. Otherwise our ERP may go looking for a "work" file that does not exist.

Solution

I have created a POC to demonstrate how to utilize Delivery Notification. For this sample I am using local file drops, but I have tested this with an FTP adapter as well.


So here is my orchestration. I have a standard receive shape followed by a Scope shape that has Transaction = None, Synchronized=True. To find out more info on Scope shapes click here






Inside of this scope, I have a log point and Send Shape that is connected to a Logical Send port. Within the Send Port, I have specified the "Delivery Notification" = Transmitted.



I have added an Exception handler to the scope shape that is configured to catch Microsoft.XLANGs.BaseTypes.DeliveryFailureException exceptions. When you enable Delivery Notification the orchestration will wait for an ACK/NACK to be returned when the message is sent. If an ACK is returned, the orchestration will complete the scope shape and continue processing. If a NACK is sent back from the engine then the orchestration will raise a Microsoft.XLANGs.BaseTypes.DeliveryFailureException which is why we need to catch this type of exception.


I have added a Suspend Orchestration shape to ensure that I can resume this orchestration instance in the event of a failure.

Outside the scope shape, I have another log point and I construct my sig file. There is not much to the sig file. It basically contains a timestamp. I do not have Delivery Notification enable for this logical send port as I will just rely upon the messaging engine's "default" capabilities for writing this file.


Testing

Under normal circumstances, the sample runs as expected. A file is picked up from the receive location where BizTalk tries to write the work file to the work folder and the sig file to the sig folder.

In the event that the work folder does not exist or the work file already exists, the sig file will not be written. In this test run, I have left a copy of the same file in the work folder. When the orchestration executes, I find 2 suspended instances in my BizTalk Admin Console. Note that for this test I have my Send port's Retry Count and Retry Interval set to 0 just to speed up the testing process. You can alter these values and the behaviour remains the same; the work file will be retried as many times as configured before it gets to this state.


At this point, in my production environment, I would receive a MOM Alert as BizTalk has logged an error in the Event Viewer. This would allow for some investigation into the problem. In my sample scenario I just remove the original file from this folder and am free to resume the Suspended Message Instance. Once resumed, the work file is written as it should be. In order to get the sig file written, I must now resume the Orchestration instance. Upon resuming this instance, the sig file is written to disk.


The order of these two steps is critical. If you resume the orchestration instance prior to the message instance, the sig file would be written prior to the work file. This is the scenario that we are trying to avoid by using Delivery Notification so it is important for operations staff to understand this concept.

Also be cautious about the potential performance impacts of enabling Delivery Notification. For more information related to performance, please check out Kevin Smith's blog

12 comments:

goodboy said...

Hi Kent,
Great post. I have one question regarding this. I am using a send port Group to send the same output file to multiple location something like archiving the output file.
And also one send port is marked with Order Delivery(not the archive port). So whats happening, if any error occurs in the port marked with Order Delivery, I get proper ACK back in Orchestration, but if any error occurs on the other port then there is no response returned back to Orchestration. I am using both DeliveryFaliureException and General Exception. I am not sure where I am getting wrong or I believe NACK does not work in case of Send Port Group. Please let me know if you got into this scenario or find anything. You can also mail me at ajk86in@gmail.com.
Thanks in advance.

Kent Weare said...

Hi Goodboy,

Yes, you are right using a send port group with Delivery notification will not work. I modified the solution that I used in this post and the orchestration continued on even though one of the send ports contained a non existent URI.

If I understand your scenario, BizTalk is behaving as it should. If you have a send port marked with DeliveryNotification = Transmitted then your orchestration will hault whenever an error is encountered with that port.

For another port that does not have delivery notification set, the outbound message will be sent to the messagebox, where it will be picked up by a send port subscription. This event is occuring independant of the orchestration. The orchestration will continue to process since it is not waiting for an Ack from the messaging engine.

There is nothing from stopping you from creating another port that also has delivery notification. What you are telling the orchestration is that event 'A' must be successful, before event 'B' is initiated. Once event 'B' is successful then the rest of the orchestration can be processed.

I hope I understand your scenario correctly. If you have further questions, let me know.

Kent

Ram Kinkar Pandey said...

Hey Kent,
If your solution is also applicable with a WCF Adapter?
I am making a WCF call to a one-way operation(operation is void) but that can throw any exception. If any exception is throws from other end then if this solution can handle mentioned scenario?
My basic motive is to distinguish between a delivery failure(service was no up, IIS was down) and a delivery rejection(service threw an exception).

So i was wondering that if this solution is also applicable in my scenario.

Kent Weare said...

Hi Ram,

I have not tested Delivery Notification with one way WCF calls but I can't see why it wouldn't work. Delivery Notification involves the adapter notifying the messaging engine when an operation succeeds or fails.

Delivery Notification would not be used to receive exceptions that the service has returned. Delivery Notification is more appropriate for determining whether IIS is online and able to process your request message.

Gopakumar said...

Hi Kent,
In the case if the target location doesnt exist, the send port (with delivery notification = transmitted) fails, and the message instance gets suspended. Is there any way to "kill" or terminate this suspended instance (of message, not orchestration) programatically?

Thanks,
GK

Kent Weare said...

GK,

Have you looked into failed message routing? Stephen Thomas has a sample that deals with both a receive and send port failures.

http://geekswithblogs.net/sthomas/archive/2005/08/02/48962.aspx

Hari said...

Hi Kent,
Iam trying the handle the error in a sQL adapter.Iam doing a delete operation in a SQL database.If teh delete fails I want to terminate the orchestration.Can delivery notification be used for this? or what is the best way to handle the scenario.
Thanks

Kent Weare said...

Hari,

I have not tried to use Delivery Notification with WCF-SQL, but I can't see why it couldn't be used.

Regarding the delete operation, the Delivery Notification is used to detect communication failures. So if you can connect to SQL Server, but there is an internal error within the SQL statement or stored proc then I am not so sure this would work. When you set up your scope exception handler, you need to specify a DeliveryFailureException as the exception type. If the messaging engine detects this exception type you are covered, if not then this method won't work.

Ken Luo said...

Hi Kent,

I'm doing testing with this option recently to understand how it works in different binding, one-way and two-way ports.

What i found is that in a two-way port type, no matter whether this option is set to none or transmitted, orchestration always works like "transmitted".

Kent Weare said...

Hi Ken

This is due to the nature of synchronous messaging. Meaning that your orchestration will not perform any further actions until it gets a response back from the system you are trying to call.

Kent

dhare said...

Hi Kent,

We also have the same requirement to get the Delivery Notification. I used a similar method as this post to suspend the orchestration and the port. But when I try to resume the send port it sent the file but send port remains suspended with a new service name with - "Routing Failure Report for """. I'm using BizTalk 2010. Appreciate if you can help on this issue. Thanks and Regards

Kent Weare said...

hi Dhare,

Sounds like something isn't configured quite right. When you get a routing error report it means that the waiting subscription no longer exists. Has the orchestration disappeared?

Kent