Web Services, Part 2: WSDL and WADL
Part 1 of this series talks about SOAP vs. REST. In this installment I'll discuss the reasons for defining the web service contract between client and server, the existing methods for doing it, and the important concepts of each.
Defining the Contract
An important part of any web service is the contract (or interface) which it defines between the service and any clients that might use it. This is important for a number of reasons: visualization with tools, interaction with other specifications (e.g., web service choreography), code generation, and enforcing a high-level agreement between the client and service provided (that still gives the service freedom to change the underlying implementation). Taken together, they give pretty compelling use cases for having web services contracts, although advocates of minimalism may disagree.
When IBM, Microsoft, and Ariba submitted WSDL 1.1 to the W3C in 2001 as a language for describing web services in conjunction with SOAP 1.1, HTTP POST and GET, and MIME, it quickly became a standard used by every SOAP toolkit. This happened in spite of the fact that it never progressed beyond being a W3C Note (which, according to W3C, is a document available for "discussion" and not officially endorsed by the W3C). In fact, though there is both a WSDL 1.1 and 1.2, WSDL 2.0 is the only version of the specification officially endorsed by the W3C.
With the rise in popularity of RESTful web services, there also became a need to describe contracts for these types of web services as well. Although WSDL 2.0 attempts to fill the gap by providing support for HTTP binding, another specification fills this need in an arguably better way: WADL , a specification developed at Sun by Marc Hadley. Though it has not been submitted to any official standards body (OASIS, W3C, etc.), WADL is promising because of its more comprehensive support for REST-style services.
In general there are two different approaches to development of web services in the real world: code-first or contract-first. Code-first is where existing code (generally methods/functions) is turned into a web service using tooling, e.g. the
java2wsdl script in Apache Axis. Contract-first is where the actual web services contract is developed first (usually in WSDL), then this is then associated with the appropriate implementation--often using code generation with a tool such as the
wsdl2java script in Apache Axis.
Though code-first is a highly popular approach, contract-first is generally considered to be best practice in order to shield the consumers of a service from changes in the underlying code base. By providing an XML-based contract, you are also protecting the client from the vagaries of how different Web Service toolkits generate contracts from code, differences in the way that language types are translated to XML types, etc. Though writing WSDL or WADL rather than code may involve some additional learning curve at the beginning, it pays off in the long run with more robustly designed services.
An official W3C standard, the Web Services Description Language (WSDL) is an XML language for describing web services. WSDL 1.1 (which is still in wide use) has five major elements--
service--in that order (figure 1 below); all these major elements may be defined 0 or more times in a WSDL document, except for
<types>, which may be 0 or 1 time. Here's a short description of each:
<types>: This is where XML types to be used in the WSDL document are defined. Traditionally, this has meant using XML Schema, but newer versions of WSDL also support Relax NG.
<message>: This is the section where the input or output parts of an operation are defined, i.e. the "parameters" or "return types". It may have multiple child
<part>elements, though WS-I forbids the use of more than one part per message in a document literal style service. The <part> itself may have an element (referring to a qualified XML element) or a type (referring to an XML Schema type) attribute; the later is use in RPC/encoded style services, the former in RPC/literal or Document/literal style services (see WSDL Styles).
<portType>: Here is where the operations that a web service offers are defined in terms of messages (input and output, with faults). Faults (referring to SOAP faults here) are the web service equivalent of the exception in languages like C++ or Java; most SOAP toolkits will translate SOAP faults into exceptions at runtime.
<binding>: This is the "how" of a service, specifying the binding of the operations defined in the portType(s) to specific protocols, such as SOAP.
<service>: This is the "where" of the service, specifying the address where a bound operation may be found.
These sections do not necessarily have to reside in the same XML document. In fact, it is common for there to be at least two different WSDL files, where one imports the other (see Abstract and Concrete WSDLs).
<definitions> <types>? <!-- Defines the XML types used in the WSDL --> </types> <message>* <part element="..." or type="..."/>* </message> <portType>* <!-- Defines the web service "methods" --> <operation>* <input message="..."/>? <output message="..."/>? <fault message="..."/>* </operation> </portType> <binding>* <operation> <!-- Binding of the operation to a protocol, e.g. SOAP --> </operation> </binding> <service>* <port name="..." binding="..."> <!-- Specifies the address of a service, e.g., with soap:address --> </port> </service> </definitions>
Figure 1: Major elements of WSDL 1.1. (1)
At first blush, having all these different parts of WSDL seems a bit overly complex--after all, do you really need to define both a part (message) for an operation as well as an operation separately (this was my first reaction...)? Well, WSDL 1.1 was created to be highly decoupled, and to maximize reuse of every possible piece; for example, one can define a message that can be used both as an input or an output, or can be used by multiple port type operations. The end result of this structure, however, was a bit unnecessary and hard to read, so the authors of the WSDL 2.0 improved this by removing the
<message> section, and using defined elements instead.
WSDL underwent a major renovation in version 2.0, changing the root tag to
<description>, and ushering in many other changes and additions. I've already covered much of the structure in WSDL 1.1, so here I will describe mainly the differences:
<interface>: As the name implies, this section tends to resemble interfaces in Java, which makes sense since they serve very similar purposes. Like interfaces, they can define multiple operation "signatures" and can be extended for reusability. The
<portType>of WSDL 1.1, and adds explicit input faults and output faults. The child
<operation>elements here can also explicitly define message-exchange patterns in their
patternattribute (see below).
<binding>: This element has children that are identical to those of the interface, so that a binding can be specified for each. The major difference over version 1.1 is that bindings are re-usable. To be re-usable the binding simply omits the
interfaceattribute; it may be specified later in the service declaration.
<port>are replaced by similar
WSDL 2.0 also defines an explicit HTTP binding to all the methods: GET, POST, PUT, and DELETE. This becomes important for RESTful style web services. In essence, though, WSDL is service rather than resource oriented, so the fit with RESTful services is not as natural as it is in WADL.
<description> <types>? <!-- Defines the XML types used in the WSDL, as in 1.1 --> </types> <interface name="..." extends="...">* <fault element="..."/>* <operation pattern="..message pattern uri..">* <input element="..."/>* <output element="..."/>* <infault ref="..some fault..."/>* <outfault ref="..some fault"/>* </operation> </interface> <binding interface="..."?> <!-- The binding of a protocol to an interface, same structure as the interface element --> </binding> <service interface="..."> <!-- Defines the actual addresses of the bindings, as in 1.1, but now "ports" are called "endpoints" --> <endpoint binding="..." address="..."/>* </service> </description>
Figure 2: Major elements of WSDL 2.0. (1)
This developerWorks article does a great job of explaining the different styles of WSDL, so I will only summarize briefly here.
In general, an RPC (or "remote procedure call") style service will define the references in its message parts as XML Schema types; a Document style service will define element references on its message parts (the
soap:binding will use the appropriate
style attribute). An Encoded style will encode the types of the children of the
soap:body in the SOAP message; a literal style will not encode them, but leave them as literal XML elements (the binding of input and output messages will have the appropriate
RPC vs. Document (where "ns:myElement" is a reference to a defined element) WSDL definitions
<!-- RPC request message --> <message name="input"> <part name="param" type="xsd:int"/> </message> <!-- Document request message --> <message name="input"> <part name="param" element="ns:myElement"/> </message>
Encoded Vs. Literal SOAP Messages
<!-- Encoded SOAP request --> <soap:body> <param xsi:type="xsd:int">1</param> <soap:body> <!-- Literal SOAP request --> <soap:body> <param>1<param> <soap:body>
There are, generally speaking, four distinct styles of WSDL: RPC/Encoded, RPC/Literal, Document/Literal, and Document/Literal Wrapped. As explained in Part 1, RPC/Encoded, once ubiquitous, is now pretty much dead: unless you have to interact with a legacy web service, use something else. Of the remaining styles, RPC/Literal has the drawback that you cannot really validate the types in the SOAP message. With Document/Literal, you can validate the types but you lose the name of the operation in the SOAP. This is where the Document/Literal Wrapped style comes in handy: it "wraps" the body of the document payload in an element that represents the operation name (it also has the additional benefit of enforcing only one child of
soap:body as mandated by WS-I). The only real drawback of Document/Literal Wrapped is that you cannot "overload" web service operation names, but this is a minor quibble. Generally speaking, using this style of WSDL is your best bet, unless your SOAP toolkit is unable to work with it.
Message Exchange Patterns
Message exchange patterns are the "handshake protocol" of web services. They let a client know what type (in/out) of messages or faults must be exchanged, and in what order.
WSDL 1.1 defined 4 basic message exchange patterns:
- One-way: An operation only receives an
- Request-response: An operation receives a request, then issues a response. Here the
<operation>is defined before the
- Solicit-response: An operation sends a request, then waits for a response. Here the
<output>would be defined before the
- Notification: An operation sends a message only.
Using the document ordering of elements to establish the message exchange pattern was obviously a little too subtle, so WSDL 2.0 uses an explicit
pattern attribute to define it. WSDL 2.0 also expands the number to 8 message exchange patterns, which can be categorized as inbound MEP (if the service receives the first message) or outbound MEP (if the service sends the first message):
- In-only: Here a service operation only receives an inbound message, but does not reply. This MEP cannot use a fault. When referred to by an operation's pattern attribute, it has the value "http://www.w3.org/ns/wsdl/in-only".
- Robust In-only: Identical to In-only, except that this type of MEP can trigger a fault. When referred to by an operation's pattern attribute, it has the value "http://www.w3.org/ns/wsdl/robust-in-only".
- In-Out: Identical to the request-response of WSDL 1.1. A fault here replaces the out message. When referred to by an operation's pattern attribute, it has the value "http://www.w3.org/ns/wsdl/in-out".
- In-Optional Out: Similar to In-Out, except that the out message is optional. When referred to by an operation's pattern attribute, it has the value "http://www.w3.org/ns/wsdl/in-opt-out".
- Out-Only: The service operation produces an out-only message, and cannot trigger a fault. When referred to by an operation's pattern attribute, it has the value "http://www.w3.org/ns/wsdl/out-only".
- Robust Out-Only: Similar to Out-Only, except that this type of MEP can trigger a fault. When referred to by an operation's pattern attribute, it has the value "http://www.w3.org/ns/wsdl/robust-out-only".
- Out-Optional In: The service produces an out message first, which may optionally be followed by an inbound response. When referred to by an operation's pattern attribute, it has the value "http://www.w3.org/ns/wsdl/out-opt-in".
A WSDL document can be divided into "abstract" and "concrete" portions that by convention often are defined in two or more files (where the concrete file imports the abstract one). The abstract elements are
<interface> in 2.0); the concrete ones are
<service>. Separating these two sections allows for maximal reuse and flexibility in defining services.
A great illustration of this principle is with WS-RP (Web Services for Remote Portlets), a specification essentially for exchanging portlet content between different servers (e.g., a Java application server and, say, Microsoft Sharepoint). WS-RP defines in its specifications all of the types and operations that will be used in the web service of the "producer". The producer server only has to specify the actual concrete WSDL.
WADL, or Web Application Description Language, is a specification developed to be an alternative to WSDL with specific support for RESTful web services. Whether or not WADL will be widely adopted is still an open question--certainly it would help if it were submitted to a standards body--but it is interesting nevertheless to present it in contrast with WSDL. Here, instead of providing a more comprehensive overview (the 11/09/2006 specification is very easy to read), I'll provide an example to give a flavor of how it works in the form of the ever-popular stock quote example (Figure 3 below). Notice how it defines both resources and representations, as well as the methods that can be used to manipulate the resources.
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://research.sun.com/wadl/2006/10 wadl.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ex="http://www.example.org/types" xmlns="http://research.sun.com/wadl/2006/10"> <grammars> <include href="ticker.xsd"/> </grammars> <resources base="http://www.example.org/services/"> <resource path="getStockQuote"> <method name="GET"> <request> <param name="symbol" style="query" type="xsd:string"/> </request> <response> <representation mediaType="application/xml" element="ex:quoteResponse"/> <fault status="400" mediaType="application/xml" element="ex:error"/> </response> </method> </resource> </resources> </application>
Figure 3: A WADL example.
WADL does a nice job of capturing the style of REST. As with any other technology, though, most will wait to use it until it sees some significant adoption.
This has certainly been a whirlwind tour of WSDL and WADL. We've covered some of the most important points here in a fairly concise fashion, but there is quite a lot which can be said about the subject. I encourage anyone who wants to dive deeper to look at the References below.
Next in this series I will examine developing web services in Java.
(1) I've adopted the cardinality convention of using "?" to denote 0 or 1, "*" to denote 0 or more, and "+" to denote 1 or more (a short-hand for the XML Schema-defined constraints)
The WSDL 1.1 Specification
The WSDL 2.0 Specification: Primer, Core, and Adjuncts
The WADL Specification (11/2006)
Which style of WSDL should I use?, IBM developerWorks
Understanding WSDL, MSDN
What's New in WSDL 2.0, XML.com
Introducing WADL, Marc Hadley's Blog