When working with webservices there is hardly a way to get arround WSDL, the Web Service Description Language. Still a lot of developers tend to think that they don’t need to know the interna, because tools like java2wsdl generate the WSDL file for them. So why bother with the details? Well, as long as you code first this might be true in parts, but the moment you have to hit a different development path, namely contract-first, things change. Now you have to create the WSDL file and respective XML schema first. Therefore it can’t be wrong to know how the WSDL clock ticks.
We will concentate on the WSDL 1.1 revision, even though version 2.0 is a W3C recommendation since March 2006 (but not wide spread one). After a short overview we will walk through the WSDL components by example. Please note, that you need to have a basic understanding of XML and XML schema for our walk.
The W3C describes the WSDL as follows:
WSDL is an XML format for describing network services as a set of endpoints operating on messages containing either document-oriented or procedure-oriented information.
In short the WSDL tells you how to access a web service. You can use it to communicate the service interface to other developers who then use this information to invoke the service, but moreoften it will be utilizedfor an automated machine only communication.
|Types||Defines the data that the web service uses in its messages – usually through an XML schema definition|
|Message||Defines the messages used by the service, each referring to a data type|
|Port Type||Defines the service interface with an abstract set of operations. Usually each operation refers to a message element.|
|Binding||Defines a concrete protocol and data format specification for a particular port type|
|Service||A collection of related endpoints consisting of a set of port elements that each references a binding element.|
As you can see this is like a kind of chain. Each component refers to a previously defined component. Now that we know the components let’s have a look a the outline of the WSDL 1.1 definition:
<definitions> <types> </types> <message> <part> </part> </message> <portType> <operation> <input> </input> <output> </output> <fault> </fault> </operation> </portType> <binding> <operation> </operation> </binding> <service> <port> </port> <service> </definitions>
Subsequently we’ll learn to know each of the major elements step by step.As mentioned above the easiest way to understand that thing is by example. We are going to define a simple web service that receives a customer id as input and returns a simple customer record with name and address data in its response.Everything starts with the <definitions>-tag, which I have not yet introduced . It is the root element of a WSDL definition.
<wsdl:definitions name="MyCustomerTestService" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://www.webservicetest.net" targetNamespace="http://www.webservicetest.net" >
As you can see there are a lot of attributes defining the namespaces used in the document, except the first attribute which is used for documentation purposes only. The attribute
targetNamespace defines the target namespace that we want to use and refers to the namespace prefixed with
The first child of the
definitions element is the types element. It defines the data types used for the message exchange. In our example we are defining a simple type CustomerID as a string of exactly eight characters without whitspace and complex type Customer which captures name and address data.
<wsdl:types> <xs:schema targetNamespace="http://www.webservicetest.net" elementFormDefault="qualified"> <xs:simpleType name="CustomerId"> <xs:restriction base="xs:NMTOKEN"> <xs:minLength value="8"/> <xs:maxLength value="8"/> </xs:restriction> </xs:simpleType> <xs:complexType name="Customer"> <xs:sequence> <xs:element name="Id" type="tns:CustomerId"/> <xs:element name="Firstname" type="xs:string"/> <xs:element name="Lastname" type="xs:string"/> <xs:element name="Adress" type="tns:Address"/> </xs:sequence> </xs:complexType> <xs:complexType name="Address"> <xs:sequence> <xs:element name="Street" type="xs:string"/> <xs:element name="Number" type="xs:int"/> <xs:element name="ZIP-Code"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:minLength value="5"/> <xs:maxLength value="5"/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="City" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema> </wsdl:types>
The next step is the definition of the messages. A message defines an input, output or fault element and consists of one or more part elements, which describe the content of the message. Sounds quite theoretical so better have a look a something concrete. We are defining one request and one response message.
<wsdl:message name="getCustomerDataRequest"> <wsdl:part name="CustomerRequest" type="tns:CustomerId"/> </wsdl:message> <wsdl:message name="getCustomerDataResponse"> <wsdl:part name="CustomerResponse" type="tns:Customer"/> </wsdl:message>
The message names have to be unique within the WSDL document, whereas the
part name have to be unique within the enclosing message.
type refers to the (simple or complex) data types that we defined in the schema definition. Alternatively you can use the attribute
element, which then refers to an XSD element.Now that the messages are defined we have to use them somewhere. That is what happens in
portType component which defines the service interface. The
name of a
portType has, as you may have guessed, to be unique within the WSDL document.
<wsdl:portType name="CustomerData"> <wsdl:operation name="getCustomerData"> <wsdl:input message="tns:getCustomerDataRequest"/> <wsdl:output message="tns:getCustomerDataResponse"/> </wsdl:operation> </wsdl:portType>
portType may include several abstract operations, where each operation element refers to a set of messages, as a combination of input, output and fault element, defining the data exchange of the operation according to a so called Message Exchange Patterns (MEP). WSDL 1.1 supports four MEPs:
The requester sends a request, but receives no answer. From the endpoints view: The endpoint receives a message, but sends no response.
operation consists of a single
input child element.
The requester sends a request and receives a message. From the endpoints view: The endpoint receives a message and returns a response.
operation consists of an
output and optional
fault child element.
The endpoint sends a notification without having received a request.
operation consists of a single
output child element.
The endpoint sends a notification and receives a response.
operation consists of an
input and optional
fault child element.
In our example we are using the request-response pattern, but omit the
fault element. The attribute
message refers to the name of the message that we have defined in the section above. Note that we have to use a qualified name and therefore need the prefix
Let’s have a look at upcoming
binding component. Right now we have abstract descriptions of interfaces, operations and messages. Now we are getting concrete by describing the transport protocol for the message exhange, the data format and give information about transport and coding of the messages. In our example we are using SOAP as transport protocol.
<wsdl:binding name="CustomerSOAPBinding" type="tns:CustomerData"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="getCustomerData"> <soap:operation soapAction=""/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding>
Once again we have to give the baby a unique name and furthermore create a reference to a
portType. This is done through the
type attribute, using a qualified name. The
soap:binding element indicates that the binding uses the SOAP protocol. We are using the default (document-style)
style, meaning the operation name is not added to the transmitted message. In addition the
transport attribute defines that HTTP is used.You may wonder why the soapAction attribute of the soap:operation element is nothing but an empty string. Well, I understood that it’s mainly used for some kind of inspection and discontinued in WSDL 2.0 anyway. Nevertheless for HTTP the presence of the attribute is required, but you can set it to an empty string.The
operation within the
binding refers to an operation with the same name in the
portType definition. As part of the
operation element the
use attribute specifies if the input, output and fault message are are
encoded, or whether they define the concrete schema of the message (
literal).Note, that using SOAP is just one way of defining a binding (even though it is part of the WSDL) as you can see by a look a the grammar for a binding:
<wsdl:definitions .... > <b> <wsdl:binding name="nmtoken" type="qname"> *</b> <b> <-- extensibility element (1) --> *</b> <b> <wsdl:operation name="nmtoken"> *</b> <b> <-- extensibility element (2) --> *</b> <b> <wsdl:input name="nmtoken"? > ?</b> <b> <-- extensibility element (3) --> </b> <b> </wsdl:input></b> <b> <wsdl:output name="nmtoken"? > ?</b> <b> <-- extensibility element (4) --> *</b> <b> </wsdl:output></b> <b> <wsdl:fault name="nmtoken"> *</b> <b> <-- extensibility element (5) --> *</b> <b> </wsdl:fault></b> <b> </wsdl:operation></b> <b> </wsdl:binding></b> </wsdl:definitions>
Please refer to How the SOAP Binding Extends WSDL for further information on how to extend the standard binding element.Just one major component left:
service. It defines a set of related endpoints where the service can be accessed.
<wsdl:service name="CustomerService"> <wsdl:port name="CustomerSOAPPort" binding="tns:CustomerSOAPBinding"> <soap:address location="No Target Adress"/> </wsdl:port> </wsdl:service>
Endpoints are represented by the element
port uses a distinct
name and has a reference to a
binding element to describe the endpoint. The soap:address finally assigns an address (URI) to the port. A port that refers to a SOAP binding MUST specify exactly one address. With this definition of an endpoint it’s possible to call a web service by just having the WSDL.Well, that’s the end of the quick walk through. In the subsequent image I’ve put all the components that we defined together into a single image and you can see, how each component references the previous one.