Content Based Routing Web Services in .NET and J2EE

Abstract: In the recent years Web Services has been adopted by the developers community as one of the most popular ways to build distributed applications. The Web Services adoption in some scenarios demands higher requirements. The Web Service protocols stack WS-* defines protocols that address different areas in distributed applications. Routing is one of the vital requirements in distributed applications, some of the main Web Services technology providers provide routing functionality in these platforms using different WS-* protocols. In this article we cover the content-based-routing functionality in three Web Services technologies leaders in the .NET and J2EE worlds: WSE, Indigo and WASP.

Content-Based-Routing.

Routing is long used term in computer environments, basically is the process in which an intermediary decides to redirect incoming messages. When the redirection decision is based in the message's content we talk about content-based-routing. One of the routing's main benefits is to make the application network topology to the client and additionally we gain another item that provides great flexibility to the message-path.

Routing is a key aspect in the Web Services based applications. It is true that neither SOAP and WSDL provides standard routing support but instead if this we count we a series of WS-* protocols that makes possible to add routing potentialities to our applications.

Now we will start to check the routing functionality provided in some of the most important Web Services technologies. Well, say hello to WSE.

Content-Based-Routing using WSE 2.0.

WSE 2.0 have several improvements in routing aspects. Since the version 1.0 WSE supports routing messages capabilities between Web Services using WS-Routing. WS-Routing provides a set of elements that makes possible to describe the route that a message must follow.

<m:path xmlns:m="http://schemas.xmlsoap.org/rp/">
    <m:action>http://testservice/routetest</m:action>
    <m:to>soap://receivertest/firstendpoint</m:to>
    <m:fwd>
      <m:via>soap://B.com</m:via>
      <m:via>soap://C.com</m:via>
    </m:fwd>
    <m:rev>
       <m:via/>
    </m:rev>
    <m:id>uuid:85c9f5d0-33fb-4a56-b02b-5b756641c1d6</m:id>
</m:path>

I don't want to enter in the details of WS-Routing, however we will explore a few details. Messages can be sent forward (m:fwd) for  request message or backward (m:rev) for a response message. Each via (m:via) element defines a specific endpoint in the message path. WS-Routing is based in intra-message routing concepts. A simple SOAP message will traverse a series of intermediaries until arrive to the destination. Each intermediary must modify the contents (removing a via element) of the message and redirects it to the next endpoint (specified by the next via element). Using this concepts the sender of the message must know the whole path that the message will follow. 

WSE 2.0 replaces WS-Routing by WS-Addressing and changes the routing conception to a next-hop routing paradigm. You can see the details in this excellent article of Aaron Skonnard. Next-Hop is a different routing conception, it is based in the argument that a sender endpoint shouldn't have to know the whole message path. Instead it only knows one endpoint which performs the routing needs. Next-Hop routing is a simple and very powerful solution, like the great thinks in our world, and offers the possibility to adds some new features like security to our routing infrastructure. The use of WS-Addressing also brings together a set of additional potentialities like the use of endpoint references that provides the way to pass additional metadata properties, like contracts and policies, with the sender's address.

Routing using WSE 2.0.

In WSE 2.0 there are various features to provide next-hop routing. Mixing these features we can arrive to a set of routing solutions. One of the most important solutions is based in WS-Referral. This specification is used for configure some instructions using by the routers to build  message paths. The following examples indicates that the message targeting http://localhost/testservice.asmx should be routed to http://localhost/testint.asmx..

<r:ref xmlns:r="http://schemas.xmlsoap.org/ws/2001/10/referral">
  <r:for>
     <r:exact>http://localhost/testservice.asmx</r:exact>
   </r:for>
   <r:if/>
   <r:go>
      <r:via>http://localhost/testint.asmx</r:via>
   </r:go>
</r:ref>

The main component in the referral-based routing infrastructure is the SoapHttpRouter component. When a message arrives to an intermediary endpoint the SoapHttpRouter inspects the referral cache and based of its contents and the message performs the necessary steps to route the message to the next endpoint. To use referral-based routing you need to configure the referral cache and the SoapHttpRouter in you application. The next code example shows a simple SoapHttpRouter configuration.

<configuration>
  <system.web>
    <httpHandlers>
      <add verb="*" path="*.asmx"
              type="Microsoft.Web.Services2.Messaging.SoapHttpRouter,
                        Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </httpHandlers>
  </system.web>
</configuration>

You also need to configure the referral cache in your application.

<configuration>
  <configSections>
      <section name="microsoft.web.services2"
         type="Microsoft.Web.Services2.Configuration.WebServicesConfiguration, Microsoft.Web.Services2,         Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </configSections>
  <microsoft.web.services2>
     <referral>
        <cache name="referralCache.config" />
     </referral>
  </microsoft.web.services2>
</configuration>

Well, is amazingly simple. If you want to route the messages based in their contents you must defines a router class that inherits from SoapHttpRouter class  and overrides the  ProcessRequestMessage method. Then follow the same steps explained above and register the custom router.

 public class CustomRouter: Microsoft.Web.Services2.Messaging.SoapHttpRouter
 {
    protected override Uri ProcessRequestMessage(SoapEnvelope message)
   {
                    //writes the routing logic here....
    }
}

WSE 2.0 offers interesting possibilities to route SOAP message between Web Services. However routing in WSE 2.0 is tightly-coupled to the HTTP transport and maybe is a good idea to write and transport-independent routing support fro WSE. Steve Maine writes a series of interesting posts in his blog reflecting about this aspect.

In the past November we see the first version of Windows Longhorn and its three pillars Avalon, WinFS and Indigo. Is my opinion that Indigo represents the most complete technology to develop service oriented applications and we can expect some fantastic features in its releases. Indigo provides support for several advanced Web Services features and, surprise, suports content-base-routing.

Content-Based-Routing using Indigo.

Indigo represents the future of Web Service technologies in .NET environments. As part of its conception Indigo provides solution for several advances aspects in the Web Services World like transactions, reliable messaging and, surprise, routing among others.

To support content-based-routing Indigo provides two fundamental features: routing and filtering.

Routing using Indigo.

The main component in the Indigo routing solution is the router. A router is basically a port extension that intercepts the message in the receive pipeline and executes the routing logic. The router bases its logic in a set of routes that defines the scope of messages to which it applies, the set of endpoints that can receive those messages, and the logic (route type) used to select the endpoints that are to receive messages. In addition to its routing functionality a router can also be configured to acts as a routing policy generator that is a router may returns the routing policy in response to the GetPolicy message from the client. A typical scenario for this feature is the following:

  1. The client sends a GetPolicy message to a router
  2. The router sends a GetPolicy message to a service.
  3. The service returns its policy.
  4. The router adds the routing policy to the policy returned by the services and returns the resulting policy to the client.

 The router uses a RouteSelector to select the appropriate route based on a particular message. All the rules to perform the routing logic are typically stored in a rule store; there are different types of rule stores like MemoryRuleSore and FileRuleStore. The rule manager component loads the rules in the rule store into a RuleView that contains configuration information and properties associated with the rules.  By default the rule manager has two rule views to construct the rules and properties. One rule view is loaded from the rule store and the other is constructed with information from rule manager extensions.

Indigo provides an infrastructure to perform very complicated routing process. Seems to be that the routing process in Indigo is very difficult but this is not true. To program a router in Indigo the first thing that we need to do is to configure the router and the rule manager. The next code shows a simple section of the configuration file that performs this task.

 

<router>
  <rootUri>http://www.tempuri.org/quickstarts/router</rootUri>
</router>
<ruleManager>
  <ruleStore>
     <fileStore>
        <fileName>Router.exe.routes</fileName>
     </fileStore>
  </ruleStore>
  <allowRemoteUpdates>false</allowRemoteUpdates>
  <enforceRemoteSecurity>true</enforceRemoteSecurity>
</ruleManager>

The rule manager for this example uses a file store as the default rule store. The next step is to provide the routing logic in the .routes file. The following code shows a simple .routers file that redirects the messages targeted to a distributed role to other web Service.

<routes>
  <router id="http://www.tempuri.org/quickstarts/router">
    <priorityRoute url="soap.tcp://localhost:46000/Broker/">
      <routingPolicyTtl>10</routingPolicyTtl>
      <priorityDestination>
        <sendTo>soap.tcp://localhost:46001/TestService</sendTo>
      </priorityDestination>
    </priorityRoute>
  </router>
</routes>

These two steps represents all you need to do to develop a router, the other things are the Indigo typical aspects. You need to build an application that hosts the router and the sender-receiver endpoints. Using Indigo you can build complex routing applications and mix the routing functionality with other Web Services advanced capabilities provided by Indigo like Security, Transactions, Reliable Messaging, etc. However if you want to provide your own content-based-routing support to your application you can use another interesting feature in Indigo: message filtering.

A filter is a typical message handler that uses the XPathFilter object to match some filter criteria. In the next code example you can see the uses of XPathFilter in a ProcessMessage method.

XmlNamespaceManager namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("env", "http://www.w3.org/2001/12/soap-envelope");
namespaceManager.AddNamespace("wsa", "http://schemas.xmlsoap.org/ws/2002/12/addressing");
XPathFilter FilterTest = new XPathFilter("/env:Envelope/env:Header/wsa:Action='http://testaction/'", namespaceManager);
if(FilterTest.Match(msg))
  Console.Out.WriteLine("Ok");
else
  Console.Out.WriteLine("Not Ok");

Using the Indigo filter capabilities we can build custom filters that add content-selection facilities to the routing infrastructure.

Well, until now we had seen the content-based-routing support in two .NET based technologies but, what about the J2EE world?.

Content-Based-Routing using WASP.

WASP is a powerful technology developed by Systinet and that brings some Web Services advanced features, like Reliable Messaging, Addressing, to the J2EE environments. The content-based-routing support in WASP is still in an early stage but is based in a non-routing WS-* protocol: WS-Eventing.

WS-Eventing.

WS-Eventing is a specification proposed in January 2004 by Microsoft, Tibco, and BEA. WS-Eventing provides the mechanisms to permit the Web Services to receive some kinds of events. Using WS-Eventing Web Services can subscribe to interests events that occurs in other endpoints. Semantically this specification it is not a routing specification in it all sense. However in practical effects WS-Eventing is a powerful way to redirect messages between Web Services based of its contents. This article isn't to explain all the WS-Eventing's components, however we will explore some type of messages relevant since the content-based-routing perspective. Lets take a look.

Subscription messages.

To subscribe to a particular type of message the subscribing endpoint can send a subscription message to the event source. As part of the subscription message the sender endpoint can specify some filters that identify the messages in which it has interested. The subscription is active for some amount of time, later the subscribing endpoint can renew the subscription. In the other case the subscription in ended passed the specified amount of time.

 <s12:Envelope
    xmlns:s12='http://www.w3.org/2003/05/soap-envelope'
    xmlns:wsa='http://schemas.xmlsoap.org/ws/2003/03/addressing'
    xmlns:wse='http://schemas.xmlsoap.org/ws/2004/01/eventing'
    xmlns:ew='http://www.example.com/warnings'>
   <s12:Header>
     <wsa:Action>
       http://schemas.xmlsoap.org/ws/2004/01/eventing/Subscribe
     </wsa:Action>
     <wsa:MessageID>
        uuid:ac586c5c-5566-48r1-8c77-fc1c2rv47650
     </wsa:MessageID>
     <wsa:ReplyTo>
        <wsa:Address>http://MyMachine/WSEventingTest/MyEventSink</wsa:Address>
        <wsa:ReferenceProperties>
          <ew:MySubscription>3402</ew:MySubscription>
        </wsa:ReferenceProperties>
     </wsa:ReplyTo>
     <wsa:To>http://MyMachine/WSEventingTest/EventSource</wsa:To>
     </s12:Header>
     <s12:Body>
       <wse:Subscribe>
           <wse:NotifyTo>
             <wsa:Address>
                http://www.other.example.com/OnStormWarningSubscriber.asmx
             </wsa:Address>
              <wsa:ReferenceProperties>
                 <ew:MySubscription>3402</ew:MySubscription>
              </wsa:ReferenceProperties>
           </wse:NotifyTo>
           ................
         
<wse:Expires>Some date</wse:Expires>
          <wse:Filter xmlns:er='http://wseventingtest/FirstSample'>
                 /s12:Envelope/s12:Body/er:Product/ow:Price > 60
          </wse:Filter>
    </wse:Subscribe>
  </s12:Body>
</s12:Envelope>

WS-Eventing uses WS-Addressing in its messages. The <wsa:action> header specify that the message is a subscribe message. The <wsa:ReplyTo> header indicates where to send the subscription response messages and <wsa:To> represents the EventSource of Product events. Enter in the body we find the <wse:NotifyTo> element that indicates where to send notification messages with some reference properties. Later <wse:Expires> contain the expiration date of the subscription and the <wse:Filter> defines the events in which the event sink has interests based of the message's contens.

In response to this message the endpoint specified in the ReplyTo header receives a Subscription response message. Once the subscription have been established  the subscriber begin to receive notification based of the messages send it to the service specified in the subscription message. This part of the mechanism is similar to content-based-routing, the Eventing infrastructure monitor the services, inspect the receive message and if one message math the subscription filter it redirects this message to the subscriber endpoint. WS-Eventing support other types of messages to optimize the subscription mechanism like Subscription Ends, Renews, and UnSubscribes.

The fact is that WS-Eventing is not a routing specification and consequently it have some limitations. Adds specific security features  like signing and encryption, for each endpoint,  is very limited since each router can inspect the message and based of its contents can construct a notification message. In the other hand construct a  routing path can be very tedious due the fact that each router may create subscriptions to the preceding router in a particular path.

Now we explain how to use WS-Eventing to route messages between Web Services using the WS-Eventing implementation provided by Systinet.

Routing using WASP.

When we install and configure the cbr package into the WASP platform we have a WS-Eventing-based content-based routing service and some tools to manage the subscriptions. The subscription process can be very simple if we use the content-based-router adding in the WASP administration console. Using this tool we set the endpoint to receive the notifications and the filter that qualifies this type of event. When you finish to configure the subscription you are ready to receive notification messages generated by WASP. You can build your subscriber using almost any Web Services development tool and then send messages to the preconfigured router typically (http://localhost:6060/cbr) , if your message match the established filter a notification message is send to your subscriber endpoint. Using this administration tool you can make operations like list and delete over the subscription and is amazingly simple.

The WS-Eventing Web Service in WASP is typically located at http://localhost:6060/cbr-wse/routernameroutername the default router name is default. In addition every router also provides an administration endpoint to complement the WS-Eventing with operations like retrieve the list of subscriptions, etc. The next code shows how to subscribe programmatically to some kind of event that fires when the price of some product exceeds 100.

TestSubscription.NotifyTo=new EndpointReferenceType();
TestSubscription.NotifyTo.Address=new AttributedURI();
TestSubscription.NotifyTo.Address.Value= "http://localhost/SubscriberHost/TestService.asmx" ;

TestSubscription.Filter=new MessagePredicateAssertion();
TestSubscription.Filter.Value= "/s12:Envelope/s12:Body/er:NewProduct/er:Price > 100";
TestSubscription.Expires=expireDate;
Eventing objEventing= new Eventing(cbrRouterURL);
SubscribeResponse SbrResponse =new SubscribeResponse();
SbrResponse =objEventing.SubscribeOp(TestSubscription);
SbrResponse =objEventing.SubscribeOp(TestSubscription);

WS-Eventing is not a routing specification. However provides the mechanisms to fires messages based of some rules about the content of event messages. We can adopt the cbr implementation of Systinet to develop powerful content-based-routing applications. In the future other platforms will provide WS-Eventing implementations that interoperate each other.

Where are We?.

In this article we have explored the content-based-routing functionality vision in three Web Service technologies and the use of different WS-* protocols to provide routing capabilities. In both .NET and J2EE environments we have interesting choices to develop content-based-routing Web Services applications. With the evolution of WS-* protocols there is no doubt that we will find other powerful implementations that support routing functionality and mix it with other Web Services capabilities.

Resources.

Moving from WS-Routing to WS-Addressing Using WSE 2.0.

Code Name Indigo: A Guide to Developing and Running Connected Systems with Indigo.

Longhorn SDK.

WS-Eventing and content-based routing for integrating multiple applications via Web services.

from c# corner

posted on 2004-07-26 21:15  星星之火  阅读(1114)  评论(0编辑  收藏  举报

导航