How to implement retries on BizTalk ESB Off-Ramps

I'm sitting in the Vancouver airport reflecting on a very successful and interesting 2 day deep dive training course that we ran for our west coast partners. This was the first time that we ran the course over two days, and it allowed us to get a lot deeper into the code than we normally would in a one day session. Because of this, we received a lot of great questions from the developers who attended. While I'm waiting for my flight, I thought I'd blog about a couple of them.

Those of you familiar with the concept of Off-Ramps in the Microsoft ESB Guidance for BizTalk server will know that they are implemented using Dynamic BizTalk send ports. Dynamic ports have the ability to configure themselves at runtime based on contextual data stored within a message. The message itself is able to tell the dynamic port how to function, what transport protocol to use, what endpoint to point towards etc.   The ESB guidance contains an adapter provider mechanism and a resolver mechanism which allows you to store this configuration data in external data stores like a UDDI server, SQL Server, a rules engine etc.  The ESB resolver mechanism looks up this information from this remote data store and feeds it into an adapter provider. The adapter provider then converts this data into a format that a BizTalk dynamic port can use to configure itself.

BizTalk also has the concept of static ports which do not load configuration data at runtime but instead require an administrator to hard code configuration data right into the port. Static ports are not as flexible as dynamic ports and are therefore not as effective when implementing an ESB pattern. However, they do have a number of interesting features that aren't seen in dynamic ports. One of these features is the ability to define a retry interval and a set number of retries.  If the port fails to transmit a message successfully the first time, it will shut down and then retry the message after a set period of time. The port will continue to try and resend the message until it reaches a maximum number of retries. A BizTalk administrator can set the length of the retry interval and the number of retries for a static port directly in the BizTalk administration console.  However, when you create a dynamic port in the admin console, these configuration options do not show up. The question that one attendee asked was

"Since the ESB guidance is heavily dependant on dynamic ports , is it unable to support retries"?

Fortunately the answer is definite "NO". The ESB guidance with its adapter providers is able to support retries. To do this, you need to tweak the adapter providers classes to tell them to set this property for us.

The adapter providers effectively work like a dynamic runtime level BizTalk administrator, they provide a complete set of configuration information to the dynamic port.  The adapter providers pull this information from the resolver mechanism which is able to connect to the UDDI server, database server etc. In the basic guidance, the adapter providers pull down a small subset of configuration information from the resolver mechanism. We can modify this to pull additional information such as retry settings.

I've outlined the steps below that you need to follow in order to implement retry functionality. For this walk-through, I'm going to use the UDDI server to store our information. I'm also going to be working with the WCF-basicHTTP adapter provider that allows us to implement SOAP 1.1 messaging

1)  The first step is to modify the service entry in the UDDI server so that it contains the retry settings.  Open up the service entry in the ESB that you want to implement retries for. Add a new binding to this service call called "RetryCount" and give it a value of "5" (i.e. the adapter will retry 5 times). Create a second new binding called "RetryInterval" and set this equal to "1" (this means retry every 1 minute).

2) We don't need to modify the resolver mechanism as it is already built to automatically pull down any and all information from the UDDI registry. As long as we put the data in there, it will pull it down and given it to the adapter provider, which we'll do next.

3) Open up the Microsoft.Practices.ESB.sln solution file and open the ESB.Adapter.WCF-basicHTTP project. Inside this project, open the AdapterProvider.cs class.  If you scroll down to lines 82 and 83, you'll see where the adapter provider takes the settings retrieved from the resolver and attaches them to the outgoing message as adapter properties.  You will need to add the following 2 lines in the section.

pipelineContext.Write(BTS.RetryCount,"https://schemas.microsoft.com/BizTalk/2003"  , ResolverDictionary["Resolver.RetryCount"] );
pipelineContext.Write(BTS.RetryInterval, "https://schemas.microsoft.com/BizTalk/2003", ResolverDictionary["Resolver.RetryInterval"] );

This code will retrieve the settings we made in UDDI and will attach them to the outgoing message context. The dynamic adapter will then use these settings when it attempts to send the message.

4) Build and deploy the new version of the adapter provider project.

5) Restart the BizTalk host instance and the IIS service instance

That's it, you've implemented retry capabilities in ESB guidance for the WCF-basicHTTP OffRamp.

Cheers and keep on BizTalking