Contract-First Development With BizTalk Server (And A Gotcha)


In my last
MSDN webcast
I briefly demonstrated true contract-first development using BizTalk with schemas and orchestrations. I wanted to walk through
the steps here, and point out a huge "gotcha" that stumped me for a bit.

So I started constructing this sample app to prove that I could build out and deploy my contract and service before adding any "guts" to the process
underneath. I did this by first creating two schemas, representing the messages that go both into and out of my service. At this point,
all I have is a deployed BizTalk project with two schemas. Next, I walked through the BizTalk Web Services Publishing Wizard, and chose
to Publish schemas as web services.



The value of this capability eluded me for a while when I first started using BizTalk 2004. Why would I ever create a service out of schemas?
Most commonly, you'd use this function to create a "fire and forget" asynchronous channel for folks to submit messages with no expectation
of response. Then, you could have any series of orchestrations pick up the inbound doc and process it. In my case however, I want to
create an actual request-response service. So my next step in the Wizard was to delete the default web service configuration.



I created a new service called TradingPartnerService. And then I added a new request-response web method
called SubmitOrder. The parameters for this method were the two schemas I created previously (one for request, one for
response).



I then completed the wizard without having it create the pre-configured Receive Location for me. Mainly because I like creating my
own. So, into my application I added a new Receive Location (and Receive Port) configured with SOAP and pointing to my fancy new service.



At this point, I have a real-life service with input and output ready to go. Now, obviously if I go and consume this service,
BizTalk won't be happy since I've added no subscribers to this inbound message. But, I've still defined my contract and interface
prior to any implementation logic.

My next step is to create an orchestration that will consume this service. In my orchestration I created a stock request-response port type
and port, and put some fairly basic processing inside. The Messages received and returned are the same types that the service
expects.



Then I deployed my orchestration, and bound it to my Receive Port that had a SOAP Receive Location. At this point, everything should
work fine. I've got a processing subscriber to take my request message and generate a valid response message to my caller. However,
when I called this service from my simple UI, I got a dreaded: System.Web.Services.Protocols.SoapException: internal soap processing failure -->
batch completion failure
. I hate this error. So freakin' vague. So after checking all sorts of security things (since that's my
problem with web services roughly 92% of the time), I kept getting the same error. My suspended message list had a message with no
body, but interesting context.



Now what had bugged me up until now was how calling this particular service method (SubmitOrder) actually got the message to my
orchestration. Notice in the context above that the calling method is captured. So, I went to the Subscription Viewer in the
Administration Console and checked out the subscription for my orchestration. I saw the picture below, and immediately began raining
mighty blows upon my head.



Because I had kept the default operation name in the orchestration (Operation_1), that became the service method name it's looking for
on inbound messages, NOT the actual name SubmitOrder. So, of course the inbound message couldn't find a subscriber! I went back
to my orchestration and changed my port Operation name to match the service method. This is the gotcha.



Once I redeployed my changes, I refreshed my subscription. Now I see a good looking subscription, and calling my web service gives me
expected result.



So a couple morals. First of all, you can see how calling a web service actually reconciles to a physical subscription. The method
name plays a key part there. On a related note then, that service name needs to match up with a subscriber or you're service call will
fail. As you can see, it's completely possible to do contract-first development with BizTalk, and fill in the plumbing logic later
on. You just have to make sure you tie all your pieces together!

Skip to main content