Example WSDL Binding for SOAP/TCP

At the recent W3C WSDL WG face-to-face meeting, I offered to write up a
sample binding for SOAP over TCP (SOAP/TCP) to illustrate a binding that
could use output-input (was solicit-response) and/or output-only (was
notify) operations within a WSDL portType. The example only illustrates
the latter, but it would not be difficult to construct a similar example
that illustrated the former.

 

EXAMPLE

 

For example, imagine a hypothetical service that understands a SOAP
version of Internet Relay Chat (IRC). To connect to the service, a
client would use the Connect operation. The client would then use the
JoinChannel operation to join a particular channel. To submit a new
message, the client would use the NewMessage operation, and the service
would push that message out to other clients using the PropagateMessage
operation.

 

When bound to SOAP/TCP, the client would create a TCP connection to the
service, and all messages between the client and service would pass
along that TCP connection.

 

Here's what the WSDL might look like:

 

<?xml version="1.0" encoding="utf-8" ?>

<wsdl:definitions 

  xmlns:wsdl="http://www.w3.org/@@@@/@@/wsdl"

  xmlns:xs="http://www.w3.org/2001/XMLSchema"

  xmlns:stp="http://example.org/2002/10/soap/tcp"

  xmlns:tns="http://example.org/2002/10/soapirc"

  xmlns:xsTns="http://example.org/2002/10/soapirc/types"

  targetNamespace="http://example.org/2002/10/soapirc">

 

<wsdl:types>

  <xs:schema

    targetNamespace="http://example.org/2002/10/soapirc/types">

 

    <xs:element name="Connect" type="xsTns:ConnectType" />

    <xs:complexType name="ConnectType">

      <xs:sequence>

        <xs:element name="name" type="xs:normalizedString" />

        <xs:element name="eMailAddress" type="xs:anyURI" />

        <xs:element name="nickName" type="xs:token" />

        <xs:element name="altNickName" type="xs:token" minOccurs="0" />

      </xs:sequence>

    </xs:complexType>

    <xs:element name="ConnectResponse" type="xsTns:ConnectResponseType"
/>

    <xs:complexType name="ConnectResponseType">

      <xs:sequence>

        <xs:element name="versionNumber" type="xs:string" />

        <xs:element name="MOTD" type="xs:string" />

      </xs:sequence>

    </xs:complexType>

    <!-- Disconnect TODO -->

 

    <xs:element name="JoinChannel" type="xsTns:JoinChannelType" />

    <xs:complexType name="JoinChannelType">

      <xs:sequence>

        <xs:element name="channelName" type="xs:token" />

      </xs:sequence>

    </xs:complexType>

    <xs:element name="JoinChannelResponse"

      type="xsTns:JoinChannelResponseType" />

    <xs:complexType name="JoinChannelResponseType">

      <xs:sequence>

        <xs:element name="topic" type="xs:string" />

        <xs:element name="nickNames" type="xsTns:listOfToken" />

      </xs:sequence>

    </xs:complexType>

    <xs:simpleType name="listOfToken">

      <xs:list itemType="xs:token" />

    </xs:simpleType>

    <!-- LeaveChannel TODO -->

 

    <xs:element name="NewMessage" type="xsTns:MessageType" />

    <xs:element name="PropagateMessage" type="xsTns:MessageType" />

    <xs:complexType name="MessageType">

      <xs:sequence>

        <xs:element name="messageText" type="xs:string" />

      </xs:sequence>

    </xs:complexType>

 

  </xs:schema>

</wsdl:types>

 

<wsdl:message name="Connect">

  <wsdl:part name="Connect" element="xsTns:Connect" />

</wsdl:message>

<wsdl:message name="ConnectResponse">

  <wsdl:part name="ConnectResponse"

    element="xsTns:ConnectResponse" />

</wsdl:message>

<wsdl:message name="JoinChannel">

  <wsdl:part name="JoinChannel"

    element="xsTns:JoinChannel" />

</wsdl:message>

<wsdl:message name="JoinChannelResponse">

  <wsdl:part name="JoinChannelResponse"

    element="xsTns:JoinChannelResponse" />

</wsdl:message>

<wsdl:message name="NewMessage">

  <wsdl:part name="NewMessage"

    element="xsTns:NewMessage" />

</wsdl:message>

<wsdl:message name="PropagateMessage">

  <wsdl:part name="PropagateMessage" 

    element="xsTns:PropagateMessage" />

</wsdl:message>

 

<wsdl:portType name="SoapIrcPortType">

  <wsdl:operation name="Connect">

    <wsdl:input message="tns:Connect" />

    <wsdl:output message="tns:ConnectResponse" />

  </wsdl:operation>

  <wsdl:operation name="JoinChannel">

    <wsdl:input message="tns:JoinChannel" />

    <wsdl:output message="tns:JoinChannelResponse" />

  </wsdl:operation>

  <wsdl:operation name="NewMessage">

    <wsdl:input message="tns:NewMessage" />

  </wsdl:operation>

  <wsdl:operation name="PropagateMessage">

    <wsdl:output message="tns:PropagateMessage" />

  </wsdl:operation>

</wsdl:portType>

 

<wsdl:binding name="SoapIrcBinding"

    type="tns:SoapIrcPortType">

  <stp:binding

    framing="http://example.org/2002/10/soap/tcp/dime" />

</wsdl:binding>

 

<wsdl:service name="SoapIrcService">

  <wsdl:port name="SoapIrcServicePort"

      binding="tns:SoapIrcBinding">

    <stp:address

      location="tcp://example.com:1027/SoapIrc" />

  </wsdl:port>

</wsdl:service>

 

</wsdl:definitions>

 

FRAMING

 

When we send SOAP messages directly over the TCP stream we will probably
want to frame them; adding framing makes it easier to detect the
boundaries between SOAP messages.

 

DIME [1] is a simple, lightweight message format that has been
explicitly limited to provide a few core services needed for
encapsulating messages. To use DIME for framing, the SOAP Envelopes
would be records within a DIME stream.

 

Of course, this proposal is not predicated on DIME and one could use
other framing mechanisms.

 

REPLY TO

 

Operations that begin with an output operation must have been given a
"reply to" address.  For many bindings, such as with the HTTP binding,
the REPLY TO address is implied by the transport and is transparent to
the protocol defined by the WSDL portType. Here we assume the SOAP TCP
binding would use this approach, and the "reply to" address would be the
source IP address of the packet initiating the TCP connection.

 

Note that it would also be possible to define a well-know REPLY-TO
"header" that could be used in place of the transport source address -
this would make the REPLY TO mechanism more general; e.g., it could be
applied to many different WSDL bindings, or it could be used to send
messages from different sources over a single TCP stream.

 

MODEL

 

Messages between a given endpoint and a WSDL port bound to SOAP/TCP
would flow over a TCP connection. Messages for any operation variety
(i.e., input-only, input-output, output-input, output-only) could be
exchanged over such a connection.

 

A WSDL port bound to SOAP/TCP would indicate the address of the WSDL
port. The simplest approach would be to list an IPv4/v6 address and TCP
port number. Alternatively, we could define an appropriate URI scheme
with a default TCP port number; the WSDL port address could be a URI of
that scheme. (The example above shows the second approach.)

 

Either way, if a TCP connection didn't exist between an endpoint and the
WSDL port, the endpoint could open a TCP connection using the location
of the WSDL port.

 

STYLE AND USE

 

For simplicity, assume that the SOAP Body would always be serialized
using a document-oriented style, and that message parts would always
appear as literal SOAP Body blocks (no additional "wrappers"). (I don't
think this assumption is critical to the example.)

 

COMPONENT MODEL

 

A component model for the above would be straightforward, and I'd be
happy to write it up if there is any interest.

 

--Jeff

 

[1] <http://www.ietf.org/internet-drafts/draft-nielsen-dime-02.txt>

Received on Friday, 8 November 2002 21:01:27 UTC