A Busy Developers Guide to WSDL 1.1
By Sam Ruby, February 15, 2002.
This document demonstrates how the process of achieving meaningful
interoperation between different environments can be achieved in a simpler and less error prone
manner by applying some of the basic concepts described in WSDL
1.1 . The DIY Web Services Tutorial
will be used as an example throughout this document. A basic
understanding of the current
mechanisms used to invoke web services from various environments is
presumed. Familiarity with SCNS
and WSDL
FM would be helpful. Knowledge of the underlying SOAP
1.1 protocol is not a requirement.
Part II of this document covers adding type information.
Part III of this document covers document literal web services.
Overview

When picking apart a SOAP
message or a WSDL
document, it is not hard to see how you can extract the information that is
relevant to you and ignore the rest. But somehow this process doesn't seem
reversible. The truth is quite the opposite: once you realize that you are
simply describing a message that you would accept, and not saying anything
about what other messages you might also accept. A concrete example
may help illustrate the point here. Imagine an environment where operations are not case sensitive. As
there is no requirement to enumerate all the permutations you can accept, simply
name one you would accept. Similarly, if your environment does not access
objects based on the namespace of the body element, you need only identify
one namespace that you would accept, which in this case would be pretty much anything,
actually. So by filling in every blank with answers you do know, and
providing reasonable defaults for the rest, you can provide clients all the
information they need to access your web service.
The next few sections of this document document will construct a working WSDL
document in chunks and use the <import>
facility to link the pieces together. Then the actual code which makes use
of this document will be presented.
Declaring the portType

A port is simply a collection of operations.
Many programming languages refer to this as a library, a module, or a
class. But this is the world of messaging, so the connection points are
called ports, and an abstract definition of a port is called a port type.
In this case, we are looking at an abstract definition of the helloWorld
procedure. Here's how this would be defined in WSDL:
<?xml version="1.0" encoding="utf-8"?>
<definitions
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:tns="uri:diy" targetNamespace="uri:diy"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types/>
<message name="helloWorldRequest">
<part name="name" type="s:anyType"/>
</message>
<message name="helloWorldResponse">
<part name="helloWorldResult" type="s:anyType"/>
</message>
<portType name="tutorialPort">
<operation name="helloWorld">
<input message="tns:helloWorldRequest"/>
<output message="tns:helloWorldResponse"/>
</operation>
</portType>
</definitions>
In plain English, we are defining the helloWorld operation for the tutorial
port in the uri:diy namespace. This operation has an input
message called a request and output message called a response.
Each of these messages consist of a single part which can be of any type.
While I don't recommend typeless interfaces in general (more on this in a
future essay),
I do so here both to show that it can be done and to keep this example
simple. Note also the empty <types/> element. This is where
additional types would be defined.
At this point, one might wonder why messages are broken out to this level of granularity. The reason for this is that in a larger system you might want
to reuse messages with the output of one operation being the input to the next.
Binding this port to SOAP
PortTypes are protocol independent. While the there are many choices
for protocols, for the purpose of this document we are going to pick one: RPC style SOAP requests over HTTP with
SOAP encoding. OK, now that I have named the protocol in words, lets see
how this is expressed in WSDL:
<?xml version="1.0" encoding="utf-8"?>
<definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="uri:diy" targetNamespace="uri:diy"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<import namespace="uri:diy" location="porttype.wsdl"/>
<binding name="tutorialSoap" type="tns:tutorialPort">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="helloWorld">
<soap:operation soapAction="/radio" style="rpc"/>
<input>
<soap:body use="encoded" namespace="uri:tutorial"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="uri:tutorial"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
</definitions>
The first thing this definition does is to import the previously defined
portType. Then it defines a SOAP binding using an http
transport using the rpc style. The helloWorld
operation is further qualified to contain a soapAction, and the
bodies of both the input and output messages are defined with the appropriate
encoding and namespace. Again, if your implementation doesn't particularly
care about namespaces (it need not, after all), then simply provide some
reasonable and meaningful default.
While this may seem like a lot of work, realize that this is exactly the same
information that you needed to provide on a call to soap.rpc.client.
Finally note that this definition provides much more flexibility than you may
need. For example, you might not envision a need for specifying different
encodings for input and output messages. That's OK, for now, simply focus
on defining what messages you will accept and will produce.
Defining the service.
 Again, we start by importing the work done so far.
Then a service is defined with a single instance of a the abstract tutorialPort
type which is bound to the tutorialSOAP binding. Finally, the
information on the actual endpoint URL is provided. The result follows:
<?xml version="1.0" encoding="utf-8"?>
<definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="uri:diy" targetNamespace="uri:diy"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<import namespace="uri:diy" location="binding.wsdl"/>
<service name="tutorial">
<document>
For a complete description of this service, go to the following URL:
<a href="http://radio.userland.com/webServicesTutorial">http://radio.userland.com/webServicesTutorial</a>
</document>
<port name="tutorialPort" binding="tns:tutorialSoap">
<soap:address location="http://127.0.0.1:5335/"/>
</port>
</service>
</definitions>
Also note the document that was added. Truth be told, this should
have been done every step of the way. But in any case, the WSDL is at this
point complete. Now lets see this in action.
Accessing this Web Service from Apache Axis
The first thing to do is to use the WSDL2Java
tool to produce Java classes from this WSDL. Compile the generated
Java classes along with the following test program:
import diy.*;
public class Test {
public static void main(String[] args) throws Exception {
TutorialPort tutorial = new TutorialLocator().getTutorialPort();
System.out.println(tutorial.helloWorld(args[0]));
}
}
Now invoke the result using
java Test Dave
And Murphy willing (and presuming that you successfully installed and got
working the DIY tutorial
web service), the result will be:
Hello Dave!
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 invoke the same service based on a WSDL definition, the differences are
dramatic. The reason is simple: administrative details such as parameter
names and soap action are taken care of for you. Furthermore when you
consider that this same definition can be used to make life easier (modulo the
upcoming interoperability
effort) - not only for Radio and Axis users, but also for users of many others
implementations such as SOAP::Lite,
PHP, or
even the .Net
framework - the case for a standard, interoperable, web services description
language is fairly compelling.
Commentary

Most importantly, treat any WSDL you define (either programmatically or
manually) as a starting point. Others may wish to refine it or provide
alternate values for ones that you defaulted or to
add type information. This is natural,
particularly if you are defining a WebService that can be implemented in many
different environments. More helpful advice can be found here.
And a good source for additional information on what can be done with a WSDL can
be found here.
|
|
© Copyright
2002
Sam Ruby
.
Last update:
9/1/2002; 6:53:32 PM
.
This theme is based on the SoundWaves
(blue) Manila theme. |
|