The Day Trader application: an example using output-input operations for classic ("true") pub/sub operations.

This is an example of a "classic" pub/sub application, with sample/proposed
WSDL for illustration.  In keeping with a long-standing WSDL tradition,
we'll describe a stock service.  This one represents a stock trading floor.

First, let's describe trading, pre-electronics.

On a trading floor, all the traders are equals (apart from the fact that
some have more money or more assets, and others have more friends or better
reputations).  When the day starts, someone starts the ball rolling by
bellowing "Sell!  Enron!  Forty!  Ten thousand!" Zero or more traders may
bellow back acceptances, and start elbowing their way toward the offer
(well, in this case, maybe zero or ... zero).  Elsewhere, another trader
bellows "Buy!  MCI!  Ten!  Hundred thousand!", and the shouts of acceptance
are legion as sellers move in to unload.  So it continues until the bell. 
Another day, another billion ... lost (that's okay, we can write it off as
deferred income).

Colorful, but not obviously relevant, right?  Okay, let's make it
electronic.

First, each trader can offer a service: OfferToSell, OfferToBuy.  Each
trader can also respond to a service: AcceptSellOffer, AcceptBuyOffer.  The
deal closes (in the pit) when they get close enough to personally exchange
tokens, although most of the interactions happen broadcast (where
'broadcast' means leather lungs).  The information being exchanged is
straightforward enough, though.

<types>
  <xs:schema>
    <xs:complexType name="tradeType">
      <xs:sequence>
        <xs:element name="traderID" type="xs:anyURI" minOccurs="1" />
        <xs:element name="symbol" type="xs:string" minOccurs="1" />
        <xs:element name="price" type="xs:integer" minOccurs="1" />
        <xs:element name="quantity" type="xs:integer" minOccurs="1" />
      </xs:sequence>
    </xs:complexType>

    <xs:element name="SellOffer" type="tradeType" />
    <xs:element name="SellAccept" type="tradeType" />

    <xs:element name="BuyOffer" type="tradeType" />
    <xs:element name="BuyAccept" type="tradeType" />

    <xs:element name="SellConfirm" type="tradeType" />

    <xs:element name="BuyConfirm" type="tradeType" />
  </xs:schema>
</types>

I'm going to skip over message definitions, in the interest of brevity (and
because they may go away, and because it's clearer if I stick the
information into the operations outright).

<portType name="trader">
  <operation name="Sell">
    <output element="SellOffer" />
    <input element="SellAccept" />
  </operation>
  <operation name="Buy">
    <output element="BuyOffer" />
    </input element="BuyAccept" />
  </operation>
  <operation name="ConfirmSale">
    <output element="SellConfirm" />
    <input element="BuyConfirm" />
  </operation>
  <operation name="ConfirmPurchase">
    <output element="BuyConfirm" />
    <input element="SellConfirm" />
  </operation>
</portType>

A nice, abstract service defined entirely (and controversially, no doubt) in
terms of output-input (solicit-response) operations.  There are two reasons
for choosing this model, rather than calling it request/response.

1) request/response has some *very* clearly understood semantics: two
participants, generally synchronous, service is "always offered."  Since the
daytrader application is classic pub/sub, each participant can equally be
cast as client or as server.  But reusing "request/response," with
*radically* different semantics (service returns multiple responses from
multiple locations, asynchronously, for a limited time only) can only serve
to blur what is now a well-understood problem.

2) Conceptually, the traders are *offering* a service, not making a request. 
It will be easier for folks modelling or reading the description to
understand if the service is described as a service, not as a client. 
Creating perceptual stumbling blocks for service description writers or
readers is not a terribly good idea.

Now, we're going to bind this to IP multicast.  We could just as easily bind
it to TIBCO rv or various competitors, but IP multicast is publically
documented, so will probably be preferred.  Note that we don't need anything
else--no subscription, in particular--because we plan on binding this to a
service that has built-in subscription/administration (which cannot be
modelled in WSDL, as we'll see).

<binding name="DayTrader" type="trader">
  <protocolBinding uri="http://example.org/ip-multicast" />
  <!-- nothing else very interesting; I don't want to do soap:body etc. -->
</binding>

<service name="DayTraderService">
  <port name="DayTraderServicePort" binding="DayTrader">
    <ipmulti:address location="227.17.17.17" />
  </port>
</service>

Still with me?  Let's do some criticism, then.  Since I'm writing and
criticizing, these are likely to be rather straw men, but please do look at
them.

First, from what's in the WSDL one cannot figure out how the trading quite
exactly works.  This is correct.  There's some out of band information that
has to be supplied, either by the protocol binding, or by a higher-level
language (such as BPEL or WSCI).  That information: an offer to buy or offer
to sell attracts zero or more responses.  A confirmation has precisely one
response.  Order is important: an offer to buy, for instance, attracts zero
or more acceptances to buy; when the service decides not to collect any more
acceptances, it initiates a set of (node-to-node, using the traderID to find
an address) confirmations.  The relationship between operations is not
expressed in the WSDL (it can only be expressed in a flow language, I
believe; adding flow to WSDL is just *way* out of scope).  The multiplicity
of respondents is not indicated, except by the identification of the MEP. 
Again, I think it is out of scope for WSDL, per se, to define these things;
they are the province of the MEP and binding specifications.

Second, there's no subscription information!  That's because it's implicit. 
In order to use *this* particular service, each trader must have an
operating system that supports, and is configured for, multicast. 
Configuration of IP multicast subscriptions depends on: a) the state of the
protocol stack in the host subscribing, and b) the state of the nearest
multicast router.  The process of subscription is: change the NIC and
protocol stack to recognize the multicast address as "me" (and you aren't
going to do this with an XML message, in any operating system that I can
think of, even if you could figure out how to express the target address). 
Send an IGMP (this is roughly the same level as IP and ICMP; it isn't going
to suddenly grow an XML syntax) to the nearest router letting it know that I
have another "identity".  Both of these things have to happen.  Change IGMP
to use an XML syntax, and you can send subscription notices *all* *day*
*long* to no effect, if the host protocol stack doesn't recognize the
address as its own.  Subscription, unsubscription, administration are built
into the protocol at a very low level; any processor supporting IP multicast
already knows (from the special IP address) what it has to do, and it
doesn't need (and *can't* use) an XML message to do it.

This, by the way, is not a contrived example.  It is more or less how
trading works, except that it's using SOAP as the envelope format, instead
of custom (lightweight!) stuff.

Now, let's turn a quick corner.  Having gotten all the traders to use our
day trader application, we discover that there are lots of folks out there
who want to join the fun, and LOSE MONEY FAST!  Only they don't have
multicast OSs, or network support staff, or really very many clues at all
(well, day traders ... *shrug*).

They *do* have email.  But we can't do this over email, can we?

Well, sure we can.  First, we have to define subscription and unsubscription
messages.  I'm going to give those a quick pass, but I point out that they
are application level messages.  The application gets to define what they
look like.  There's no particular reason for WSDL to restrict what they look
like.  We'll pretend we've added schema elements named "subscribe" and
"unsubscribe", okay?  I'm using a slightly different style, here, which is a
possible future for allowing multiple MEPs to share the same pattern.  This
allows us to use the classic double-opt-in message exchange pattern for
administration of the mailing list.

<portType name="admin">
  <operation name="subscribe"
    mep="http://www.tibco.com/xmlns/soap/mep/confirmation/">
    <input element="subscribe" />
    <output element="challenge" />
    <input element="confirm" />
  </operation>
  <operation name="unsubscribe"
    mep="http://www.tibco.com/xmlns/soap/mep/confirmation/">
    <input element="unsubscribe" />
    <output element="challenge" />
    <input element="confirm" />
  </operation>
</portType>

<binding name="DayTraderAdmin">
  <protocolBinding uri="http://www.tibco.com/xmlns/soap/dist-email/" />
  <!-- still nothing interesting -->
</binding>

<service name="DayTraderAdminService">
  <port name="DayTraderAdminServicePort" binding="DayTraderAdmin">
    <email:address location="day-traders-admin@example.com" />
  </port>
</service>

And we need to revise the service itself, of course.

<binding name="DayTrader" type="trader">
  <protocolBinding uri="http://www.tibco.com/xmlns/soap/dist-email/" />
  <!-- nothing else very interesting; I don't want to do soap:body etc. -->
</binding>

<service name="DayTraderService">
  <port name="DayTraderServicePort" binding="DayTrader">
    <email:address location="day-traders@example.com" />
  </port>
</service>

And we're done ... at least in WSDL terms.  We're *not* done in terms of
explaining how the subscription relates to the list itself.  But again, it
seems to me that that opens issues of scoping, for WSDL, that ultimately
drive it to be a flow language.  We can define the operations in WSDL.  We
can't define the order of operations.  We can define services in WSDL.  We
can't define how those services are related to one another.

We do define how services are associated with bindings, and how bindings
implement port types.  That's enough, that's our scope, and we can't get
into the question of order of execution, without enlarging scope to Web
Services Description and Process Language.

Amy!
-- 
Amelia A. Lewis
Architect, TIBCO/Extensibility, Inc.
alewis@tibco.com

Received on Tuesday, 12 November 2002 16:00:38 UTC