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.
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
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.
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).
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>
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.
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.
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 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
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.
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.
[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/).