February 2008 - Posts

Darren Jefford at the next BizTalk User Group meeting in Stockholm
29 February 08 11:14 PM | wmmihaa | 1 comment(s)

I'm happy to announce that Darren Jefford will do two sessions at our next BizTalk user group meeting in Stockholm at the 8th of April. The first session will be about performance and testing followed by "stories from the field", and of course, lots of Q&A.

Darren Jefford is a Principal Consultant, Application Development Consulting at Microsoft UK. He is also the author of the Professional BizTalk Server 2006 book.

   

I've been fortunate to attend several of his sessions at TechEd and at the SOA Bpm conference. His experience with large scale BizTalk solutions, together tips & tricks and lots of knowhow, makes you really want to attend this meeting.

The invitations will be sent out next week.

Darrens Blog: http://blogs.msdn.com/darrenj/

ESB Guidance...part 7
06 February 08 10:26 PM | wmmihaa | 5 comment(s)
How to consume an Itinerary Service

I have to admit; -I wasn’t planning on writing seven articles about ESB Guidance. But the documentation does not cover much of this topic, and there are things to take under consideration when working with the itinerary services provided by the ESB Guidance.

Normally when working with Web Services, we are given a URL, which we’ll reference in our Visual Studio project. Adding this reference will give us a proxy class, along with other classes needed to submit the service methods.  For example if the service would have a SubmitOrder(Order order) method, we’d have an Order class to work with.

ESB Guidance comes with both a Web Service and a WCF Service Itinerary On-Ramps. Both versions support One-way- and Two-way messaging scenarios.

Calling an Itinerary Service is a bit different from calling a Web- or WCF Service in a normal fashion. This is because the service methods are not typed to any request or response object.  Each itinerary service method can serve any type of itinerary, which is the actual definition of what the service will do. In other word, part from many practical reasons, it is possible to have only one receive location and one subscribing send port, to serve as all endpoints of your BizTalk solution (please do not read this as an recommendation). For more information about how Itineraries work, see previous post.

So being a consumer of an Itinerary Service, clearly, given a URL is not enough. We also need the schema definitions along with the actual itinerary (xml file).

If you are comfortable with creating the xml message in your code, all you need to do is to add the service reference to your project, create your xml message according to the schema, deserialize the itinerary xml to the Itinerary object and call the service:

static void Sample1()
{
    // Create the Order xml. This is the "object" that is going to be submitted.
    XmlDocument orderXml = new XmlDocument();
    orderXml.Load(@"C:\ESB Guidance\Data\NAOrderDoc.xml");
    
    // Create the Itinerary Xml Document from the file 
    XmlDocument itinararyXml = new XmlDocument();
    itinararyXml.Load(@"C:\ESB Guidance\Itineraries\SubmitOrderItinerary.xml");

    // Calling the WCF Service
    using (ProcessRequestClient wcfClient = 
        new ProcessRequestClient("WSHttpBinding_ITwoWayAsyncVoid"))
    {
        if (wcfClient.State != System.ServiceModel.CommunicationState.Opened)
            wcfClient.Open();

        // Creating the Itinerary
        // Deserialize the OuterXml to the Itinerary object
        StringReader reader = new StringReader(itinararyXml.DocumentElement.OuterXml);
        XmlSerializer ser = new XmlSerializer(typeof(Itinerary), 
            "http://schemas.microsoft.biztalk.practices.esb.com/itinerary");
        Itinerary wcfItinerary = 
            (Itinerary)ser.Deserialize(reader);

        // Submit WCF Call
        wcfClient.SubmitRequest(wcfItinerary, orderXml.OuterXml);
        wcfClient.Close();
    }

    
    // Same as above but calling the Web Service
    using (asmxItineraryOneWay.Process svc = 
        new asmxItineraryOneWay.Process())
    {
        svc.Credentials = System.Net.CredentialCache.DefaultCredentials;

        // Creating the Itinerary
        // Deserialize the OuterXml to the Itinerary object
        StringReader reader = new StringReader(itinararyXml.DocumentElement.OuterXml);
        XmlSerializer ser = new XmlSerializer(typeof(asmxItineraryOneWay.Itinerary), 
            "http://schemas.microsoft.biztalk.practices.esb.com/itinerary");
        asmxItineraryOneWay.Itinerary asmxItinerary = 
            (asmxItineraryOneWay.Itinerary)ser.Deserialize(reader);

        // Set the ItineraryValue
        svc.ItineraryValue = asmxItinerary;

        XmlNode orderXmlNode = (XmlNode)orderXml;
        svc.SubmitRequest(orderXmlNode);
    }

}

However, you could use Xsd.exe or XsdObjectGen.exe to create the Order class, to submit to the service method. I also created a sample ItineraryFactory class to help deserialize the Itinerary and to serialize the Order object:

static void Sample2()
{
    // Create the Order object.
    OrderDoc order = new OrderDoc();
    order.customerName = "Microsoft";
    order.ID = 1;
    order.requestType = 10;

    // Create the Itinerary
    string itineraryXml = @"C:\ESB Guidance\Itineraries\SubmitOrderItinerary.xml";
    Itinerary itinerary = ItinaryFactory.Load(itineraryXml);

    // Serialize the Order object to string
    string data = ItinaryFactory.SerializeToString(order);
    
    using (ProcessRequestClient client = new ProcessRequestClient("WSHttpBinding_ITwoWayAsyncVoid"))
    {
        if (client.State != System.ServiceModel.CommunicationState.Opened)
            client.Open();
        client.SubmitRequest(itinerary, data);
        client.Close();
    }
}
ESB Guidance...part 6
01 February 08 11:04 PM | wmmihaa | 18 comment(s)

Policy based routing using the Business Rule Engine resolver

There are several samples that come with the ESB Guidance installation utilizing the BRE Resolver to resolve the endpoints.  All of them implements a very simple rule that states  {if 1==1 then...}. This can still be useful when you only want to use the BRE for the purpose of having an endpoint repository. In which case you'd create one policy for each endpoint.

But what if you'd like to apply a rule like {if Customer == "Microsoft" then... else..}. Of course the ‘else' statement has to be implemented as a new rule, but part from that, this could be very useful if you like to route the message to different endpoint depending on the context of the message. Sort of like Content Based Routing but being able to support more complex scenarios.

Looking at the BRE connection string there is a ‘useMsg' property. How to use this property is not described in the documentation, and in all the samples useMsg is set to null (False).

BRE:\\policy=GetCanadaEndPoint;version=1.0;useMsg=;

Setting this property to True, should cause the Resolver Manager to add the message as a fact upon executing the policy. Unfortunately there is a bug in the ResolveProvider in ESB.Resolver.ESB assembly:

Dictionary<string, string> IResolveProvider.Resolve(string config, string resolver, 
    IBaseMessage message, IPipelineContext pipelineContext)
{
    
    // Resolve the params from arguments by creating
    // class from schema, and storing the results
    Resolution resolution = new Resolution();
    XmlDocument xd1 = null;

    try
    {
        // Populate context
        ResolverMgr.SetContext(resolution, message, pipelineContext);

        // resolve with rules and return dictionary
        return ResolveRules(config, resolver, xd1, resolution, message);

    }
    catch (System.Exception ex)
    {
        EventLogger.Write(MethodInfo.GetCurrentMethod(), ex);
        throw;
    }
    finally
    {
        if (null != resolution)
            resolution = null;                
    }
}

The problem is that the XmlDocument xd1 (the actual bts message) is always going to be null, and will cause an null object reference exception to be raised. You will have to fix this by changing it to (line 224):

XmlDocument xd1 = new XmlDocument(); 

The next problem was a little bit trickier to figure out. It seemed the BRE could not match the DocumentType with the actual message. As it turn out, the DocumentType has to be added to the BizTalk context properties before the resolver is executed or it will be set to "Microsoft.Practices.ESB.ResolveProviderMessage".

This means you have to change the DocumentType in the Business Rule Composer.

BRE Fact Explorer

Then set the useMsg property to True:

BRE:\\policy=GetEndPointByCustomer;version=1.0;useMsg=True;

And implement your rule:

Rule

Good luck!

 

Filed under: , ,

This Blog

News

    MVP - Microsoft Most Valuable Professional BizTalk User Group Sweden BizTalk blogdoc

    Follow me on Twitter Meet me at TechEd

    Visitors

    Locations of visitors to this page

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

Syndication