A Busy Developer's Guide to WSDL 1.1, Part III
By Sam Ruby, December 17, 2002.
Part I and Part
II of this document described how to document first untyped,
then typed remote procedure calls using WSDL. This third part documents
another style of interaction - exchange of well formed and valid
documents. For further insight into this perspective about how one should
develop distributed applications, see Sean McGrapth's API's
Considered Harmful essay.
Overview

SOAP doesn't pick sides in the API vs document debate. If you want to
do simple RPC, then peace be with you. If you want to simply exchange
documents, then peace be with you too.
The purpose of this document (i.e, Part III) is to describe how WSDL
can be used to describe the latter types of exchanges.
Like Part I of this document, the style will be one of progressive
disclosure. However, in this case, we will start "from the other
end" by describing the service and working our way towards the document
description. This not only provides a little variety, it allows the
discussion to start with the concepts that are familiar and then work towards
the parts of the description where the concepts are different than those found
in RPC encoded interfaces.
The example used throughout this document is based closely on the RESTLog
interface which creates a new news item. There are two differences that
will be introduced in the process: the RSS items will be placed into a proper
namespace, and the document itself will be placed inside a SOAP envelope in
accordance with the SOAP 1.1 specifications.
Declaring the service

There is no difference at the service level, so people who have
read Part I will find this part very familiar.
<service name="RESTLog">
<port name="RESTLogSoap" binding="restlog:soap">
<soap:address location="http://localhost/RESTLog.asmx" />
</port>
</service>
I prototyped the server side using ASP.Net, and the XML above soap:address
location reflects
that. Later we will see how this information can be changed dynamically at
runtime to point to the resource.
Binding this port to SOAP
Here we will see the first substantive differences.
<binding name="soap" type="restlog:RESTLogSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<operation name="createNews">
<soap:operation soapAction="" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
Instead of rpc, you will see document. Instead of
encoded, you will see literal. This reflects the
difference in usage. It is worth mentioning at this point that this
essentially is a difference in perspective or how you chose to document an
interface. As all RPC calls in SOAP are expressed in terms of XML, it is
generally possible to document the literal XML directly. The reverse is
not always true, as XML elements documents can have attributes.
Defining the messages.

A document exchange can be loosely defined as "if I send you a document
that looks like this, I can either expect to receive a document that
looks that, or a fault." This portion of the WSDL simply
defines the two messages.
<message name="createNewsIn">
<part name="item" element="rss:item" />
</message>
<message name="createNewsOut">
<part name="createNewsResult" element="restlog:createNewsResult" />
</message>
<portType name="RESTLogSoap">
<operation name="createNews">
<input message="restlog:createNewsIn" />
<output message="restlog:createNewsOut" />
</operation>
</portType>
In RPC style descriptions of Web Services, the message element plays a much
greater role, as a message can contain many typed parts, each corresponding to a
parameter. In document style descriptions of Web Services, a message
typically is described as a single XML element.
Defining the schema.

This is the part that can almost be thought of as an afterthought when
defining an RPC style service, but is the core of a document literal
definition. Since this essay is for educational purposes, I'm not going to document the full Dublin Core or RSS specs in
XML Schema here, just enough to get the job done.
<types>
<xsd:schema targetNamespace="http://purl.org/dc/elements/1.1/">
<xsd:element name="date" type="xsd:dateTime"/>
</xsd:schema>
<xsd:schema targetNamespace="http://backend.userland.com/rss2">
<xsd:element name="item" type="rss:Item" />
<xsd:complexType name="Item">
<xsd:sequence>
<xsd:element name="title" type="xsd:string" />
<xsd:element name="description" type="xsd:string" />
<xsd:element name="link" type="xsd:anyURI" />
<xsd:element ref="dc:date" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
<xsd:schema targetNamespace="http://wellformedweb.org/RESTLog.cgi/5">
<xsd:element name="createNewsResult" type="xsd:int" />
</xsd:schema>
</types>
As you can see, the first schema is extremely simple. It defines a single element,
named date.
In the second shema, the element is defined in terms of a type. Don't
let the name "complexType" fool you, in this case all that is being defined a
simple sequence of elements. I could have made this a repeating choice, or
gotten really fancy, but I'm intentionally keeping this simple. Also note
that a reference is made to the date element from the Dublin Core
namespace.
I've also defined a schema for the returned value. This part I've
entirely made up as it was not clear to me at least from the existing RESTLog
documentation what
a successful request will return. Needless to say, such documentation of
not only the successful results but also what can be expected upon failure is
important.
Accessing this Web Service from .NET
The first thing to do is to use the wsdl.exe
tool to produce a proxy class from this
WSDL. Compile the generated C#
code along with the following test program:
public class test {
public static void Main(string[] args) {
RESTLog wfw = new RESTLog();
wfw.Url = "http://www.wellformedweb.org/";
Item item = new Item();
item.title="My Summer Vacation";
item.date=System.DateTime.Now;
item.link="http://127.0.0.1/cgi-bin/RESTLog.py/4";
item.description = @"
On my summer vacation I went to...
<a href=""http://www.myrtlebeachonline.com/mld/myrtlebeachonline/"">
Myrtle Beach
</a>.
<br>I got a <b><i>really</b></i> nasty sunburn.
";
int itemID = wfw.createNews(item);
}
}
Now, a few comments on this program. First, note that there is no hint or
mention of XML to be found. I create a RESTLog. I create an
Item. I fill in a few values. Then I instruct the RESTLog to
createNews with the item. The names of the classes and properties are
taken directly from the service and schema. Furthermore, all marshalling
of data is taken care of for you automatically - e.g., dates and integers.
String are automatically XML encoded so even ill-formed HTML can be passed in
well formed XML.
The results are not only well formed XML, but valid with respect to the
schema and service definition. Always.
This example was C#. But it could have just as easily been Java,
VisualBasic, JScript, Perl, or any other language for which there is a toolkit
that understands WSDL document literal definitions.
Conclusion

If you compare the amount of code it takes to directly invoke a SOAP web
service without the benefit of a WSDL description and the amount of code it
takes to produce and traverse and arbitrary XML document, the difference is
significant. Even more importantly, developers can immediately program
using native data types with the necessary conversions taking place
transparently.
Commentary

The goal here is to drive integration costs to as close to zero as is humanly
possible.
At the moment, the norm is for somebody to define an interchange format and
evangelize it. Then a set of very smart people undertake to build
individual bindings to each programming language. Only then is the
application accessible to a wide range of developers.
The alternative that WSDL provides is that there can be a single definition
of an interface. One that you can author in notepad, create by filling in
a form in a Wizard, or reverse engineer from an existing implementation.
This single definition can then be used to generate - either statically or
dynamically - the necessary set of infrastructure to enable seamless integration
across programming environments.
None of this is done at the expense of the Web Monkeys like me who often like
to produce their XML with printfs, and scan it with regex'es. Such
implementations will interoperate too.
|
|
© Copyright
2002
Sam Ruby
.
Last update:
9/1/2002; 6:53:32 PM
.
This theme is based on the SoundWaves
(blue) Manila theme. |
|