As promised, here's the follow up to my earlier post One Way operations in services
It came as a shock to me recently to discover that BizTalk 2006 R2 (which added support for WCF to BizTalk 2006) doesn't support WCF one-way operations over anything other than MSMQ. This post by Sonu has some of the details: WCF One Way Services and BizTalk WCF Adapter
"All WCF clients and services that communicate with the BizTalk WCF adapter are expected to be two way, with the exception of services that use NetMsmqQueueBinding. For every other binding, BizTalk expects a void response back from the service (or a non-void response if using a two-way send port). This is so that BizTalk knows when to delete the message from the Message Box and thereby ensuring no message loss."
This is a tiny bit disappointing as BizTalk has long supported one-way operations with ASMX endpoints. One of the things I've always liked about BizTalk is how it encourages loose-coupling. For example, if I design an orchestration that receives a message from one system, does some work and sends a message to another system.
At this point I don't care about the adapter, transport or protocol implemented behind those ports; it might be a file, it might be a web service or it might be MSMQ. This is a good thing.
As an example I took the orchestration shown above which has a one-way receive port and a one-way send port. I decided to publish an ASMX service for the receive
port and configure a file-adapter for the send port. And it works just as expected: I fire a HTTP web service request at an ASMX end point and get an instant
acknowledgment. Some time later, a file appears at the location specified by my file adapter. Happy days.
Now lets assume I want to add a WCF endpoint to expose this orchestration. I follow a similar process as when hosting an ASMX endpoint but this time using the BizTalk WCF Service Publishing Wizard:
As you can see from the screenshot above, the wizard has even recognised the one-way receive port in my orchestration and is ready to publish it. Great. Once published - I can even see the WSDL. Beautiful.
However, it's only when we try to call the service method and get a soap fault that we know something is wrong:
"The published message could not be routed because no subscribers were found. This error occurs if the subscribing orchestration or send port has not been enlisted, or if some of the message properties necessary for subscription evaluation have not been promoted. Please use the Biztalk Administration console to troubleshoot this failure."
The other clue is the freshly suspended (non-resumable) message. Boo.
So what if I want to use WCF as a receive port with this orchestration? I can see two choices.
Change the orchestration to have a request/response port and send back some null/void message. BizTalk doesn't really deal in voids so I created a new XmlSerializable class called void that I could use as my response, it's as simple as this:
[XmlRoot(ElementName = "Void", Namespace = Void.NAMESPACE)]
public class Void
private const string NAMESPACE = "urn:schemas-yourcompany-void:2008-08";
Here's what such an orchestration might look like:
I don't like this for two reasons; the orchestration had to change (and therefore became protocol/adapter aware and we effectively lost our loose coupling that I like so much) and the client will get a much slower response.
Create a WCF wrapper hosted in IIS that isn't directly connected to BizTalk and can therefore support one-way operations. Then talk directly to another adapter (e.g. SOAP) that does support one-way ports in BizTalk.
What about performance?
Whilst the first solution does take longer to respond to the client (whilst BizTalk writes to the MsgBox, reads from the MsgBox, starts the orchestration, writes to the MsgBox and so on....) the latter solution does waste some cycles deserializing and reserializing messages but it would respond to the client much more quickly and keeps the abstraction intact. However, chances are you wanted to use a WCF based adapter for a reason, maybe WCF's support for distributed transactions. Of course, this would rule out wrapping a SOAP adapter as an option.
I really hope the lack of one-way support will be fixed in future combinations of BizTalk and WCF (though my personal guess
would be this won't happen in the R3
timeframe) as BizTalk has the ideal mechanism for guaranteed delivery just like MSMQ - once the message has been written to the Message Box it's been delivered; time to send our 202 back to our client.
01 Sep 2008
» Next Post:
« Previous Post:
Guaranteeing the order of results in SQL Server
Comments are closed for this post.
13 Oct 2008
Good article and very valid points. I too have never really liked the idea of the orchestration knowing so much about the protocol and the message exchange pattern. Proper business processes should always be independent of those concerns. But i found that one way to alleviate this is to make use of facades. The main business orchestration will always subscribe to the message box, pick its messages from there and send back the responses. The facade is responsible for getting the data from the endpoint and publishing to the message box. Direct binding is helpful and if you need an async communication between the orchestrations you can make use of correlation on some message/data context. This is also useful when you use Schema WS that are 2 way because if you publish straight to the message box , the orchestration listening to the msgbox will receive it but the port wont get back the message because of some problems with the way the Endpoint manager handles the routing (its been explained in another blog post somewhere quite well, gotta dig that out) , so in many cases you need to have an orchestration listening for the message. These orchs are not 'business processes' merely transitory vehicles.