WSDL Tales From The Trenches, Part 2
June 24, 2003
In a previous article ("WSDL Tales From the Trenches, Part 1"), I painted a big picture of web services design. As I said, Web Services Description Language (WSDL) only defines the syntax of how a web service may be invoked; it says nothing about its semantics. I will observe this distinction in what I say in this article about WSDL.
The version of WSDL being most widely used now, 1.1, is published as a W3C Note. It is not an official standard. WSDL 1.1 offers a lot of latitude for invoking web services. Tool support tends to be patchy. WSDL gets a lot of bad press because it got the trade-off wrong between expressivity and flexibility on the one hand and verbosity and complexity on the other. Before we proceed, I will come clean and tell you that I am at a loss to tell you how to write truly clear, crisp WSDL.
Tools
Before getting into details, let's consider the possible tool support you may be able to rely on. First, it helps to use an XML-aware editor when you write WSDL, preferably one with the capability to validate the WSDL document. When retrofitting WSDL to existing web services, I find it very useful to be able to generate, send, and receive messages from the editor; XML Spy from Altova does this for web services with SOAP over HTTP bindings. This makes it practical to develop, test, and debug WSDL interactively. Unfortunately, XML Spy does not provide this capability for other bindings. A useful feature that seems to be missing in today's tools is the ability to validate a server's response against a web service description (hereafter, "WSD").
Modular web service descriptions
Using the import
keyword, you can separate a WSD into modular documents. An
example in the W3C Note uses three documents, which contain, respectively, data type
definitions, abstract definitions, and specific service bindings. The specific or
concrete
service definitions depend on the abstract service definitions, which in turn depend
on the
data type definitions.
Apart from improving readability, this technique also improves opportunities for certain types of extension and reuse: the same data type definitions can be used across many abstract services, and the same abstract services can be offered through many different bindings, at many addresses.
Initially, a set of web services may be represented as a set of three documents. As services grow, however, this may evolve into a tree of documents with the data type definitions at its root, branching into several abstract services documents, and further fanning out to concrete services.
portType
s are collections of semantically related operations, much as an
interface in a programming language. A binding
does not have to cover all
operation
s of a given portType
. For example, the respective
operation
s may use different transfer protocols. Since a service
is a set of port
s and a port
refers to a single
binding
, it is possible to specify services that do not offer all the
operation
s defined in a portType
. However, the presence of such
service
s is indicative of badly factored portType
s.
A single service may be composed of many interfaces, each representing a different aspect of the service. For example, a service may have a port for its business logic and another port for accessing its management features.
Namespaces
WSDs, once agreed upon, should be frozen. WSDL 1.1 makes the use of target namespaces optional. It is convenient, however, to assign a namespace to identify services and their versions unambiguously, as has become the common practice with standards specifications. The downside is that WSDL 1.1 is not very clear about what is meant by the target namespace. In other words, what precisely is being put into it? I suspect that the same rules were meant to apply as with W3C XML Schema.
Here's a quick recap of the rules in W3C XML Schema: what is put into the target namespace
is governed by the form
attribute on the element
and
attribute
elements. In the absence of such attribute, the defaults set at the
level of the root schema
element through the elementFormDefault
and attributeFormDefault
attributes come into play. In the absence of an
explicit default, the implicit default applies: only globally defined elements go
into the
namespace.
What are the repercussions of these Schema rules on WSDL? First, WSDL does not deal
with
element
s and attribute
. Second, the top level elements in WSDL
are message
s, portType
s, binding
s, and
service
s, which are the entities that will be put into the target namespace.
types
is obviously not relevant here. Third, while in theory Schema's
form
attribute could be used with any of the elements defined in WSDL, this
is not common practice. Fourth, similarly, Schema's elementFormDefault
and
attributeFormDefault
attributes could be used on the definitions
element, but I have not seen it done.
Thus, we can say that all message
s, portType
s,
binding
s and service
s go into the target namespace, and their
children do not.
Is this rule useful? Does it matter? It does when messages are encoded
in such
a way that, except for this rule, the WSD namespace could "leak" into messages. Indeed,
it
took me some time to figure out that the namespaces I was seeing in encoded SOAP messages
were not due to the WSD namespace because of the common, but confusing practice of
using the same namespace as input for SOAP encoding. A corollary of our namespace
rule is
that a message's elements and attributes are not in the WSD's namespace, unless
they are put there by the SOAP encoding namespace.
If a WSD is modularized in the way I suggested before, a namespace should be assigned
to
each document. WSDs should not import
definitions with the same namespace. The
WSDL specification does not state this rule explicitly, but again, I suspect Schema's
import
was the inspiration for WSDL's element of the same name and that the
same rules were intended. Schema does not allow an importing and imported schema to
share a
namespace. This is a very useful rule in my view since a namespace is difficult to
reason
about if you cannot rely on the fact that the definition is complete.
Error handling
Perhaps the single most important difference between a demo and a production-quality service is the quality of the error handling. Yet the literature pays little attention to this topic.
Defining separate messages in order to distinguish between error conditions can be convenient; the structure of such messages may vary according to the error condition that occurred. This listing specifies a web services that will raise the hackles of any system administrator: it runs a binary supplied by the caller. I apologize to readers that are looking for examples of good use of namespaces and modularization, as this will not do. The example focuses on error handling. Two errors have been foreseen in the design: first, there may not be enough memory, in which case the allocated heap space and the amount of memory in use is returned; second, the program may attempt to dereference a null pointer, in which case a stack trace is returned.
The fault message types are derivations of an abstract type. The motivation for the abstract type comes from mapping the faults to an inheritance hierarchy in one or more programming language. So this revised listing is a more compact WSD. The differences between the sets of (fault) messages that are valid according to the respective documents are minute.
The intent, however, is a lot clearer with the former document; client implementors
working
with the latter document will likely surmise that an OutOfMemoryException
may
be returned. But it is not clear from the specification that this is the intention.
Neither
can client implementors feel confident that their code covers all fault conditions
since the
abstract tException
type may have been extended by types other than the ones
listed in the latter document.
I have seen hybrid approaches, ones where the supertype is not declared abstract. In this universe, fault messages may be specified in the WSD to be of a derived type, sometimes the supertype is specified. This creates even greater uncertainty regarding the exact format that will be received by the client; hence, I do not recommend it.
document/literal
versus rpc/encoded
The accepted wisdom is to use literal wire format with document invocation style and encoded with RPC invocations. There are no fundamental reasons for this restriction; it is rather a historical coincidence that tools tend to support (one of) these combinations.
The trade off is between the complexity of the programming model and the complexity
of
message marshalling. RPC offers a comfortable programming model. It is not without
its
dangers, as I pointed out in the previous article. However, it is also important to
be aware
of the obligations that the wire formats used with RPC impose on marshalers: the distinction
between literal
and encoded
is between writer and reader makes
right, respectively. This means that the latter wire format may have many different
representations for semantically equivalent messages.
The classic example is SOAP's encoding support for both independent and embedded elements. It is up to the receiver to understand all representations. I already indicated the importance of nailing down the format of the messages as much as possible in the previous section. The reason for this is that reader-makes-right comes at a cost. This may not matter in environments where sophisticated tools are available to generate client stubs, but working with heterogeneous platforms, this is by no means always the case.
The shape of things to come
As mentioned previously, WSDL 1.1 does not carry the weight of a standard. Yet the specification has been widely used, often frustrating hopes for interoperability. Thus the motivation for WS-I entering the fray; not to take ownership of the WSDL standard, but to define profiles "consisting of a set of non-proprietary Web services specifications, along with clarifications and amendments to those specifications which promote interoperability".
I cannot help feeling irritated at having to keep yet another organization dealing with standards on the radar. Despite its declared aim, I fear that initiatives such as WS-I will lead to the balkanization of standards. Nonetheless, I would recommend reading section 5 of the Basic Profile Approval Draft, which does a pretty good job of clarifying some of the darker recesses of WSDL 1.1. And yet I do not like the fact that they focus all their attention on SOAP.
In the previous installment I also briefly discussed the OASIS WSS TC, which seems to be taking the lead in the definition of web services security standards. Yet another body bringing a much-needed piece of the puzzle. But are the pieces going to fit, and who is going to be putting them all together?
Ownership of future versions of WSDL seems to firmly rest with the W3C where a Web Service Description Working Group has WSDL 1.2 in the making. According to its charter, the release for the new specification is planned for May 2003. That target is clearly going to be missed. Nevertheless, the shape of things to come is emerging in the drafts they occasionally publish. So what is likely to happen to the anomalies we covered above?
The draft available at the time of writing seems to confirm the interpretation of
what ends
up in the target namespace of a WSD. It says that the "targetNamespace
attribute information item defines the namespace affiliation of top-level
components defined in this definitions
element information item. Messages, port types, bindings and services are top level
components." Whether WSDL 1.2 will support implementing several interfaces in a single
service is hotly
debated right now. The WSDL 1.2 draft states explicitly that the same rules against
sharing namespaces with imported documents apply as in XML Schema. On the other hand,
an
alternative mechanism for modularizing descriptions is provided via an include
element modeled on XML Schema's include
element that does allow sharing of
namespaces.
Acknowledgments
XML Spy is a registered trademark of Altova GmbH. To Caroline Greenman, thanks for comments, as always.
Resources
Here are some resources that give good advice on writing WSDL:
- Yaron's (not so) Quick and (really) Dirty Guide to WSDL;
- Web Services Description Language (WSDL) Explained;
- Common WSDL Errors.
For the diehards, it is of course essential to read the W3C WSDL 1.1 Note. I would recommend section 5 of Basic Profile Approval Draft too as it clarifies many points in WSDL 1.1. The Web Service Description Working Group are in the process of writing the WSDL 1.2 specification. From time to time a draft is published.