Pages

1/16/2008

Web Service : Service Definition

Service Definition

This section describes the core elements of the WSDL language. Binding extensions for SOAP, HTTP and MIME are included in Sections 3, 4 and 5.

2.1 WSDL Document Structure

A WSDL document is simply a set of definitions. There is a definitions element at the root, and definitions inside. The grammar is as follows:

<wsdl:definitions name="nmtoken"? targetNamespace="uri"?>

<import namespace="uri" location="uri"/>*

<wsdl:documentation .... /> ?

<wsdl:types> ?

<wsdl:documentation .... />?

<xsd:schema .... />*

<-- extensibility element --> *

</wsdl:types>

<wsdl:message name="nmtoken"> *

<wsdl:documentation .... />?

<part name="nmtoken" element="qname"? type="qname"?/> *

</wsdl:message>

<wsdl:portType name="nmtoken">*

<wsdl:documentation .... />?

<wsdl:operation name="nmtoken">*

<wsdl:documentation .... /> ?

<wsdl:input name="nmtoken"? message="qname">?

<wsdl:documentation .... /> ?

</wsdl:input>

<wsdl:output name="nmtoken"? message="qname">?

<wsdl:documentation .... /> ?

</wsdl:output>

<wsdl:fault name="nmtoken" message="qname"> *

<wsdl:documentation .... /> ?

</wsdl:fault>

</wsdl:operation>

</wsdl:portType>

<wsdl:binding name="nmtoken" type="qname">*

<wsdl:documentation .... />?

<-- extensibility element --> *

<wsdl:operation name="nmtoken">*

<wsdl:documentation .... /> ?

<-- extensibility element --> *

<wsdl:input> ?

<wsdl:documentation .... /> ?

<-- extensibility element -->

</wsdl:input>

<wsdl:output> ?

<wsdl:documentation .... /> ?

<-- extensibility element --> *

</wsdl:output>

<wsdl:fault name="nmtoken"> *

<wsdl:documentation .... /> ?

<-- extensibility element --> *

</wsdl:fault>

</wsdl:operation>

</wsdl:binding>

<wsdl:service name="nmtoken"> *

<wsdl:documentation .... />?

<wsdl:port name="nmtoken" binding="qname"> *

<wsdl:documentation .... /> ?

<-- extensibility element -->

</wsdl:port>

<-- extensibility element -->

</wsdl:service>

<-- extensibility element --> *

</wsdl:definitions>

Services are defined using six major elements:

  • types, which provides data type definitions used to describe the messages exchanged.
  • message, which represents an abstract definition of the data being transmitted. A message consists of logical parts, each of which is associated with a definition within some type system.
  • portType, which is a set of abstract operations. Each operation refers to an input message and output messages.
  • binding, which specifies concrete protocol and data format specifications for the operations and messages defined by a particular portType.
  • port, which specifies an address for a binding, thus defining a single communication endpoint.
  • service, which is used to aggregate a set of related ports.

These elements will be described in detail in Sections 2.2 to 2.7. In the rest of this section we describe the rules introduced by WSDL for naming documents, referencing document definitions, using language extensions and adding contextual documentation.

2.1.1 Document Naming and Linking

WSDL documents can be assigned an optional name attribute of type NCNAME that serves as a lightweight form of documentation. Optionally, a targetNamespace attribute of type URI may be specified. The URI MUST NOT be a relative URI.

WSDL allows associating a namespace with a document location using an import statement:

<definitions .... >

<import namespace="uri" location="uri"/> *

</definitions>

A reference to a WSDL definition is made using a QName. The following types of definitions contained in a WSDL document may be referenced:

  • WSDL definitions: service, port, message, bindings, and portType
  • Other definitions: if additional definitions are added via extensibility, they SHOULD use QName linking.

Each WSDL definition type listed above has its own name scope (i.e. port names and message names never conflict). Names within a name scope MUST be unique within the WSDL document.

The resolution of QNames in WSDL is similar to the resolution of QNames described by the XML Schemas specification [11].

2.1.2 Authoring Style

The use of the import element allows the separation of the different elements of a service definition into independent documents, which can then be imported as needed. This technique helps writing clearer service definitions, by separating the definitions according to their level of abstraction. It also maximizes the ability to reuse service definitions of all kinds. As a result, WSDL documents structured in this way are easier to use and maintain. Example 2 below shows how to use this authoring style to define the service presented in Example 1. Here we separate the definitions in three documents: data type definitions, abstract definitions, and specific service bindings. The use of this mechanism is of course not limited to the definitions explicitly presented in the example, which uses only language elements defined in this specification. Other types of definitions based on additional language extensions can be encoded and reused in a similar fashion.

Example 2. Alternative authoring style for the service in Example 1.

http://example.com/stockquote/stockquote.xsd

<?xml version="1.0"?>

<schema targetNamespace="http://example.com/stockquote/schemas"

xmlns="http://www.w3.org/2000/10/XMLSchema">

<element name="TradePriceRequest">

<complexType>

<all>

<element name="tickerSymbol" type="string"/>

</all>

</complexType>

</element>

<element name="TradePrice">

<complexType>

<all>

<element name="price" type="float"/>

</all>

</complexType>

</element>

</schema>

http://example.com/stockquote/stockquote.wsdl

<?xml version="1.0"?>

<definitions name="StockQuote"

targetNamespace="http://example.com/stockquote/definitions"

xmlns:tns="http://example.com/stockquote/definitions"

xmlns:xsd1="http://example.com/stockquote/schemas"

xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

xmlns="http://schemas.xmlsoap.org/wsdl/">

<import namespace="http://example.com/stockquote/schemas"

location="http://example.com/stockquote/stockquote.xsd"/>

<message name="GetLastTradePriceInput">

<part name="body" element="xsd1:TradePriceRequest"/>

</message>

<message name="GetLastTradePriceOutput">

<part name="body" element="xsd1:TradePrice"/>

</message>

<portType name="StockQuotePortType">

<operation name="GetLastTradePrice">

<input message="tns:GetLastTradePriceInput"/>

<output message="tns:GetLastTradePriceOutput"/>

</operation>

</portType>

</definitions>

http://example.com/stockquote/stockquoteservice.wsdl

<?xml version="1.0"?>

<definitions name="StockQuote"

targetNamespace="http://example.com/stockquote/service"

xmlns:tns="http://example.com/stockquote/service"

xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

xmlns:defs="http://example.com/stockquote/definitions"

xmlns="http://schemas.xmlsoap.org/wsdl/">

<import namespace="http://example.com/stockquote/definitions"

location="http://example.com/stockquote/stockquote.wsdl"/>

<binding name="StockQuoteSoapBinding" type="defs:StockQuotePortType">

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

<operation name="GetLastTradePrice">

<soap:operation soapAction="http://example.com/GetLastTradePrice"/>

<input>

<soap:body use="literal"/>

</input>

<output>

<soap:body use="literal"/>

</output>

</operation>

</binding>

<service name="StockQuoteService">

<documentation>My first service</documentation>

<port name="StockQuotePort" binding="tns:StockQuoteBinding">

<soap:address location="http://example.com/stockquote"/>

</port>

</service>

</definitions>

2.1.3 Language Extensibility and Binding

In WSDL the term binding refers to the process associating protocol or data format information with an abstract entity like a message, operation, or portType. WSDL allows elements representing a specific technology (referred to here as extensibility elements) under various elements defined by WSDL. These points of extensibility are typically used to specify binding information for a particular protocol or message format, but are not limited to such use. Extensibility elements MUST use an XML namespace different from that of WSDL. The specific locations in the document where extensibility elements can appear are described in detail in section A3.

Extensibility elements are commonly used to specify some technology specific binding. To distinguish whether the semantic of the technology specific binding is required for communication or optional, extensibility elements MAY place a wsdl:required attribute of type boolean on the element. The default value for required is false. The required attribute is defined in the namespace "http://schemas.xmlsoap.org/wsdl/".

Extensibility elements allow innovation in the area of network and message protocols without having to revise the base WSDL specification. WSDL recommends that specifications defining such protocols also define any necessary WSDL extensions used to describe those protocols or formats.

See Sections 3, 4, and 5 for examples of extensibility elements defined as part of the base WSDL specification.

2.1.4 Documentation

WSDL uses the optional wsdl:document element as a container for human readable documentation. The content of the element is arbitrary text and elements ("mixed" in XSD). The documentation element is allowed inside any WSDL language element.

2.2 Types

The types element encloses data type definitions that are relevant for the exchanged messages. For maximum interoperability and platform neutrality, WSDL prefers the use of XSD as the canonical type system, and treats it as the intrinsic type system.

<definitions .... >

<types>

<xsd:schema .... />*

</types>

</definitions>

The XSD type system can be used to define the types in a message regardless of whether or not the resulting wire format is actually XML, or whether the resulting XSD schema validates the particular wire format. This is especially interesting if there will be multiple bindings for the same message, or if there is only one binding but that binding type does not already have a type system in widespread use. In these cases, the recommended approach for encoding abstract types using XSD is as follows:

  • Use element form (not attribute).
  • Don't include attributes or elements that are peculiar to the wire encoding (e.g. have nothing to do with the abstract content of the message). Some examples are soap:root, soap:encodingStyle, xmi:id, xmi:name.
  • Array types should extend the Array type defined in the SOAP v1.1 encoding schema (http://schemas.xmlsoap.org/soap/encoding/) (regardless of whether the resulting form actually uses the encoding specified in Section 5 of the SOAP v1.1 document). Use the name ArrayOfXXX for array types (where XXX is the type of the items in the array). The type of the items in the array and the array dimensions are specified by using a default value for the soapenc:arrayType attribute. At the time of this writing, the XSD specification does not have a mechanism for specifying the default value of an attribute which contains a QName value. To overcome this limitation, WSDL introduces the arrayType attribute (from namespace http://schemas.xmlsoap.org/wsdl/) which has the semantic of providing the default value. If XSD is revised to support this functionality, the revised mechanism SHOULD be used in favor of the arrayType attribute defined by WSDL.
  • Use the xsd:anyType type to represent a field/parameter which can have any type.

However, since it is unreasonable to expect a single type system grammar can be used to describe all abstract types present and future, WSDL allows type systems to be added via extensibility elements. An extensibility element may appear under the types element to identify the type definition system being used and to provide an XML container element for the type definitions. The role of this element can be compared to that of the schema element of the XML Schema language.

<definitions .... >

<types>

<-- type-system extensibility element --> *

</types>

</definitions>

2.3 Messages

Messages consist of one or more logical parts. Each part is associated with a type from some type system using a message-typing attribute. The set of message-typing attributes is extensible. WSDL defines several such message-typing attributes for use with XSD:

  • element. Refers to an XSD element using a QName.
  • type. Refers to an XSD simpleType or complexType using a QName.

Other message-typing attributes may be defined as long as they use a namespace different from that of WSDL. Binding extensibility elements may also use message-typing attributes.

The syntax for defining a message is as follows. The message-typing attributes (which may vary depending on the type system used) are shown in bold.

<definitions .... >

<message name="nmtoken"> *

<part name="nmtoken" element="qname"? type="qname"?/> *

</message>

</definitions>

The message name attribute provides a unique name among all messages defined within the enclosing WSDL document.

The part name attribute provides a unique name among all the parts of the enclosing message.

2.3.1 Message Parts

Parts are a flexible mechanism for describing the logical abstract content of a message. A binding may reference the name of a part in order to specify binding-specific information about the part. For example, if defining a message for use with RPC, a part MAY represent a parameter in the message. However, the bindings must be inspected in order to determine the actual meaning of the part.

Multiple part elements are used if the message has multiple logical units. For example, the following message consists of a Purchase Order and an Invoice.

<definitions .... >

<types>

<schema .... >

<element name="PO" type="tns:POType"/>

<complexType name="POType">

<all>

<element name="id" type="string/>

<element name="name" type="string"/>

<element name="items">

<complexType>

<all>

<element name="item" type="tns:Item" minOccurs="0" maxOccurs="unbounded"/>

</all>

</complexType>

</element>

</all>

</complexType>

<complexType name="Item">

<all>

<element name="quantity" type="int"/>

<element name="product" type="string"/>

</all>

</complexType>

<element name="Invoice" type="tns:InvoiceType"/>

<complexType name="InvoiceType">

<all>

<element name="id" type="string"/>

</all>

</complexType>

</schema>

</types>

<message name="PO">

<part name="po" element="tns:PO"/>

<part name="invoice" element="tns:Invoice"/>

</message>

</definitions>

However, if the message contents are sufficiently complex, then an alternative syntax may be used to specify the composite structure of the message using the type system directly. In this usage, only one part may be specified. In the following example, the body is either a purchase order, or a set of invoices.

<definitions .... >

<types>

<schema .... >

<complexType name="POType">

<all>

<element name="id" type="string/>

<element name="name" type="string"/>

<element name="items">

<complexType>

<all>

<element name="item" type="tns:Item" minOccurs="0" maxOccurs="unbounded"/>

</all>

</complexType>

</element>

</all>

</complexType>

<complexType name="Item">

<all>

<element name="quantity" type="int"/>

<element name="product" type="string"/>

</all>

</complexType>

<complexType name="InvoiceType">

<all>

<element name="id" type="string"/>

</all>

</complexType>

<complexType name="Composite">

<choice>

<element name="PO" minOccurs="1" maxOccurs="1" type="tns:POType"/>

<element name="Invoice" minOccurs="0" maxOccurs="unbounded" type="tns:InvoiceType"/>

</choice>

</complexType>

</schema>

</types>

<message name="PO">

<part name="composite" type="tns:Composite"/>

</message>

</definitions>

2.3.2 Abstract vs. Concrete Messages

Message definitions are always considered to be an abstract definition of the message content. A message binding describes how the abstract content is mapped into a concrete format. However, in some cases, the abstract definition may match the concrete representation very closely or exactly for one or more bindings, so those binding(s) will supply little or no mapping information. However, another binding of the same message definition may require extensive mapping information. For this reason, it is not until the binding is inspected that one can determine "how abstract" the message really is.

2.4 Port Types

A port type is a named set of abstract operations and the abstract messages involved.

<wsdl:definitions .... >

<wsdl:portType name="nmtoken">

<wsdl:operation name="nmtoken" .... /> *

</wsdl:portType>

</wsdl:definitions>

The port type name attribute provides a unique name among all port types defined within in the enclosing WSDL document.

An operation is named via the name attribute.

WSDL has four transmission primitives that an endpoint can support:

  • One-way. The endpoint receives a message.
  • Request-response. The endpoint receives a message, and sends a correlated message.
  • Solicit-response. The endpoint sends a message, and receives a correlated message.
  • Notification. The endpoint sends a message.

WSDL refers to these primitives as operations. Although request/response or solicit/response can be modeled abstractly using two one-way messages, it is useful to model these as primitive operation types because:

  • They are very common.
  • The sequence can be correlated without having to introduce more complex flow information.
  • Some endpoints can only receive messages if they are the result of a synchronous request response.
  • A simple flow can algorithmically be derived from these primitives at the point when flow definition is desired.

Although request/response or solicit/response are logically correlated in the WSDL document, a given binding describes the concrete correlation information. For example, the request and response messages may be exchanged as part of one or two actual network communications.

Although the base WSDL structure supports bindings for these four transmission primitives, WSDL only defines bindings for the One-way and Request-response primitives. It is expected that specifications that define the protocols for Solicit-response or Notification would also include WSDL binding extensions that allow use of these primitives.

Operations refer to the messages involved using the message attribute of type QName. This attribute follows the rules defined by WSDL for linking (see section 2.1.2).

2.4.1 One-way Operation

The grammar for a one-way operation is:

<wsdl:definitions .... > <wsdl:portType .... > *

<wsdl:operation name="nmtoken">

<wsdl:input name="nmtoken"? message="qname"/>

</wsdl:operation>

</wsdl:portType >

</wsdl:definitions>

The input element specifies the abstract message format for the one-way operation.

2.4.2 Request-response Operation

The grammar for a request-response operation is:

<wsdl:definitions .... >

<wsdl:portType .... > *

<wsdl:operation name="nmtoken" parameterOrder="nmtokens">

<wsdl:input name="nmtoken"? message="qname"/>

<wsdl:output name="nmtoken"? message="qname"/>

<wsdl:fault name="nmtoken" message="qname"/>*

</wsdl:operation>

</wsdl:portType >

</wsdl:definitions>

The input and output elements specify the abstract message format for the request and response, respectively. The optional fault elements specify the abstract message format for any error messages that may be output as the result of the operation (beyond those specific to the protocol).

Note that a request-response operation is an abstract notion; a particular binding must be consulted to determine how the messages are actually sent: within a single communication (such as a HTTP request/response), or as two independent communications (such as two HTTP requests).

2.4.3 Solicit-response Operation

The grammar for a solicit-response operation is:

<wsdl:definitions .... >

<wsdl:portType .... > *

<wsdl:operation name="nmtoken" parameterOrder="nmtokens">

<wsdl:output name="nmtoken"? message="qname"/>

<wsdl:input name="nmtoken"? message="qname"/>

<wsdl:fault name="nmtoken" message="qname"/>*

</wsdl:operation>

</wsdl:portType >

</wsdl:definitions>

The output and input elements specify the abstract message format for the solicited request and response, respectively. The optional fault elements specify the abstract message format for any error messages that may be output as the result of the operation (beyond those specific to the protocol).

Note that a solicit-response operation is an abstract notion; a particular binding must be consulted to determine how the messages are actually sent: within a single communication (such as a HTTP request/response), or as two independent communications (such as two HTTP requests).

2.4.4 Notification Operation

The grammar for a notification operation is:

<wsdl:definitions .... >

<wsdl:portType .... > *

<wsdl:operation name="nmtoken">

<wsdl:output name="nmtoken"? message="qname"/>

</wsdl:operation>

</wsdl:portType >

</wsdl:definitions>

The output element specifies the abstract message format for the notification operation.

2.4.5 Names of Elements within an Operation

The name attribute of the input and output elements provides a unique name among all input and output elements within the enclosing port type.

In order to avoid having to name each input and output element within an operation, WSDL provides some default values based on the operation name. If the name attribute is not specified on a one-way or notification message, it defaults to the name of the operation. If the name attribute is not specified on the input or output messages of a request-response or solicit-response operation, the name defaults to the name of the operation with "Request"/"Solicit" or "Response" appended, respectively.

Each fault element must be named to allow a binding to specify the concrete format of the fault message. The name of the fault element is unique within the set of faults defined for the operation.

2.4.6 Parameter Order within an Operation

Operations do not specify whether they are to be used with RPC-like bindings or not. However, when using an operation with an RPC-binding, it is useful to be able to capture the original RPC function signature. For this reason, a request-response or solicit-response operation MAY specify a list of parameter names via the parameterOrder attribute (of type nmtokens). The value of the attribute is a list of message part names separated by a single space. The value of the parameterOrder attribute MUST follow the following rules:

  • The part name order reflects the order of the parameters in the RPC signature
  • The return value part is not present in the list
  • If a part name appears in both the input and output message, it is an in/out parameter
  • If a part name appears in only the input message, it is an in parameter
  • If a part name appears in only the output message, it is an out parameter

Note that this information serves as a "hint" and may safely be ignored by those not concerned with RPC signatures. Also, it is not required to be present, even if the operation is to be used with an RPC-like binding.

2.5 Bindings

A binding defines message format and protocol details for operations and messages defined by a particular portType. There may be any number of bindings for a given portType. The grammar for a binding is as follows:

<wsdl:definitions .... >

<wsdl:binding name="nmtoken" type="qname"> *

<-- extensibility element (1) --> *

<wsdl:operation name="nmtoken"> *

<-- extensibility element (2) --> *

<wsdl:input name="nmtoken"? > ?

<-- extensibility element (3) -->

</wsdl:input>

<wsdl:output name="nmtoken"? > ?

<-- extensibility element (4) --> *

</wsdl:output>

<wsdl:fault name="nmtoken"> *

<-- extensibility element (5) --> *

</wsdl:fault>

</wsdl:operation>

</wsdl:binding>

</wsdl:definitions>

The name attribute provides a unique name among all bindings defined within in the enclosing WSDL document.

A binding references the portType that it binds using the type attribute. This QName value follows the linking rules defined by WSDL (see section 2.1.2).

Binding extensibility elements are used to specify the concrete grammar for the input (3), output (4), and fault messages (5). Per-operation binding information (2) as well as per-binding information (1) may also be specified.

An operation element within a binding specifies binding information for the operation with the same name within the binding's portType. Since operation names are not required to be unique (for example, in the case of overloading of method names), the name attribute in the operation binding element might not be enough to uniquely identify an operation. In that case, the correct operation should be identified by providing the name attributes of the corresponding wsdl:input and wsdl:output elements.

A binding MUST specify exactly one protocol.

A binding MUST NOT specify address information.

2.6 Ports

A port defines an individual endpoint by specifying a single address for a binding.

<wsdl:definitions .... >

<wsdl:service .... > *

<wsdl:port name="nmtoken" binding="qname"> *

<-- extensibility element (1) -->

</wsdl:port>

</wsdl:service>

</wsdl:definitions>

The name attribute provides a unique name among all ports defined within in the enclosing WSDL document.

The binding attribute (of type QName) refers to the binding using the linking rules defined by WSDL (see Section 2.1.2).

Binding extensibility elements (1) are used to specify the address information for the port.

A port MUST NOT specify more than one address.

A port MUST NOT specify any binding information other than address information.

2.7 Services

A service groups a set of related ports together:

<wsdl:definitions .... >

<wsdl:service name="nmtoken"> *

<wsdl:port .... />*

</wsdl:service>

</wsdl:definitions>

The name attribute provides a unique name among all services defined within in the enclosing WSDL document.

Ports within a service have the following relationship:

  • None of the ports communicate with each other (e.g. the output of one port is not the input of another).
  • If a service has several ports that share a port type, but employ different bindings or addresses, the ports are alternatives. Each port provides semantically equivalent behavior (within the transport and message format limitations imposed by each binding). This allows a consumer of a WSDL document to choose particular port(s) to communicate with based on some criteria (protocol, distance, etc.).
  • By examining it's ports, we can determine a service's port types. This allows a consumer of a WSDL document to determine if it wishes to communicate to a particular service based whether or not it supports several port types. This is useful if there is some implied relationship between the operations of the port types, and that the entire set of port types must be present in order to accomplish a particular task.

No comments: