Handling of Exceptions in One Way Web Services in BizTalk

Monday, September 26, 2011
post by Richard Seroter
I’m currently working on the design of the “fan out” process from our ERP system (SAP) and we’ve had lots of discussions around asynchronous services and exception handling.
The pattern we’ve started with is that BizTalk receives the message from SAP and fans it out using one-way send ports (and web services) to each interested subscriber. However, some folks have expressed concern about how exceptions within the various services get handled. In a true one-way architecture, BizTalk is never alerted that the service failed, and the service owner is responsible for gracefully handling all exceptions.
If a .NET developer builds a very plain web service, their web method may be something like this:
[WebMethod]
public void DoSomethingCool(CoolObject co) {
   throw new Exception(“bad moon rising”);
}
So what does this actually generate? If you look, the actual contract generated from this yields a response message!
You can see there that the service caller would expect a confirmation message back. If BizTalk calls this service, even from a one-way send port, it will wait for this response message. For the service above that fails, BizTalk shows the following result:
The proper way (as opposed to the lazy way above) to build a one-way .NET web service is to add the attribute tag below.
[SoapDocumentMethod(OneWay = true)]
[WebMethod]
public void DoSomethingCool(CoolObject co) {
   throw new Exception(“bad moon rising”);
}
If you build THIS service, then the contract looks like this …
Notice that the only response BizTalk (or any caller) is expecting is a HTTP 200 response. If anything besides the base connection fails, BizTalk won’t know or care. If I call the service now, there is no indication (Event Log, Suspended Messages) that anything went wrong.
The first web service above is the equivalent of writing the web method as such …
[SoapDocumentMethod(OneWay = false)]
[WebMethod]
public void DoSomethingCool(CoolObject co) {
   throw new Exception(“bad moon rising”);
}
Setting OneWay=false would force this method to return a response message. So what does this response message REALLY look like? I traced the web service call, and indeed, you get a DoSomethingCoolResponse message that is apparently just eaten up by BizTalk (no need to subscribe to the response) …
Now what if the web service times out on these “fake” one way calls? Would BizTalk really raise an error, or would it simply say “ok, I sent it, never got a response, but that’s cool.” I added a 2 minute “sleep” to my service and tried it out. Sure enough, BizTalk DID suspend the message (or set it for retry, depending on your settings).
The only exception that will cause either a two-way OR one-way service to suspend is if the connection fails. If I shut down the web server, calling either type of service results in a suspended (or retry) message like so …
While it’s super that a service that returns no data can still return a basic success acknowledgement, there are broad implications that need to be thought out. Do you really want BizTalk to catch an exception thrown by your service? If the code is bad, all the retries are going to fail anyway. What about keeping messages in order? Do you really want to use “ordered delivery” and thus block all messages following the “bad” service call? I’m a bigger fan of letting the service itself catch the exception, log the ID of the object coming in, and on a scheduled basis, go retrieve the actual data from the system of record, vs. trying to make BizTalk keep things all synchronized.
Any architecture experiences with one-way services or patterns you wish to share?

No comments:

Post a Comment

Post Your Comment...