Using the Microsoft ESB Guidance: UDDI

Some of you may have heard by now that we are in the process of releasing the Microsoft Enterprise Service Bus (ESB) guidance. This guidance contains pre-built components, use cases, documentation and sales material that our Business Process Integration partners can use to rapidly deploy ESBs on top of BizTalk, Windows, SharePoint and SQL Servers.  Over the holidays I spent some time digging into the code and thought I'd share a bit of what I've been seen. 

I thought that I'd first talk about the standard ESB concept of "EndPoint Resolution" and how our guidance allows you to achieve this.  Endpoint resolution is core requirement in any ESB as a Service may not always reside at the same address or endpoint. Therefore we need to be able to locate our services at runtime (wherever they may be).   The Microsoft ESB guidance comes prebuilt with this capability, so I thought I post a small "How-To" blurb about how you can do it.

The Task

The basic task I thought I'd tackle is to submit a generic message from a basic client application into the ESB and have it routed it to a Service based on a entry in a local UDDI server.  The following image show the Services that exist in my UDDI server.

  1.  

  2. The service that I'll wanted to submit the message to is "ENDPOINT: PostOrderMessage".  You can see from the screen image that this Service has been setup with a File Folder as its endpoint. "C:\projects\Microsoft BizTalk ESB\Tests\Common\Filedrop\Output\Order %MessageID%.xml"  If the solution works properly, I should be able to find my messages sitting in this folder.

  3.  

  4. ESB Concept: The "On Ramp"

  5.  

  6. As you dig into the guidance you'll quickly learn that one of the key components within it is the "On Ramp".  The On Ramp acts as a central entry point into the ESB engine and it allows client applications to submit generic messages that contain processing, routing and transformation instructions. The On Ramp is a key concept to understand in order use the ESB guidance and if you're planning on using it, you'll need to have a good understanding it.

  7.  

  8. To keep things simple, the On Ramp is a Web Service that applications can use to submit XML based messages into BizTalk. On top of this, the On Ramp allow us to specify a number of processing, routing and transformation instructions that the BizTalk will follow when processing the message.  To send these processing instructions, we use specific SOAP headers that are attached to our message when we submit to the On Ramp . If you've got the ESB guidance already, you can view all of the possible headers by opening the "EsbEnvGeneric.xsd" property schema file in the Microsoft.BizTalk.Esb.Schema project.  This XSD file is a standard BizTalk property schema and denotes the properties that our SOAP headers will eventually be promoted into.  For those of you that don't have the guidance, here a quick list of the parameters you can use when submitting your messages.

  9.  

    • ProcessingInstruction
    • Itinerary
    • MapRulesPolicy
    • MapSelAssemblyName
    • MapSelMethodCall
    • MapSelTypeName
    • MapType
    • MapUddiLabel
    • MapXPath
    • EndpointAddress
    • EndpointConfigurationString
    • EndpointConfigurationRulesPolicy
    • EndpointConfigurationUddiLabel
    • EndpointConfigurationXPath
    • EndpointDeliveryAgent
    • EndpointMessagePattern
    • EndpointRulesPolicy
    • EndpointSelectAssembly
    • EndpointSelectMethod
    • EndpointSelectType
    • EndpointUddiLabel
    • EndpointXpath
  10.  

  11. For most projects, you'll ending have to work with most these headers in order to achieve full ESB capabilities, but for our simple task we'll just need to use three:

    1. EndPointUddiLabel - We use this to tell the ESB the name of the Service to lookup in the UDDI
    2. ProcessingInstruction - We use this to tell the ESB that the message needs to be routed.
    3. Itinerary - Where we'll tell the ESB that this message needs to following a routing itinerary
  12.  

  13. Building the Solution

  14.  

  15. The first thing I did was to deploy and configure the ESB guidance as per the installation instructions it ships with. I won't cover those steps here, so I'll just jump to what I did once that process was complete.

  16.  

  17. The first thing I did was to build out a client app that I could use to submit my messages to the ESB.  I used a very basic Windows Forms application as my client. All I needed was a form that would let me to define my message and specify the name of the Service I wanted to route the message to.

  18.  

  19.  

  20. Once I had my basic form built out, the next step I needed to take was to add a web reference to the ESB On Ramp. 

  21.  

  22.  

  23. Once I'd added the web reference, I had everything I needed to submit messages into the ESB. For my project,  I created a function to handle all interaction with the On Ramp web service. It creates my message, assigns the three SOAP headers I need and submits the message it to the On Ramp Web Service. Here's the code:

  24.  

  25. /// <summary>

  26. /// This function prepares a message and submits it to the ESB on ramp

  27. /// </summary>

  28. /// <param name="strMessageBody">The core content of the message</param>

  29. /// <param name="strServiceName">The name of the service in the UDDI that we want to send the message to</param>

  30. private string SubmitMessage(string strMessageBody, string strServiceName)

  31. {

  32. // Get an instance of the On Ramp Service

  33.          ESB.OnRamp ramp = new ESB.OnRamp();

  34.  

  35. // Assign security credentials

  36. ramp.Credentials = new System.Net.NetworkCredential("username", "password");

  37.  

  38. // Assign values to the headers we need to perform the UDDI based routing

  39. ramp.EsbSoapHeadersValue = new ESB.EsbSoapHeaders();

  40. ramp.EsbSoapHeadersValue.EndpointUddiLabel = strServiceName;

  41. ramp.EsbSoapHeadersValue.ProcessingInstruction = "ROUTE";

  42. ramp.EsbSoapHeadersValue.Itinerary = "ROUTE";

  43.            

  44. // Get the message to send

  45. XmlDocument doc = new XmlDocument();

  46. doc.LoadXml(strMessageBody);

  47.  

  48. try

  49.             {

  50.                 //Send the message and return the result

  51.                 ramp.Receive(doc);

  52.                 return "Message Submitted Successfully.";

  53.             }

  54. catch (System.Exception ex)

  55. {

  56. return "Error: " + ex.Message;

  57. }

  58. }

  59.  

  60. As you can see, the ESB class that was created when we added our Web Reference, contains a 2 classes. The "ESB.OnRamp" class which is our proxy to the actual Web Service and the "ESB.EsbSoapHeadersValue" class. This second class contains all of the properties that relate to SOAP headers that the ESB On Ramp will use.

  61.  

  62. I setup the OnClick event of my Submit button to call this function and I passed in the values of my two textboxes.  As easy as that, I had built an application that was able to send a message into my ESB architecture.  Once I'd done that, the ESB engine took care of everything else.  It only took me ~10 minutes to build out my app and start routing my messages to Services.  Its really is pretty simple and easy to get going with this.  I've included a screen cam video at the end of this entry that shows me running the solution. (Its set for 1024x768 resolution)

  63.  

  64. Now that you've seen how to route message using UDDI, some of you might wonder what exactly is going on under the BizTalk covers. So lets take a look.

  65.  

  66. The Inner Workings

  67.  

The first thing to look at is obviously the On Ramp. The On Ramp is essentially a Web Service and a BizTalk receive port. The receive location within the port uses the SOAP adapter to interact with the Web Service and also uses a custom pipeline "ReceiveForESBGeneric".

 

  1.  

The SOAP adapter is configured to use the same Web Service that we made a web reference to in our client application. The custom pipeline is responsible for promoting the SOAP headers into BizTalk message properties so that other elements within BizTalk can access our instructions. Once the receive location processes the incoming message, the message (along with its promoted properties) is published into the standard BizTalk MessageBox and the On Ramp is done its work.

  1.  

At this point, another BizTalk artifact takes over, the "Generic.odx" orchestration. This orchestration comes as part of the guidance and can be found int the Microsoft.BizTalk.ESB.Agents.Delivery project. The messages received from our On Ramp receive port are sent to this orchestration using BizTalk's standard publish/subscribe mechanism. This orchestration handles all incoming messages that need to be routed.

 

  1.  

The orchestration has a direct bound receive port based on specific filter expressions. The receive shape that has a filter setup to receive all messages that have their "ProcessingInstruction" property set to "ROUTE". Hence why I had to set that that SOAP header to use a value of "ROUTE" in my client application.

 

 

Once receiving the message, the orchestration checks to see if an proper endpoint has already been assigned to this message. If it hasn't, then the orchestration will begin the process of resolving it. This is done in the "Call Resolution Class" expression box in the "Resolve EndPoint" scope.  In this expression box, a call is made to a function call "Microsoft.BizTalk.ESB.Helpers.Resolver.Resolve".  This function is a part of a custom library that ships with the ESB guidance and it handles the lower level steps required to resolve the endpoint.

 

In our example, we specified a UDDI service name in the EndPointUddiLabelField SOAP header.  Because we did this, the Resolve function will attempt to resolve the endpoint by making a call to the UDDI server.  If it finds the requested service in the directory, then the endpoint is returned (as a string) to the orchestration.

 

This endpoint is then used to configure the "GenericDeliveryAgentSend" dynamic port .  The configuration of the port is done in the "Set Endpoint" expression shape.

 

 

Once configured, the port is able to transmits our message to the Service endpoint.

 

As you can see, the orchestration also contains number of exception handling steps which all tie into the central exception management framework that the guidance contains. The orchestration also contains a number of "Tracing" steps which allow for easier debugging of the process.

 

More than just UDDI and more than just Routing

 

I've quickly shown how to submit a message to the ESB engine that ends up being routed based on a UDDI entry. However I must add that you aren't limited to UDDI lookups for your address resolution.  Using the SOAP headers, you can tell the ESB engine to use the Business Rules Engine or you can pass in the End Point directly with your message and there are also options for using XPath.  The code contained in the guidance is incredibly flexible with regards to how you want to handle your endpoint resolution.

 

Also, message Routing is just one feature of the guidance. It also provides some great capabilities around dynamic message transformation, centralized exception management for services, linked itineraries and more.   There are more than a few projects I've worked on where I wish I had this functionality prebuilt for me!

 

Cheers and Keep on BizTalking...

ESB_EndPoint_Resolution.zip