
Abstract: Even if you are perfectly content working with the well-established WSDL 1.1 standard, it is worth taking the time to know just how and why certain features and language elements have changed and expanded with WSDL 2.0. In this article we start focusing on the differences between WSDL 1.1 and 2.0 and then move on to assembling an entire WSDL 2.0 document. Note that this article is not an introduction to the Web Services Description Language. If you are new to WSDL then be sure to read up on basic WSDL 1.1 elements before proceeding.


Introduction

As shown in Figure, the WSDL 2.0 language introduces some noticeable differences
to the document structure of a WSDL definition, namely:
|
•
|
The definitions element is renamed to description.
|
|
•
|
The portType element is renamed to interface.
|
|
•
|
The port element is renamed to endpoint.
|
Additionally, the message element is removed, as explained in the next section.

|
Figure 1: WSDL 2.0 inherits its overall structure from WSDL 1.1, but does make some changes to both abstract and concrete
descriptions.
|

Elimination of the message Element

The WSDL 1.1 message element was mainly intended to serve as the bridge between
message- and RPC-centric communication. It can
be used to describe a document type message based on just one part element, or it can
support RPC type (parameter-driven) messages based on multiple parts. However, its
expressive power for RPC is limited. For example, it cannot describe a variable number
of input parameters or a choice of responses. WSDL 2.0 addresses this industry shift by
removing support for the message element altogether. It simply allows an operation to
reference a type (such as an XML Schema element) directly.


Interface Definition

WSDL 2.0 not only changes the element name of an interface definition from portType
to interface, it also expands the interface construct with a set of new elements and
attributes, as shown in the highlighted parts of this example:
<interface name="..." extends="..." styleDefault="...">
<fault name="..." element="..." />
<operation name="..." pattern="..." style="..."
wsdlx:safe="...">
<input messageLabel="..." element="..." />
<output messageLabel="..." element="..." />
<infault ref="..." messageLabel="..." />
<outfault ref="..." messageLabel="..." />
</operation>
</interface>

Let's explore these new elements and attributes more closely.


The interface Element's extends Attribute

Object-oriented programming introduced the concept of interface inheritance whereby
a new interface can be derived from an existing interface by inheriting and then extending
its operations.

The optional extends attribute of the interface element allows one interface to extend
or inherit from one or more other interfaces. In such cases, the interface contains all the
operations it extends plus the operations it defines directly.

Now let's have a look at an example of how the extends attribute works.

ActionCon introduces a requirement that any activities related to the processing of
purchase orders must be logged in a storage center for auditing purposes. As shown
here, Steve defines an interface for logging and then uses that interface in one of several
purchase order-related interfaces.

<interface name="ifPurchaseOrderLog">
<operation name="opLogOrder"
pattern="http://www.w3.org/2006/01/wsdl/out-only">
<output messageLabel="Out" element="po:orderLog"/>
</operation>
</interface>

The ifPurchaseOrderLog interface construct represents the operation that can be
inherited by other interface constructs, and the ifPurchaseOrder interface construct
is the interface that inherits it via the use of the extends attribute.

<interface name="ifPurchaseOrder" extends="tns:ifPurchaseOrderLog" >
<operation name="opChangeOrder"
pattern="http://www.w3.org/2006/01/wsdl/in-out">
<input messageLabel="In" element="po:purchaseOrder "/>
<output messageLabel="Out" element="po:acknowledgement"/>
</operation>
<operation name="opCancelOrder"
pattern="http://www.w3.org/2006/01/wsdl/in-out">
<input messageLabel="In" element="po:poNumber"/>
<output messageLabel="Out" element="po:acknowledgement"/>
</operation>
</interface>

As a result of the inheritance, the interface
ifPurchaseOrder now contains three operations:
opLogOrder, opChangeOrder, and opCancelOrder.


The interface Element's styleDefault Attribute

Styles define certain rules that are applied to operations. The
styleDefault attribute
can be used to set a default value for the
style attributes of all operations under an
interface.
<interface name="ifPurchaseOrderLog"
styleDefault="http://www.w3.org/ns/wsdl/style/iri">
<operation name="opLogOrder"
pattern="http://www.w3.org/2006/01/wsdl/out-only">
<output messageLabel="Out" element="po:orderLog"/>
</operation>
</interface>

The following pre-defined style values are provided:

|
•
|
RPC Style (http://www.w3.org/ns/wsdl/style/rpc)
Requires that all the operations within an interface must follow the rules for
RPC-style messages.
|
|
•
|
IRI Style (http://www.w3.org/ns/wsdl/style/iri)
Places restrictions on message definitions so they may be serialized into something
like HTTP URL-encoded.
|
|
•
|
Multipart (http://www.w3.org/ns/wsdl/style/multipart)
In the HTTP binding, for XForms clients, a message must be defined following this
style and serialized as "Multipart/form-data."
|

The exact rules and restrictions of each style are documented in the WSDL 2.0 specification.
operation elements can have individual style attribute settings that override the
styleDefault setting of the parent interface element.

The styleDefault attribute is optional; if it's missing, it simply means no additional
rules need to be followed.


The wsdlx:safe Global Attribute

This new attribute indicates whether an operation is considered to be "safe" as per the
W3C Web Architecture specification, which states:

"…a safe interaction is one where the agent does not incur any obligation beyond the
interaction. An agent may incur an obligation through other means (such as by
signing a contract). If an agent does not have an obligation before a safe interaction,
it does not have that obligation afterwards.

Other Web interactions resemble orders more than queries. These unsafe interactions
may cause a change to the state of a resource and the user may be held responsible for
the consequences of these interactions. Unsafe interactions include subscribing to a
newsletter, posting to a list, or modifying a database. Note: In this context, the word
"unsafe" does not necessarily mean 'dangerous'…"

In other words, if an operation performs something along the lines of a read-only function
that doesn't permanently alter any part of the service environment or if it does not
give the consumer any new obligations, then it is considered "safe."

This attribute is essentially a means by which a service contract can communicate that a
particular operation has little risk associated with it. This can be valuable especially in
support of the Service Discoverability principle, which encourages us to improve the
communications quality of the contract. However, Service Abstraction considerations
also need to be taken into account. In some cases, it may be deemed necessary not to
allow this attribute at all.

If it is allowed, it is important that SOA governance procedures be in place to manage
the potential change of this setting. If consumer programs become dependent on a service
operation with the assumption that it is safe and then the underlying functionality of
the operation changes so that it is no longer considered safe, then this may have a variety
of negative impacts. It may also be required for this setting to be programmatically
retrieved by certain consumers.

The default value of the wsdlx:safe attribute is "false." Therefore, if the attribute is not
present or if it is explicitly set to false, then the consumer can assume the operation is
"not safe."


The fault, infault, and outfault Elements

With WSDL 2.0, the fault element is promoted to a first-level child element within the
interface construct. This lifts fault to the same level as operation, allowing one fault
message to be reused across different operations.

As shown in this example, a fault can be referenced by multiple operations via the ref
attributes of their infault and outfault elements.

<types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://actioncon.com/schema/po"
targetNamespace="http://actioncon.com/schema/po"
elementFormDefault="qualified">
<xsd:element name="invalidOrder"
type="invalidOrderType"/>
<xsd:complexType name="invalidOrderType">
<xsd:sequence>
<xsd:element name="PODate" type="xsd:date"/>
<xsd:element name="OrderID" type="xsd:string"/>
<xsd:element name="Desc" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</types>

This types construct defines the invalidOrderType type that is subsequently reused
as a fault message by the opChangeOrder and opCancelOrder operations via their
respective outfault elements.

<interface name="ifPurchaseOrder" extends="tns:ifPurchaseOrderLog" >
<fault name="invalidOrderFault" element="po:invalidOrder"/>
<operation name="opChangeOrder"
pattern="http://www.w3.org/2006/01/wsdl/in-out">
<input messageLabel="In" element="po:purchaseOrder "/>
<output messageLabel="Out" element="po:acknowledgement"/>
<outfault ref="tns:invalidOrderFault" messageLabel="Out/>
</operation>
<operation name="opCancelOrder"
pattern="http://www.w3.org/2006/01/wsdl/in-out">
<input messageLabel="In" element="po:poNumber"/>
<output messageLabel="Out"
element="po:acknowledgement"/>
<outfault ref="tns:invalidOrderFault" messageLabel="Out/>
</operation>
</interface>

Defining faults at the interface level is especially beneficial for binding definitions. For
example, a SOAP fault may have an error code (and sub-codes) in addition to its fault
message details. By defining faults at the interface level, you can ensure that common
error codes can be used across all operations that use the faults.

For example, when the interface in the following example is bound to SOAP 1.2, one can
specify a SOAP fault code as "sender" for all invalid order errors.

<binding name="bdPurchaseOrder-SOAP12HTTP"
interface="tns:ifPurchaseOrder" >
<fault ref="tns:invalidOrderFault" soap12:code="soap12:Sender"/>
<operation ref="tns:opChangeOrder" .../>
<operation ref="tns:opCancelOrder" .../>
</binding>

In this example, the fault element is bound to the binding element and therefore
becomes applicable to both operations within the binding definition, allowing the operations
to reuse the same fault code.

Given the structure of the interface and binding definitions, at runtime if an invalid
order is found, the fault message returned to the sender will appear as something like
this:

<soap:Envelope xmlns:soap=
"http://www.w3.org/2003/05/soap-envelope"
xmlns:po="http://actioncon.com/schema/po" ...>
<soap:Body>
<soap:Fault>
<soap:Code>
<soap:Value>soap:Sender</soap:Value>
</soap:Code>
<soap:Detail>
<po:invalidOrder>
<po:PODate>02-23-2008</po:PODate>
<po:OrderID>1234</po:OrderID>
<po:Desc>
The required order party ID is missing.
</po:Desc>
</po:invalidOrder>
</soap:Detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>


The pattern and messageLabel Attributes

The WSDL 2.0 specification allows message exchange patterns (MEPs) to be defined in
separate specifications and then brought into an operation definition via the new
pattern attribute.

Arelated MEP specification establishes how many messages are exchanged and in what
order. Each message can be identified with a message label and a direction ("in" or
"out").

The operation that employs a particular MEP should provide a corresponding number
of messages based on the following rules:
|
•
|
For each message with a direction of "In," an input element needs to be defined
with a messageLabel attribute set to "In."
|
|
•
|
For each message with a direction of "Out," an output element is defined with a
messageLabel attribute set to "Out."
|
|
•
|
The order of the input and output elements should be the same as the order of
their corresponding messages defined in the MEP specification.
|
WSDL2.0 uses new terms to describe MEPs. For example, the "Request-Response" MEP
from WSDL 1.1 is now "In-Out," and the "One-Way" MEP has been renamed to "In."

The messageLabel attribute of an operation's input, output, or fault element simply
indicates the role played by the message in the MEP. For example, a setting of message-
Label="In" for an "In-Out" MEP means that the message is the input message of an "In-
Out" operation. (This may seem redundant because the input element's name already
indicates that this is an input message.)

Here's an example that uses the pattern and messageLabel attributes for an operation
based on the "In-Out" MEP.

<operation name="opChangeOrder"
pattern="http://www.w3.org/2006/01/wsdl/in-out">
<input messageLabel="In" element="po:purchaseOrder "/>
<output messageLabel="Out" element="po:acknowledgement"/>
</operation>


Service and Endpoint Definitions

In WSDL 2.0, a
service element can only implement one interface via its
interface
attribute as shown in the following example. What this means is that when a service has
more than one
endpoint element, they will share an
interface but employ different
bindings and addresses.

This is because they are alternatives in the sense that each endpoint can provide the
same behavior via different binding configurations. By allowing services to provide
alternative endpoints, consumers have more freedom to determine which port is the
best for a given purpose.

<service name="svPurchaseOrder" interface="ifPurchaseOrder">
<endpoint name="purchaseOrder-http-soap12"
binding="tns:bdPO-SOAP12HTTP" address=
"http://actioncon.com/services/soap12/purchaseOrder"/>
</service>


A Complete WSDL 2.0 Definition

The following sample code shows a complete WSDL 2.0 definition. The highlighted sections indicate where the WSDL 2.0 language differs from WSDL 1.1.

<descriptiontargetNamespace="http://actioncon.com/contract/po"
xmlns="8http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://actioncon.com/contract/po"
xmlns:po="http://actioncon.com/schema/po"
xmlns:soapbind="http://www.w3.org/ns/wsdl/soap">
<!- BEGIN ABSTRACT DESCRIPTION ->
<types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://actioncon.com/schema/po"
targetNamespace="http://actioncon.com/schema/po"
elementFormDefault="qualified">
<xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
<xsd:element name="acknowledgement" type="xsd:string"/>
<xsd:element name="poNumber" type="xsd:integer"/>
<xsd:element name="status" type="xsd:string"/>
<xsd:complexType name="PurchaseOrderType">
<xsd:sequence>
<xsd:element ref="poNumber"/>
<xsd:element name="PODate" type="xsd:date"/>
<xsd:element name="BillToParty" type="PartyType"/>
<xsd:element name="ShipToParty" type="PartyType"/>
<xsd:element name="LineItems" type="LineItemsType"/>
</xsd:sequence>
<xsd:attribute name="version" type="xsd:decimal"/>
</xsd:complexType>
<xsd:complexType name="PartyType">
<xsd:sequence>
<xsd:element name="ID" type="xsd:integer"/>
<xsd:element name="PartyName" type="xsd:string"/>
<xsd:element name="ContactName" type="xsd:string"/>
<xsd:element name="Phone" type="xsd:string"/>
<xsd:element name="Address" type="AddressType"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="AddressType">
<xsd:sequence>
<xsd:element name="Line1" type="xsd:string"/>
<xsd:element name="Line2" type="xsd:string"
minOccurs="0"/>
<xsd:element name="City" type="xsd:string"/>
<xsd:element name="State" type="xsd:string"/>
<xsd:element name="PostalCode" type="xsd:string"/>
<xsd:element name="Country" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="LineItemsType">
<xsd:sequence>
<xsd:element name="LineItem" type="LineItemType"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="LineItemType">
<xsd:sequence>
<xsd:element name="ProductID" type="ProductIDType"/>
<xsd:element name="ProductName" type="xsd:string"/>
<xsd:element name="Quantity" type="xsd:int"/>
<xsd:element name="Price" type="PriceType"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="ProductIDType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="[A-Z]{2}[0-9]{4}"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="PriceType">
<xsd:restriction base="xsd:decimal">
<xsd:totalDigits value="8"/>
<xsd:fractionDigits value="2"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
</types>
<interface name="ifPurchaseOrder">
<operation name="opSubmitOrder"
pattern="http://www.w3.org/2006/01/wsdl/in-out">
<input messageLabel="In" element="po:purchaseOrder"/>
<output messageLabel="Out" element="po:acknowlegement"/>
</operation>
<operation name="opCheckOrderStatus"
pattern="http://www.w3.org/2006/01/wsdl/in-out">
<input messageLabel="In" element="po:poNumber"/>
<output messageLabel="Out" element="po:status"/>
</operation>
<operation name="opChangeOrder"
pattern="http://www.w3.org/2006/01/wsdl/in-out">
<input messageLabel="In" element="po:purchaseOrder "/>
<output messageLabel="Out" element="po:acknowledgement"/>
</operation>
<operation name="opCancelOrder"
pattern="http://www.w3.org/2006/01/wsdl/in-out">
<input messageLabel="In" element="po:poNumber"/>
<output messageLabel="Out" element="po:acknowledgement"/>
</operation>
</interface>
<!- END ABSTRACT DESCRIPTION ->
<!- BEGIN CONCRETE DESCRIPTION ->
<binding name="bdPO-SOAP12HTTP" interface="ifPurchaseOrder"
type="http://www.w3.org/2006/01/wsdl/soap"
soapbind:protocol=
"http://www.w3.org/2003/05/soap/bindings/HTTP">
<operation ref="tns:opSubmitOrder"
soapbind:mep=
"http://www.w3.org/2003/05/soap/mep/request-response"
soapbind:action=
"http://actioncon.com/submitOrder/request"/>
<operation ref="opCheckOrderStatus"
soapbind:mep=
"http://www.w3.org/2003/05/soap/mep/request-response"
soapbind:action=
"http://actioncon.com/checkOrder/request"/>
<operation ref="opChangeOrder"
soapbind:mep=
"http://www.w3.org/2003/05/soap/mep/request-response"
soapbind:action=
"http://actioncon.com/changeOrder/request"/>
<operation ref="opCancelOrder"
soapbind:mep=
"http://www.w3.org/2003/05/soap/mep/request-response"
soapbind:action=
"http://actioncon.com/cancelOrder/request"/>
</binding>
<service name="svPurchaseOrder" interface="ifPurchaseOrder">
<endpoint name="purchaseOrder-http-soap12"
binding="tns:bdPO-SOAP12HTTP" address=
"http://actioncon.com/services/soap12/purchaseOrder"/>
</service>
<!- END CONCRETE DESCRIPTION ->
</description>


Conclusion

WSDL 2.0 makes some significant changes to the structure and language of expressing Web service contracts. Some of these changes might prove beneficial if you can take advantage of them, while others may be unnecessarily disruptive. The best approach is to get a full understanding of the options and then make an educated decision.


References

[REF-1] "Web Service Contract Design and Versioning for SOA" by Thomas Erl, Anish Karmarkar, Priscilla Walmsley, Hugo Haas, Umit Yalcinalp, Canyang Kevin Liu, David Orchard, Andre Tost, James Pasley for the "Prentice Hall Service-Oriented Computing Series from Thomas Erl", Copyright Prentice Hall/Pearson PTR and SOA Systems Inc., http://www.soabooks.com/wsc/
|