Anatomy of a WSDL Document

Let’s take a detailed look at the individual parts of a WSDL document. The following code shows the major elements that may appear in a WSDL document. An asterisk (*) next to an element indicates that more than one of these elements may appear. Elements from WSDL binding extensions (i.e., SOAP, HTTP, etc.) were not included here, to keep things simpler:

<definitions>
    <import>*
    <types>
        <schema></schema>*
    </types>
    <message>*
        <part></part>*
    </message>
    <PortType>*
        <operation>*
            <input></input>
            <output></output>
            <fault></fault>*
        </operation>
    </PortType>
    <binding>*
        <operation>*
            <input></input>
            <output></output>
        </operation>
    </binding>
    <service>*
        <port></port>*
    </service>
</definitions>

In the next few sections, we define each of the major WSDL elements and present a real-life example as part of the explanation. Finding a WSDL file sophisticated enough to cover the various facets of the specification while still remaining readable was not simple. The following sections present the WSDL document that defines a web service for the translation of the Z39.50 ASN.1 specification. Z39.50/XER (XML Encoding Rules) allows information described in ASN.1 to be carried in XML. It describes the datatypes and operations that one would need to perform real-time conversions between ASN.1-encoded data structures and XML-encoded data structures.

The ez3950-PortTypes.wsdl file in the examples directory contains the WSDL for this example. This file also depends upon ez3950.xsd, which is in the same directory.

<definitions> Element

The <definitions> element in a WSDL document acts as a container for the service description. It provides a place to do global declarations of namespaces that are intended to be visible throughout the rest of the document. Here is the <definitions> element from the XML Encoding Rules. Note that some of the namespaces defined in this element have prefixes (xsd, soap, soapenc, xer, etc.), and some do not. These prefixes are bound to a particular namespace but do not govern which schemas are actually available to a schema processor:

<definitions
   targetNamespace="urn:3950"
   xmlns="http://schemas.xmlsoap.org/wsdl/"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"  
   xmlns:tns="urn:3950"
>

Are the addresses specified in these namespace URIs real? Some of them are and some of them are not. It’s a common practice to post the XML Schema document that the namespace URI refers to at the real URL. Many organizations don’t follow this practice, however. Namespaces frequently contain URIs that are just references to XML Schema documents that aren’t located on the Internet. Connect to the Internet and try entering http://schemas.xmlsoap.org/wsdl/soap/ in your browser. If you use Internet Explorer 5, you should see the XML Schema document for the SOAP binding extension for WSDL. Can you get the XML schema for all namespace URIs?

The targetNamespace attribute of the <definitions> element defines the namespace definition that this document is creating. This attribute is used in lieu of the name attribute on the <definitions> element. The target namespace creates a new, unique identifier within which any types or abstract definitions defined by the document fall. The default namespace allows you to use tags without prepending the namespace alias to the beginning of the tag. The URI for the targetNamspace attribute must be an absolute reference, not a relative one. Here, http://asf.gils.net/xer is specified as the target and http://schemas.xmlsoap.org/wsdl/ is used as the default namespace.

Given this description, keep the following issues in mind when working with namespaces:

  • A namespace is qualified in an XML document through a QNAME. The QNAME is the value following xmlns: in an XML document. It is a value used to qualify an element within the XML document. If two elements imported from different namespaces have the same name, they are qualified by using the QNAME followed by a colon.

  • The default namespace used on elements (also known as the default qualifier) is the namespace that follows the xmlns= attribute in an XML definition. If two conflicting elements come from different namespaces, the element defined in the namespace identified by xmlns= is used.

  • The targetNamespace creates a unique identifier of the namespace created in the WSDL document. Since the WSDL document defines new elements and attributes, the value of this attribute is the identifier given to the namespace to which those elements belong.

  • It is common practice to further qualify the target namespace by creating a QNAME named tns that points to the same value of targetNamespace. Thus, targetNamespace creates a new namespace, and tns becomes the QNAME for identifying “this namespace” within the same WSDL document.

Table 5-1 lists the namespace prefixes and URIs that you’ll see most frequently in WSDL documents. Of course, many namespaces aren’t listed in this table.

Table 5-1. Common namespace prefixes

Prefix

Namespace URI

Synopsis

wsdl

http://schemas.xmlsoap.org/wsdl/

Namespace of WSDL grammar.

soap

http://schemas.xmlsoap.org/wsdl/soap/

Namespace of WSDL extension binding for SOAP message.

http

http://schemas.xmlsoap.org/wsdl/http/

Namespace of WSDL extension binding HTTP protocol.

mime

http://schemas.xmlsoap.org/wsdl/mime/

Namespace of WSDL extension binding for MIME protocol.

soapenc

http://schemas.xmlsoap.org/soap/encoding/

Namespace of schema governing SOAP 1.1 encoding.

soapenv

http://schemas.xmlsoap.org/soap/envelope/

Namespace of schema governing SOAP 1.1 envelopes.

xsi

http://www.w3.org/2000/10/XMLSchema-instance

Namespace of schema governing XML Schema instances. An instance is an XML document that conforms to a given XML Schema (.xsd) file.

xsd

http://www.w3.org/2000/10/XMLSchema

Namespace of schema governing XML Schema (.xsd) files.

tns

(application or context-dependent)

Namespace convention used to refer to the current WSDL document. The prefix is an acronym for "this namespace.” Assigning the targetNamespace value to this prefix is customary.

<import> Element

After the <definitions> element, we see an <import> element:

<definitions
   targetNamespace="urn:3950"
   xmlns="http://schemas.xmlsoap.org/wsdl/"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"  
   xmlns:tns="urn:3950"
>
   <import namespace="http://asf.gils.net/xer" 
                          location="http://asf.gils.net/xer/ez.xsd"/>

The <import> element serves a purpose similar to the #include directive in the C/C++ programming language. It lets you separate the elements of a service definition into independent documents and include them in the main document, where appropriate. Effective use of the <import> element promotes the modularization of WSDL documents and creates an environment of reuse that can create clear service definitions. WSDL documents structured in this way are easier to use and maintain, but require any WSDL parsing engine to perform additional I/O operations to import any externally referenced resource. You can have zero or more <import> elements.

The <import> element imports the namespace of another file, not the file itself. Elements in an XML file are identified by a namespace declaration. A namespace declaration can occur at any element in the file and then applies for any subelements, assuming that an overriding namespace isn’t applied. When an <import> statement is used, all elements for that given namespace are included at the location of the <import> element in the parent document.

In the ez3950-PortTypes.wsdl file that we have provided, an <import> tag is used to include information located in another XML file. In this case, the <import> tag imports the file located at http://asf.gils.net/xer/ez.xsd. Even though this file is local, the WSDL file is placed on the Internet, so it is important to provide an absolute URL for the location of the imported file. The ez.xsd file is located in the examples directory and contains the schema definitions required for this WSDL file. The schema definitions are further defined in the next section.

<types> Element

The <types> element in a WSDL document acts as a container for defining the datatypes used in <message> elements. <message> elements define the format of messages interchanged between a client and a web service. Currently, XML Schema Definitions (XSD) is the most widely used data typing method, but WSDL allows the inclusion of other XML typing approaches.

For the most part, a study of the <types> element is a study of XML Schema. The <types> element has zero or more <schema> subelements, which must follow the rules for XML Schema documents. The <schema> element of our WSDL document is surprisingly simple, but long.

If you look at the ez3950-PortTypes.wsdl file provided in this chapter, a <types> element is not included. Rather, the schema definitions required for the WSDL document are included via the <import> element. What is interesting is that if you look at the ez3950.xsd file, that file does not have a <types> element. Since the namespace being imported is a schema definition, the WSDL parser automatically understands that the included elements must be included as part of the <types> definition. The <types> section listed here appears as it would if the <import> statement did not exist in the WSDL document and the WSDL contained all schema definitions inline.

The <types> section is presented in several portions to illustrate some of the different kinds of syntax available with XML Schema. XML Schema can be very complex. This chapter provides some rudimentary explanations of XML Schema notation, but we’re assuming that you already have a basic understanding of what XML Schemas are and how they work. We start with the <type> tag itself, followed by the definition of a single complex type:

<types>
 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="PDU" type="PDU"/>
        <xsd:complexType name="PDU">
            <xsd:choice>
                <xsd:element name="initRequest" type="InitializeRequest" /> 
                <xsd:element name="initResponse" type="InitializeResponse" /> 
                <xsd:element name="searchRequest" type="SearchRequest" /> 
                <xsd:element name="searchResponse" type="SearchResponse" /> 
                <xsd:element name="presentRequest" type="PresentRequest" /> 
                <xsd:element name="presentResponse" type="PresentResponse" /> 
                <xsd:element name="deleteResultSetRequest"
                   type="DeleteResultSetRequest" /> 
                <xsd:element name="deleteResultSetResponse" 
                   type="DeleteResultSetResponse" /> 
                <xsd:element name="accessControlRequest" 
                   type="AccessControlRequest" /> 
                <xsd:element name="accessControlResponse"
                   type="AccessControlResponse" /> 
                <xsd:element name="resourceControlRequest" 
                   type="ResourceControlRequest" /> 
                <xsd:element name="resourceControlResponse" 
                   type="ResourceControlResponse" /> 
                <xsd:element name="triggerResourceControlRequest" 
                   type="TriggerResourceControlRequest" /> 
                <xsd:element name="resourceReportRequest" 
                   type="ResourceReportRequest" /> 
                <xsd:element name="resourceReportResponse" 
                   type="ResourceReportResponse" /> 
                <xsd:element name="scanRequest" type="ScanRequest" /> 
                <xsd:element name="scanResponse" type="ScanResponse" /> 
                <xsd:element name="sortRequest" type="SortRequest" /> 
                <xsd:element name="sortResponse" type="SortResponse" /> 
                <xsd:element name="segmentRequest" type="Segment" /> 
                <xsd:element name="extendedServicesRequest" 
                   type="ExtendedServicesRequest" /> 
                <xsd:element name="extendedServicesResponse" 
                   type="ExtendedServicesResponse" /> 
                <xsd:element name="close" type="Close" /> 
            </xsd:choice>
        </xsd:complexType>

XML Schema is a language used to define the structure and restrictions for new elements and attributes. New elements are defined through the <simpleType> and <complexType> elements. A <simpleType> defines the format of a single element, while <complexType> defines an element with subelements. The <xsd:complexType> element (which starts at the fourth line of the preceding code) defines a complex datatype that uses a <choice> model group. This model group ensures that the value assigned to an instance of this datatype corresponds to exactly one of the possible values for it.

The next element, <xsd:simpleType> , defines a simple datatype that represents an enumeration. It starts with the definition of a predefined schema datatype, xsd:string, and then restricts the behavior to a form that meets our needs:

        <xsd:simpleType name="KnownProximityUnit">
            <xsd:restriction base="xsd:string">
                <xsd:enumeration value="character" /> 
                <xsd:enumeration value="word" /> 
                <xsd:enumeration value="sentence" /> 
                <xsd:enumeration value="paragraph" /> 
                <xsd:enumeration value="section" /> 
                <xsd:enumeration value="chapter" /> 
                <xsd:enumeration value="document" /> 
                <xsd:enumeration value="element" /> 
                <xsd:enumeration value="subelement" /> 
                <xsd:enumeration value="elementType" /> 
                <xsd:enumeration value="byte" /> 
            </xsd:restriction>
        </xsd:simpleType>

The base xsd:string type allows a string value to have any combination of characters and any length. The new type, named KnownProximityUnit, creates a new string type that allows only the values defined in the <xsd:enumeration> elements to appear as values; the value of a KnownProximityUnit must be of type xsd:string and must have one of the specified values.

The next part of the file defines several additional types derived by restriction:

        <xsd:simpleType name="ReferenceId">
            <xsd:restriction base="xsd:hexBinary" /> 
        </xsd:simpleType>
        <xsd:simpleType name="GeneralString">
            <xsd:restriction base="xsd:string" /> 
        </xsd:simpleType>
        <xsd:simpleType name="InternationalString">
            <xsd:restriction base="GeneralString" /> 
        </xsd:simpleType>
        <xsd:simpleType name="OID">
            <xsd:restriction base="xsd:string">
                <xsd:pattern value="d*{.d*}*" /> 
            </xsd:restriction>
        </xsd:simpleType>
        <xsd:simpleType name="ANY">
            <xsd:restriction base="xsd:anyType" /> 
        </xsd:simpleType>

As you can see, <simpleType> datatypes can be derived from a variety of existing base types. The ReferenceId and GeneralString types are derived from the xsd:hexBinary and xsd:string base types, respectively. The user-defined type InternationalString is derived in turn from GeneralString. Likewise, the user-defined type ANY is derived by restriction from xsd:anyType. This type can represent any value that conforms to nearly any type. In toolkits that map XML Schema to Java, xsd:anyType elements are typically mapped to java.lang.Object classes.

The next part of the WSDL file takes us for a whirlwind ride through almost every XML Schema structure and type you’re likely to come across regularly:

        <xsd:element name="SortRequest" type="SortRequest" /> 
        <xsd:complexType name="SortRequest">
            <xsd:sequence>
                <xsd:element name="referenceId" type="ReferenceId" minOccurs="0" /> 
                <xsd:element name="inputResultSetNames">
                   <xsd:simpleType>
                        <xsd:list itemType="InternationalString" /> 
                   </xsd:simpleType>
                 </xsd:element>
                 <xsd:element name="sortedResultSetName" 
                    type="InternationalString" /> 
                 <xsd:element name="sortSequence">
                     <xsd:complexType>
                          <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                              <xsd:element name="SortKeySpec" type="SortKeySpec" /> 
                          </xsd:sequence>
                     </xsd:complexType>
                 </xsd:element>
                 <xsd:element name="otherInfo" type="OtherInformation" 
                     minOccurs="0" /> 
                 </xsd:sequence>
        </xsd:complexType>
        <xsd:element name="SortResponse" type="SortResponse" /> 
        <xsd:complexType name="SortResponse">
            <xsd:sequence>
                 <xsd:element name="referenceId" type="ReferenceId" 
                      minOccurs="0" /> 
                 <xsd:element name="sortStatus">
                      <xsd:simpleType>
                            <xsd:restriction base="xsd:string">
                                <xsd:enumeration value="success" /> 
                                <xsd:enumeration value="partial-1" /> 
                                <xsd:enumeration value="failure" /> 
                            </xsd:restriction>
                       </xsd:simpleType>
                 </xsd:element>
                 <xsd:element name="resultSetStatus" minOccurs="0">
                       <xsd:simpleType>
                            <xsd:restriction base="xsd:string">
                                 <xsd:enumeration value="empty" /> 
                                 <xsd:enumeration value="interim" /> 
                                 <xsd:enumeration value="unchanged" /> 
                                 <xsd:enumeration value="none" /> 
                            </xsd:restriction>
                       </xsd:simpleType>
                 </xsd:element>
                 <xsd:element name="diagnostics" minOccurs="0">
                     <xsd:complexType>
                          <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                                 <xsd:element name="DiagRec" type="DiagRec" /> 
                          </xsd:sequence>
                     </xsd:complexType>
                 </xsd:element>
                    <xsd:element name="otherInfo" type="OtherInformation" 
                         minOccurs="0" /> 
            </xsd:sequence>
        </xsd:complexType>

The <xsd:list> element introduces a list element. This element is a datatype whose values consist of a finite-length sequence of values of an atomic datatype (i.e., xsd:string, derived restriction, etc.). It has an attribute named itemType, which specifies the atomic datatype for the items that make up the list. For the most part, the rest of the lines contain datatypes we have already discussed (user-defined complex types, user-defined simple types, or enumerations).

The last block introduces the <xsd:element> element’s ref attribute:

        <xsd:complexType name="EXTERNAL">
            <xsd:sequence>
                <xsd:element name="External">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="direct-reference" 
                                 type="xsd:string" /> 
                             <xsd:element name="encoding">
                                 <xsd:complexType>
                                     <xsd:choice>
                                         <xsd:element ref="single-ASN1-type" /> 
                                         <xsd:element ref="octet-aligned" /> 
                                     </xsd:choice>
                                 </xsd:complexType>
                             </xsd:element>
                         </xsd:sequence>
                     </xsd:complexType>
                 </xsd:element>
             </xsd:sequence>
         </xsd:complexType>
         <xsd:element name="single-ASN1-type">
             <xsd:complexType>
                 <xsd:sequence>
                     <xsd:element ref="motd" minOccurs="0" maxOccurs="unbounded" /> 
                     <xsd:element ref="DBName" minOccurs="0" 
                          maxOccurs="unbounded" /> 
                </xsd:sequence>
             </xsd:complexType>
         </xsd:element>
         <xsd:element name="octet-aligned" type="xsd:string" /> 
         <xsd:element name="motd" type="xsd:string" /> 
         <xsd:element name="DBName" type="xsd:string" /> 
         <xsd:complexType name="DatabaseNames">
             <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                 <xsd:element ref="DatabaseName" /> 
             </xsd:sequence>
         </xsd:complexType>
         <xsd:element name="databaseNames" type="DatabaseNames" /> 
         <xsd:element name="DatabaseName" type="xsd:string" /> 
         </xsd:schema>
</types>

As implied by its name, this attribute allows you to reference a user-defined type (either complex or simple) defined elsewhere within the schema document. For example, the ref="DatabaseName" attribute indicates that the element definition in which it appears (<DatabaseNames>) can include a <DatabaseName> element, which is defined elsewhere in the document. The definition for <DatabaseName> appears at the end of this block of code; it is defined as an xsd:string type with no restrictions.

A complete discussion of XML Schema would be a book in itself.[9] It suffices to say that XML Schema is a pretty intense body of work. Unfortunately, developers still have to do some XML Schema mangling, which requires you to understand the details of this complex specification. However, many web services and XML Schema toolkits are becoming adept at processing <schema> elements and providing interfaces that abstract the details of XML Schema definitions provided by developers. If you want to know more about XML Schema, see Eric van der Vlist’s XML Schema (O’Reilly).

<message> Element

The <message> element is used to model the data exchanged as part of a web service. <message> elements reference the types defined in the <types> section. The data contained within a <message> element typed by a <message> element is abstract. A message consists of one or more <part> subelements. A <part> subelement identifies the individual pieces of data that are part of this data message and the datatypes that the pieces adhere to. The following <message> element is contained in the ez3950-PortTypes.wsdl file:

<message name="soapHeader">
  <part type="xsd:string" name="id"/>
  <part type="xsd:string" name="timeout"/>
</message>

In the previous code, the <message> element is uniquely identified by the name attribute. This message is named soapHeader; it has two <part> subelements, of which the first is named id and the second is named timeout. In this case, each part is typed as an XML Schema string (xsd:string). But the types used in part definitions aren’t required to come from XML Schema; they could just as well be defined in the <types> element of the existing WSDL document itself.

The rest of the <message> elements contained in our sample WSDL file follow. Note that multiple parts are used if the message contains multiple logical parts, such as parameters in an RPC request. Each part can be a simple type or a structure. You can define the part structure here within the message using the <element> tag, or you can refer to the typed structures defined in the <types> section:

<message name="initRequest">
    <part type="xer:initRequest" name="initRequest"/>
</message>
<message name="initResponse">
    <part type="xer:initResponse" name="initResponse"/>
</message>
<message name="searchRequest">
    <part type="xer:searchRequest" name="searchRequest"/>
</message>
<message name="searchResponse">
    <part type="xer:searchResponse" name="searchResponse"/>
</message>
<message name="presentRequest">
    <part type="xer:presentRequest" name="presentRequest"/>
</message>
<message name="presentResponse">
    <part type="xer:presentResponse" name="presentResponse"/>
</message>
<message name="sortRequest">
    <part type="xer:sortequest" name="sortRequest"/>
</message>
<message name="sortResponse">
    <part type="xer:sortResponse" name="sortResponse"/>
</message>
<message name="scanRequest">
    <part type="xer:sortRequest" name="scanRequest"/>
</message>
<message name="scanResponse">
    <part type="xer:scanResponse" name="scanResponse"/>
</message>
<message name="deleteRequest">
    <part type="xer:scanRequest" name="deleteRequest"/>
</message>
<message name="deleteResponse">
    <part type="xer:scanResponse" name="deleteResponse"/>
</message>
<message name="accessControlRequest">
    <part type="xer:accessControlRequest" name="accessControlRequest"/>
</message>
<message name="accessControlResponse">
    <part type="xer:accessControlResponse" name="accessControlResponse"/>
</message>
<message name="triggerResourceControlRequest">
   <part type="xer:triggerResourceControlRequest"   
       name="triggerResourceControlRequest"/>
</message>
<message name="resourceControlRequest">
    <part type="xer:resourceControlRequest" name="resourceControlRequest"/>
</message>
<message name="resourceControlResponse">
    <part type="xer:resourceControlResponse" name="resourceControlResponse"/>
</message>
<message name="resourceReportRequest">
    <part type="xer:resourceReportRequest" name="resourceReportRequest"/>
</message>
<message name="resourceReportResponse">
    <part type="xer:resourceReportResponse" name="resourceReportResponse"/>
</message>
<message name="extendedServicesRequest">
    <part type="xer:extendedServicesRequest" name="extendedServicesRequest"/>
</message>
<message name="extendedServicesResponse">
    <part type="xer:extendedServicesResponse" name="extendedServicesResponse"/>
</message>
<message name="close">
    <part type="xer:close" name="close"/>
</message>

<portType> Element

The <portType> element specifies a subset of operations supported for an endpoint of a web service. In a sense, a <portType> element provides a unique identifier to a group of actions that can be executed at a single endpoint.

The <operation> element represents an operation. This element is an abstract definition of an action supported by a web service. A WSDL <operation> element is analogous to a Java method definition. A WSDL operation can have input and output messages as part of its action. The <operation> tag defines the name of the action by using a name attribute, defines the input message by the <input> subelement, and defines the output message by the <output> subelement. The <input> and <output> elements reference <message> elements defined in the same WSDL document or an imported one. A <message> element can represent a request, response, or a fault.

Continuing with the Z39.50 ASN.1 sample, the WSDL file defines a single <portType> element:

<portType name="ez3950PortTypes">

This element declares that this endpoint has a set of operations that are jointly referenced as ez3950PortTypes. The following lines define the <operation> elements for this <portType>:

<!-- Request-response Operations (client initiated) -->
      <operation name="init">
          <input message="initRequest"/>
          <output message="initResponse"/>
      </operation>
      <operation name="search">
          <input message="searchRequest"/>
          <output message="searchResponse"/>
      </operation>
      <operation name="present">
          <input message="presentRequest"/>
          <output message="presentResponse"/>
      </operation>
      <operation name="sort">
          <input message="sortRequest"/>
          <output message="sortResponse"/>
      </operation>
      <operation name="scan">
          <input message="scanRequest"/>
          <output message="scanResponse"/>
      </operation>
      <operation name="delete">
          <input message="deleteRequest"/>
          <output message="deleteResponse"/>
      </operation>
      <operation name="resourceReport">
          <input message="resourceReportRequest"/>
          <output message="resourceReportResponse"/>
      </operation>
      <operation name="extendedServices">
          <input message="extendedServicesRequest"/>
          <output message="extendedServicesResponse"/>
      </operation>
      <operation name="close">
          <output message="close"/>
          <input message="close"/>
      </operation>

<!-- Solicit-response Operation (Server initiated) -->
      <operation name="accessControl">
          <output message="accessControlResponse"/>
          <input message="accessControlRequest"/>
      </operation>
      <operation name="resourceControl">
          <output message="resourceControlResponse"/>
          <input message="resourceControlRequest"/>
      </operation>
      <operation name="close">
          <output message="close"/>
          <input message="close"/>
      </operation>

<!-- Notification Operations (Server initiated)-->
      <operation name="segment">
          <output message="segmentRequest"/>
      </operation>

<!-- One-way Operations (Client initiated) -->
      <operation name="triggerResourceControl">
          <input message="triggerResourceControlRequest"/>
      </operation>

  </portType>

These <operation> elements are grouped according to their behavior. When an operation is defined in a WSDL document, it is made to be abstract; it is purely an operation definition, but how that operation is mapped to a real function is defined later (i.e., the operation can behave in a number of different ways depending on the actual definition). The WSDL specification defines the following behavioral patterns as transmission primitives:

  • Request-response

  • Solicit-response

  • One-way

  • Notification

First, the operation can follow a request-response model, in which a web service client invokes a request and expects to receive a synchronous response message. This model is defined by the presence of both <input> and <output> elements. The <input> element must appear before the <output> element. This order indicates that the operation first accepts an input message (request) and then sends an output message (response). This model is similar to a normal procedure call, in which the calling method blocks until the called method returns its result.

Second, the operation can follow a solicit-response model, in which the web service solicits a response from the client, expecting to receive a response. This model is defined as having both <input> and <output> elements. The <output> element must appear before the <input> element. This order indicates that the operation first sends an output message (solicit) and then receives an input message (response).

Third, the operation can be a one-way invocation, in which the web sevice client sends a message to the web service without expecting to receive a response. This model is defined by a single <input> message with no <output> message. This model indicates that the operation receives input messages (one-way invocation), but doesn’t deliver a response to the client.

Fourth, the operation can be a notification, in which the web services sends a one-way message to the client without expecting a response. This model is defined by a single <output> message and no <input> message. It indicates that the operation sends output messages asynchronously; i.e., the messages are not in response to a request, but can be sent at any time. The operation doesn’t expect a response to the messages it sends.

Tip

For the request-response and solicit-response models, an optional <fault> element can be included. This element refers to another message. A <fault> message will be transmitted if any processing, system, or application errors occur. The <fault> message is delivered to the client in a request-response model and to the web service in the solicit-response model.

The value assigned to the name attribute of each <operation> element must be unique within the scope of the <portType>. The names of the input and output messages must be unique within the <portType>, not just the <operation>. The value assigned to the message attribute of an <input> or <output> element must match one of the names of the <message> elements defined in the same WSDL document or in an imported one.

<binding> Element

A <binding> element is a concrete protocol and data format specification for a <portType> element. It is where you would use one of the standard binding extensions—HTTP, SOAP, or MIME—or create one of your own.

Each protocol has its own wire format. For example, HTTP has a simple header/body format. SOAP, which can exist inside of HTTP and other protocols, has its own header and body. A SOAP message can have attachments included as part of a message.

Our WSDL document has already defined the <operation> elements for this web service. A <binding> element takes the abstract definition of the operations and their input/output messages and maps them to the concrete protocol that the web service uses. Should the <input> element defined in a WSDL document be located in the SOAP header? Should it be in the SOAP body? Should it be in the attachment? Also, how should the data be encoded? Should the supplied schema be used for encoding rules or should literal encoding be used? The <binding> element provides this mapping.

The SOAP binding extension

The SOAP 1.1 binding extension in the WSDL 1.1 specification allows you to use SOAP-specific grammar in the <binding> element. Table 5-2 lists the SOAP-specific elements that are part of the SOAP binding extension.

Table 5-2. SOAP binding extension elements

Element

Synopsis

<soap:binding>

This element signifies that the binding is bound to the SOAP protocol format. It has a transport attributethat specifies the network transport protocol (i.e., HTTP, SMTP, etc.) in which the SOAP message will travel. It also has a style attribute that specifies the default style of each operation in the binding. The possible values for this attribute are rpc and document.

<soap:operation>

This element overrides the style attribute; it identifies the SOAPAction attribute in an HTTP SOAP binding and identifies the encoding system used. Like the <soap:binding> element, it also has a style attribute that indicates the operation’s orientation (i.e., rpc, document). If no style attribute is specified, the style from the <soap:binding> element is inherited. It also has a soapAction attribute, which specifies the value to use for this operation’s SOAPAction HTTP header. It is very important to set the encoding rules. Encoding rules are defined through the use attribute. use=literal means that the type or element definitions referenced by the parts attribute specify the concrete schema for this message. use=encoded means that the message parts refer to abstract types and the concrete schema must be derived from the encoding style defined by the encodingStyle attribute. The advantage of using use=encoded is that you don’t need to follow the XML Schema schemas precisely when serializing the data. For example, though a schema says there’s an element <a> with two children, <b> and <c>, and these are both integers, when encoded use is in effect, SOAP encoding can make <b> a reference to an integer even though the reference may be a string.

<soap:body>

This element specifies how the message parts appear inside the SOAP body element. It is used in both RPC and document-oriented messages, but the style of the enclosing operation has important effects on how the body section is structured.

For RPC-oriented messages, each part is a parameter or a return value and appears inside a wrapper element within the body.

For document-oriented messages, there are no additional wrappers, so the message parts appear directly under the SOAP body element.

<soap:fault>

This element specifies the contents of the SOAP Fault details element and is patterned after the <soap:body> element.

<soap:header>

This element specifies how header information would appear in the SOAP Header element. These entries are transmitted in the <SOAP-ENC:Header> element of the SOAP envelope. It is patterned after the <soap:body> element.

<soap:headerfault>

This element is used to specify a fault that will contain the contents of the SOAP Fault details elements associated with a <soap:header> element. These faults will probably be mustUnderstand faults.

<soap:address>

This element provides the address (a URI) for a <port> child element of the <service> element. A port can have only one address; if the service is written in Java, with a J2EE-based toolkit or library, its address is usually the address of a servlet or JSP. The URI scheme specified for the address must correspond to the transport specified by the <soap:binding> element.

Demonstrating a binding through example

The WSDL file we are working through uses the SOAP binding extension, so it provides an excellent example for explaining how the SOAP binding extension works in reality. This example is fairly long, so it is broken up in various places with explanations of how the binding extension works. It starts with a <binding> tag:

<binding name="ez3950SOAPBinding" type="tns:ez3950PortTypes">

The <binding> tag indicates that we will map a <portType> to a particular protocol. The name attribute defines a unique identifier for this binding; the value of the type attribute must be the name of one of the <portType> elements contained within the same WSDL document or in an imported one. Note that the tns: namespace is used to reference a port type in the existing WSDL:

                    <soap:binding style="rpc" 
        transport="http://schemas.xmlsoap.org/soap/http"/>

The <soap:binding> element is a child of the <binding> element. This element indicates that we will use the SOAP binding extensions to map the operations. To use the HTTP GET/POST binding extension, replace this tag with <http:binding>. To use the MIME binding extension, use the tag <mime:binding>.

The value of the style attribute can be document or rpc. The value given in this tag is used as the default value and applied to the style attribute of each subsequent operation, if a style isn’t defined within the operation itself. The style attribute defaults to document if one is not provided. The transport attribute specifies the SOAP transport protocol that will be used. Is the SOAP packet embedded within HTTP, FTP, SMTP, or something else? In our example, the SOAP transport is HTTP.

Next, we look at the <operation> tag:

    <operation name="init">
        <soap:operation soapAction=""/>
            <input>
               <soap:body use="encoded" 
                        encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
             </input>
             <output>
               <soap:header message="soapHeader" 
                           part="id" 
                          use="encoded" 
                          encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
               <soap:header message="soapHeader" 
                          part="timeout" 
                          use="encoded" 
                          encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
               <soap:body use="encoded" 
                        encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
              </output>
    </operation>

We must include an <operation> here for each <operation> that was defined as part of the <portType> tag. The WSDL file must map the <input>, <output>, and <fault> elements of each element to a SOAP envelope.

The <operation> tag has a <soap:operation> subelement. The <soap:operation> element has a soapAction attribute that defines the value of the SOAPAction header. The URI used for this header represents the action that should occur when the message arrives at its destination. It is not the URI of the web service’s endpoint. In this case, the URI is the empty string (" ").

Since the first operations defined in the WSDL document follow the request-response model, this <soap:operation> defines <input> and <output> tags. The <input> tag has a <soap:body> subelement. The <soap:body> element defines how the message parts should appear inside of a SOAP body. The required use attribute defines how the data is encoded inside of the SOAP packet. If the value is encoded, as in this example, then the value of the encodingStyle attribute references a URI that indicates how the data should be encoded. If the value of the use attribute is literal, then the definition of the message provided within the WSDL document is written into the SOAP body without using another encoding mechanism.

In addition to defining a single <soap:body> element, the <input> and <output> elements can have zero or more <soap:header> elements. The <soap:header> element defines the content that should be included in a SOAP header as part of an envelope. Our example identifies two items included in the SOAP header for the output message. The use and encodingStyle attributes operate the same way as they do for the <soap:body> element. Individual parts, as opposed to whole messages, are included in a SOAP header. The value of the message attribute refers-0.75 to an abstract <message> already defined in the same WSDL document. The value of the part attribute identifies the part of the <message> element that should be included within the SOAP header.

If you refer to the <message> definitions earlier in this chapter, one of the messages was named soapHeader. The soapHeader message had two parts defined: id and timeout. Both parts are included as part of the SOAP header for the output message. Though our example pulled all of the SOAP header fields from a single message definition, you can pull the fields from any other message contained in the same WSDL document.

The next few pages continue the listing of the <binding> for the Z39.50 ASN.1 sample. It shows how each operation behavior is represented using the SOAP binding extension elements:

<operation name="search">
    <soap:operation soapAction=""/>
    <input>
        <soap:header message="soapHeader" part="id" use="encoded" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
        <soap:body use="encoded" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    </input>
    <output>
        <soap:header message="soapHeader" part="id" use="encoded" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
        <soap:header message="soapHeader" part="timeout" use="encoded" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
        <soap:body use="encoded" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    </output>
</operation>

<operation name="present">
    <soap:operation soapAction=""/>
    <input>
        <soap:header message="soapHeader" part="id" use="encoded" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
        <soap:body use="encoded" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    </input>
    <output>
        <soap:header message="soapHeader" part="id" use="encoded" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
        <soap:header message="soapHeader" part="timeout" use="encoded" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
        <soap:body use="encoded" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    </output>
</operation>

<operation name="sort">
   <soap:operation soapAction=""/>
   <input>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </input>
   <output>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:header message="soapHeader" part="timeout" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </output>
</operation>

<operation name="scan">
   <soap:operation soapAction=""/>
   <input>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </input>
   <output>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:header message="soapHeader" part="timeout" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </output>
</operation>

<operation name="delete">
   <soap:operation soapAction=""/>
   <input>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </input>
   <output>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:header message="soapHeader" part="timeout" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </output>
</operation>

<operation name="resourceReport">
   <soap:operation soapAction=""/>
   <input>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </input>
   <output>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:header message="soapHeader" part="timeout" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </output>
</operation>

<operation name="extendedService">
   <soap:operation soapAction=""/>
   <input>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </input>
   <output>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:header message="soapHeader" part="timeout" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </output>
</operation>

<operation name="close">
   <soap:operation soapAction=""/>
   <input>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </input>
   <output>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </output>
</operation>

<operation name="close">
   <soap:operation soapAction=""/>
   <output>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:header message="soapHeader" part="timeout" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </output>
   <input>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </input>
</operation>

<operation name="accessControl">
   <soap:operation soapAction=""/>
   <output>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:header message="soapHeader" part="timeout" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </output>
   <input>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </input>
</operation>

<operation name="resourceControl">
   <soap:operation soapAction=""/>
   <output>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:header message="soapHeader" part="timeout" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </output>
   <input>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </input>
</operation>

<operation name="segment">
   <soap:operation soapAction=""/>
   <output>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:header message="soapHeader" part="timeout" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </output>
</operation>

<operation name="triggerResourceControl">
   <soap:operation soapAction=""/>
   <input>
       <soap:header message="soapHeader" part="id" use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
       <soap:body use="encoded" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   </input>
</operation>

</binding>

This section discusses only the SOAP binding extension; extensions and elements are also defined for the HTTP and MIME binding extensions. They are similar to the SOAP binding extensions, but use different elements to reference different portions of their packets. Refer to the WSDL specification to learn how each of these binding extensions operates.

<service> Element

Even though there was a lot of text in the <binding> element and its subelements, a careful eye might notice that the binding never referenced the URL at which the web service is actually located! The <service> element typically appears at the end of a WSDL document and identifies a web service. Please note that some WSDL documents do not contain a <service> definition. The primary purpose of a WSDL document is to describe the abstract interface. A <service> element is used only when describing the actual endpoint of a service.

A web service is a grouping of one or more <port> elements. A <port> element represents a single endpoint (or access point) for the web service. Given this definition, you can create a web service that is conceptually whole, but operates out of several different URLs. Here is the <service> definition for the Z39.50 ASN.1 sample:

<service name="Oxford University Libraries">
  <documentation>
    Z39.50 Server for Oxford University Libraries
  </documentation>
  <port name="OLIS" binding="ez:ez3950SOAPBinding">
    <soap:address location="http://jafer.las.ox.ac.uk/ez3950"/>
  </port>	
</service>

A <service> element has an optional <documentation> subelement that describes the web service. It also contains one or more <port> subelements. The <port> element has a name attribute that provides a unique identifier for this endpoint. It also contains a binding attribute that references the name of a <binding> element contained within the same WSDL document or in an imported one.

The <port> element has a <soap:address> subelement—an element defined as part of the SOAP binding extension. The <soap:address> element identifies the URL of the web service. If this service used a different binding extension, this element would be different as well.

The end of the example!

That’s it! We have made it to the end of the WSDL sample—a complete, working WSDL file. We didn’t leave out any portions of this file along the way, so if you have been able to follow up to this point, you are well on your way to becoming a WSDL master.



[9] The XML Schema recommendation has three parts: a primer (http://www.w3.org/TR/xmlschema-0/), structures (http://www.w3.org/TR/xmlschema-1/), and datatypes (http://www.w3.org/TR/xmlschema-2/).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset