Dynamic Configuration of SOAP Routers



Dynamic Configuration of SOAP Routers

One glaring deficiency you may have noticed is the lack of a way to notify a router where to send a message for any particular via. In other words, without some kind of mechanism for configuring routers, the client will need to know the entire route (or each router will have to follow a proprietary configuration protocol). Because virtualization of the network is our goal, we need to change that.

Definition: Virtualization

Virtualization is used to describe what WS-Routing and WS-Referral give us. By using logical names and allowing the binding of multiple physical locations for any particular logical name, we have virtualized the topology of our distributed application.

Enter WS-Referral. WS-Referral enables routing nodes, including message senders, to send and receive route configuration data. This protocol is fairly simple, although it does have some gotchas here and there. You can send this referral information inside a SOAP header as part of a normal SOAP operation, or you can send specific referral information.

WS-Referral describes a schema for describing referrals. These referrals take the form of logical names and another name (logical or physical, usually the latter) that any messages for that logical name should travel via. WS-Referral also describes how to include these documents in SOAP headers, as well as SOAP-based operations that can query a WS-Referral layer and update a WS-Referral layer's set of referrals.

Typically, WS-Referral documents take the following form:

  1. For some name

  2. Go via some other name

  3. If this condition is true (such as this referral not being expired)

Listing 12.6 shows an example of a simple WS-Referral statement.

A Simple WS-Referral Statement
<ref xmlns="http://schemas.xmlsoap.org/ws/2001/10/referral">
  <for>
    <exact>soap://keithba.com/POService/Service.asmx</exact>
  </for>
  <if>
    <ttl>3600</ttl>
  </if>
  <go>
    <via>http://service0.keithba.com/PO/service.asmx</via>
  </go>
</ref>

WS-Referral statements can state a for of either an exact or prefix nature. Exact matches are when a URI is exactly the same, based on the URI schema being used. This isn't precisely the same as a string comparison, because URIs have some specific rules.

A for statement can also include a prefix match. This is then used to match any number of URIs that happen to match the prefix given. Listing 12.7 shows an example.

Using a Prefix Match in a WS-Referral Statement
<ref xmlns="http://schemas.xmlsoap.org/ws/2001/10/referral">
  <for>
    <prefix>soap://keithba.com/</prefix>
  </for>
  <if>
    <ttl>3600</ttl>
  </if>
  <go>
    <via>http://service.keithba.com/Handler/service.ashx</via>
  </go>
</ref>

One of the problems with the current draft specification of WS-Referral is that it uses a ttl for the expiration. Although it doesn't describe what this ttl is relative to, it's reasonable to assume that the ttl is from the time the message with the referral state was sent. For that reason, I prefer to add a custom element in the if statement for the date and time, as shown in Listing 12.8.

Indicating the Date and Time That a WS-Referral Was Sent
<ref xmlns="http://schemas.xmlsoap.org/ws/2001/10/referral">
  <for>
    <prefix>soap://keithba.com/</prefix>
  </for>
  <if>
    <kb:expires
       xmlns:kb="http://keithba.com/RefExtensions">
       10/10/2002T04:01:00PST
    </kb:expires>
  </if>
  <go>
    <via>http://service.keithba.com/Handler/service.ashx</via>
    </go>
  </ref>

One more vague element of this specification is that it allows multiple via elements within the go element. This doesn't require that all specified via elements be used; rather, it merely permits any of them to be used. This is a bit confusing. I find that the best practice is to send only one via.

With the WSE, it's easy to send a referral statement with any message. Here's a small code snippet that returns a referral from the server, such as an ASMX method:

using Microsoft.Web.Services; 
using Microsoft.Web.Services.Referral;
using Microsoft.Web.Services.Routing;

Referral refe = new Referral();
Via v = new Via( new Uri("http://foo/new") );
refe.Go.Add( v );
refe.For.Exact = new Uri( "http://foo/old" );
HttpSoapContext.ResponseContext.Referrals.Add( refe );