LibraryPrintFeedback

Writing WSDL Contracts

Version 7.1

December 2012
Trademark Disclaimer
Third Party Acknowledgements

Updated: 08 Jan 2014

Table of Contents

1. Introducing WSDL Contracts
Structure of a WSDL document
WSDL elements
Designing a contract
2. Defining Logical Data Units
Mapping data into logical data units
Adding data units to a contract
XML Schema simple types
Defining complex data types
Defining data structures
Defining arrays
Defining types by extension
Defining types by restriction
Defining enumerated types
Defining elements
3. Defining Logical Messages Used by a Service
4. Defining Your Logical Interfaces
Index

List of Tables

2.1. Complex type descriptor elements
3.1. Part data type attributes
4.1. Operation message elements
4.2. Attributes of the input and output elements

List of Examples

2.1. Schema entry for a WSDL contract
2.2. Defining an element with a simple type
2.3. Simple Structure
2.4. A complex type
2.5. Simple complex choice type
2.6. Simple complex type with occurrence constraints
2.7. Simple complex type with minOccurs set to zero
2.8. Complex type with an attribute
2.9. Complex type array
2.10. Syntax for a SOAP array derived using wsdl:arrayType
2.11. Definition of a SOAP array
2.12. Syntax for a SOAP array derived using an element
2.13. Type defined by extension
2.14. Using int as the base type
2.15. SSN simple type description
2.16. Syntax for an enumeration
2.17. widgetSize enumeration
3.1. Reused part
3.2. personalInfo lookup method
3.3. RPC WSDL message definitions
3.4. Wrapped document WSDL message definitions
4.1. personalInfo lookup interface
4.2. personalInfo lookup port type

The recommended approach to design services is to define your services in WSDL and XML Schema before writing any code. When hand-editing WSDL documents you must make sure that the document is valid, as well as correct. To do this you must have some familiarity with WSDL. You can find the standard on the W3C web site, www.w3.org.

A WSDL document is made up of the following elements:

When defining a service, the first thing you must consider is how the data used as parameters for the exposed operations is going to be represented. Unlike applications that are written in a programming language that uses fixed data structures, services must define their data in logical units that can be consumed by any number of applications. This involves two steps:

  1. Breaking the data into logical units that can be mapped into the data types used by the physical implementations of the service

  2. Combining the logical units into messages that are passed between endpoints to carry out the operations

This chapter discusses the first step. Defining Logical Messages Used by a Service discusses the second step.

The interfaces used to implement a service define the data representing operation parameters as XML documents. If you are defining an interface for a service that is already implemented, you must translate the data types of the implemented operations into discreet XML elements that can be assembled into messages. If you are starting from scratch, you must determine the building blocks from which your messages are built, so that they make sense from an implementation standpoint.

Depending on how you choose to create your WSDL contract, creating new data definitions requires varying amounts of knowledge. The Fuse Services Framework GUI tools provide a number of aids for describing data types using XML Schema. Other XML editors offer different levels of assistance. Regardless of the editor you choose, it is a good idea to have some knowledge about what the resulting contract should look like.

Defining the data used in a WSDL contract involves the following steps:

  1. Determine all the data units used in the interface described by the contract.

  2. Create a types element in your contract.

  3. Create a schema element, shown in Example 2.1, as a child of the type element.

    The targetNamespace attribute specifies the namespace under which new data types are defined. The remaining entries should not be changed.


  4. For each complex type that is a collection of elements, define the data type using a complexType element. See Defining data structures.

  5. For each array, define the data type using a complexType element. See Defining arrays.

  6. For each complex type that is derived from a simple type, define the data type using a simpleType element. See Defining types by restriction.

  7. For each enumerated type, define the data type using a simpleType element. See Defining enumerated types.

  8. For each element, define it using an element element. See Defining elements.

XML Schema provides a flexible and powerful mechanism for building complex data structures from its simple data types. You can create data structures by creating a sequence of elements and attributes. You can also extend your defined types to create even more complex types.

In addition to building complex data structures, you can also describe specialized types such as enumerated types, data types that have a specific range of values, or data types that need to follow certain patterns by either extending or restricting the primitive types.

In XML Schema, data units that are a collection of data fields are defined using complexType elements. Specifying a complex type requires three pieces of information:

For example, the structure shown in Example 2.3 is be defined in XML Schema as a complex type with two elements.


Example 2.4 shows one possible XML Schema mapping for the structure shown in Example 2.3.


You define the data fields that make up a structure using element elements. Every complexType element should contain at least one element element. Each element element in the complexType element represents a field in the defined data structure.

To fully describe a field in a data structure, element elements have two required attributes:

In addition to name and type, element elements have two other commonly used optional attributes: minOcurrs and maxOccurs. These attributes place bounds on the number of times the field occurs in the structure. By default, each field occurs only once in a complex type. Using these attributes, you can change how many times a field must or can appear in a structure. For example, you can define a field, previousJobs, that must occur at least three times, and no more than seven times, as shown in Example 2.6.


You can also use the minOccurs to make the age field optional by setting the minOccurs to zero as shown in Example 2.7. In this case age can be omitted and the data will still be valid.


Fuse Services Framework supports two methods for defining arrays in a contract. The first is define a complex type with a single element whose maxOccurs attribute has a value greater than one. The second is to use SOAP arrays. SOAP arrays provide added functionality such as the ability to easily define multi-dimensional arrays and to transmit sparsely populated arrays.

SOAP arrays are defined by deriving from the SOAP-ENC:Array base type using the wsdl:arrayType element. The syntax for this is shown in Example 2.10.


Using this syntax, TypeName specifies the name of the newly-defined array type. ElementType specifies the type of the elements in the array. ArrayBounds specifies the number of dimensions in the array. To specify a single dimension array use []; to specify a two-dimensional array use either [][] or [,].

For example, the SOAP Array, SOAPStrings, shown in Example 2.11, defines a one-dimensional array of strings. The wsdl:arrayType attribute specifies the type of the array elements, xsd:string, and the number of dimensions, with [] implying one dimension.


You can also describe a SOAP Array using a simple element as described in the SOAP 1.1 specification. The syntax for this is shown in Example 2.12.


When using this syntax, the element's maxOccurs attribute must always be set to unbounded.

Like most major coding languages, XML Schema allows you to create data types that inherit some of their elements from other data types. This is called defining a type by extension. For example, you could create a new type called alienInfo, that extends the personalInfo structure defined in Example 2.4 by adding a new element called planet.

Types defined by extension have four parts:

  1. The name of the type is defined by the name attribute of the complexType element.

  2. The complexContent element specifies that the new type will have more than one element.

    [Note]Note

    If you are only adding new attributes to the complex type, you can use a simpleContent element.

  3. The type from which the new type is derived, called the base type, is specified in the base attribute of the extension element.

  4. The new type’s elements and attributes are defined in the extension element, the same as they are for a regular complex type.

For example, alienInfo is defined as shown in Example 2.13.


XML Schema allows you to create new types by restricting the possible values of an XML Schema simple type. For example, you can define a simple type, SSN, which is a string of exactly nine characters. New types defined by restricting simple types are defined using a simpleType element.

The definition of a type by restriction requires three things:

Example 2.15 shows an example of a simple type, SSN, which represents a social security number. The resulting type is a string of the form xxx-xx-xxxx. <SSN>032-43-9876<SSN> is a valid value for an element of this type, but <SSN>032439876</SSN> is not.


Enumerated types in XML Schema are a special case of definition by restriction. They are described by using the enumeration facet which is supported by all XML Schema primitive types. As with enumerated types in most modern programming languages, a variable of this type can only have one of the specified values.

A service’s operations are defined by specifying the logical messages that are exchanged when an operation is invoked. These logical messages define the data that is passed over a network as an XML document. They contain all of the parameters that are a part of a method invocation.

Logical messages are defined using the message element in your contracts. Each logical message consists of one or more parts, defined in part elements.

[Tip]Tip

While your messages can list each parameter as a separate part, the recommended practice is to use only a single part that encapsulates the data needed for the operation.

While RPC style is useful for modeling existing systems, the service’s community strongly favors the wrapped document style. In wrapped document style, each message has a single part. The message’s part references a wrapper element defined in the types element of the contract. The wrapper element has the following characteristics:

  • It is a complex type containing a sequence of elements. For more information see Defining complex data types.

  • If it is a wrapper for an input message:

    • It has one element for each of the method’s input parameters.

    • Its name is the same as the name of the operation with which it is associated.

  • If it is a wrapper for an output message:

    • It has one element for each of the method’s output parameters and one element for each of the method’s inout parameters.

    • Its first element represents the method’s return parameter.

    • Its name would be generated by appending Response to the name of the operation with which the wrapper is associated.

Logical service interfaces are defined using the WSDL portType element. The portType element is a collection of abstract operation definitions. Each operation is defined by the input, output, and fault messages used to complete the transaction the operation represents. When code is generated to implement the service interface defined by a portType element, each operation is converted into a method containing the parameters defined by the input, output, and fault messages specified in the contract.

To define a logical interface in a WSDL contract you must do the following:

  1. Create a portType element to contain the interface definition and give it a unique name. See Port types.

  2. Create an operation element for each operation defined in the interface. See Operations.

  3. For each operation, specify the messages used to represent the operation’s parameter list, return type, and exceptions. See Operation messages.

Logical operations are made up of a set of elements representing the logical messages communicated between the endpoints to execute the operation. The elements that can describe an operation are listed in Table 4.1.


An operation is required to have at least one input or one output element. An operation can have both input and output elements, but it can only have one of each. Operations are not required to have any fault elements, but can, if required, have any number of fault elements.

The elements have the two attributes listed in Table 4.2.


It is not necessary to specify the name attribute for all input and output elements; WSDL provides a default naming scheme based on the enclosing operation’s name. If only one element is used in the operation, the element name defaults to the name of the operation. If both an input and an output element are used, the element name defaults to the name of the operation with either Request or Response respectively appended to the name.

B

binding element, WSDL elements

C

choice element, Complex type varieties
complex types
all type, Complex type varieties
choice type, Complex type varieties
elements, Defining the parts of a structure
occurrence constraints, Defining the parts of a structure
sequence type, Complex type varieties
complexType element, Defining data structures
concrete part, The concrete part

D

definitions element, WSDL elements

L

logical part, The logical part

O

operation element, WSDL elements

P

part element, Defining Logical Messages Used by a Service, Message parts
element attribute, Message parts
name attribute, Message parts
type attribute, Message parts
port element, WSDL elements
portType element, WSDL elements, Port types

S

sequence element, Complex type varieties
service element, WSDL elements

T

types element, WSDL elements