A.1. ...write a WSDL description of your WSRF stateful Web service

This HOWTO shows you how to write a simple WSDL description of a portType in a step-by-step fashion. Although it should be easy to follow those same steps to create other simple WSDL files, this is not meant as an exhaustive WSDL guide. Anyone seeking to write more complex portTypes (for example, passing complex classes instead of primitive types -int. string, etc.- as parameters or return values) should definitely consider learning WSDL and XML Schema. A couple of references are provided at the end of the appendix in case you want to learn more.

That said, let's start writing WSDL! We are going to write the WSDL description corresponding to the following Java interface:

public interface Math
{
  public void add(int a);

  public void subtract(int a);
  
  public int getValueRP();
}

Furthermore, our portType will have two resource properties: "value" of type integer and "lastOp" of type string. This is the interface used in many of the tutorial's examples.

A.1.1. The bare bones of our WSDL file

First of all, we have to write the root element of the WSDL file, which is <definitions>.

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="MathService"
    targetNamespace="http://www.globus.org/namespaces/examples/core/MathService_instance"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:tns="http://www.globus.org/namespaces/examples/core/MathService_instance"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
    xmlns:wsrpw="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
    xmlns:wsdlpp="http://www.globus.org/namespaces/2004/10/WSDLPreprocessor"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

</definitions>

This tag has two important attributes:

  • name: The 'name' of the WSDL file. Not related with the name of the portType.

  • targetNamespace: The target namespace of the WSDL file. This means that all the PortTypes and operations defined in this WSDL file will belong to this namespace.

[Tip]XML Namespaces

XML namespaces are basically a way of grouping similar 'things' together. We're using the somewhat vague term 'things' because XML Namespaces are used not only in WSDL, but in many XML languages, so just about anything can be grouped into an XML Namespace (not only portTypes and operations, which are specific to WSDL). The XML Namespace has to be a valid URI, but it doesn't necessarily have to be real (in fact, if you try to point your web browser to the URI we're using, you'll get a Page Not Found error).

The root element is also used to declare all the namespaces we are going to use. Notice how the tns namespace is the Target NameSpace. The rest of the namespace declarations should be copied verbatim.

Next up, we need to import a WSDL file with definitions we'll need later on.

<wsdl:import 
    namespace=
    "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
    location="../../wsrf/properties/WS-ResourceProperties.wsdl" />
[Note]

In general, we will import the WSDL file of every WSRF specification (such as WS-ResourceProperties) we intend to use in our service. As we'll see later on, we will need to import other WSDL files as we start looking at other parts of the WSRF specification.

A.1.2. The Port Type

Now we're going to define our portType, using the <portType> tag:

<?xml version="1.0" encoding="UTF-8"?>
<definitions ... >

<portType name="MathPortType" 
    wsdlpp:extends="wsrpw:GetResourceProperty"
    wsrp:ResourceProperties="tns:MathResourceProperties">

	<operation name="add">
		<input message="tns:AddInputMessage"/>
		<output message="tns:AddOutputMessage"/>
	</operation>
        
	<operation name="subtract">
		<input message="tns:SubtractInputMessage"/>
		<output message="tns:SubtractOutputMessage"/>
	</operation>

	<operation name="getValueRP">
		<input message="tns:GetValueRPInputMessage"/>
		<output message="tns:GetValueRPOutputMessage"/>
	</operation>

</portType>

</definitions>

The <portType> tag has three important attributes:

  • name: Name of the PortType.

  • wsdlpp:extends: This is not a standard part of WSDL, but part of the WSDLPreprocessor namespace provided by Globus (notice how we declared wsdlpp in the namespace declarations). If we were writing strict WSDL, the only way of including operations and portTypes from WSRF specifications would be to actually copy and paste those definitions from the spec's WSDL file into our own WSDL file. This, of course, is very error-prone. For our convenience, Globus provides a WSDL Preprocessor that does that automatically for us. By using the wsdlpp:extends attribute, we are telling the WSDL Preprocessor to include the GetResourceProperty portType from the WS-ResourceProperties WSDL file. This portType is first used in Chapter 6, Resource Properties.

  • wsrp:ResourceProperties: This attribute specifies what the service's resource properties are. The meaning of this attribute is explained further on.

[Warning]

Make sure you read the warning regarding the WSDL Preprocessor in Section 3.1.2, “WSRF and Globus-specific features of WSDL”.

Inside the <portType> we have an <operation> tag for the three operations exposed in our web service: add, subtract, and getValueRP. They are all very similar, so let's just take a closer look at add's <operation> tag:

<operation name="add">
  <input message="tns:AddInputMessage"/>
  <output message="tns:AddOutputMessage"/>
</operation>

The <operation> tag has an <input> tag and an <output>. These two tags have a message attribute, which specifies what message should be passed along when the operation is invoked (input message) and when it returns successfully (output message). So, we'll need to define the messages of our operations.

A.1.3. The messages

The following are the messages for the add operation. The messages for the subtract and getValueRP operations are identical.

<?xml version="1.0" encoding="UTF-8"?>
<definitions ... >

<message name="AddInputMessage">
	<part name="parameters" element="tns:add"/>
</message>
<message name="AddOutputMessage">
	<part name="parameters" element="tns:addResponse"/>
</message>

<!-- PortType -->

</definitions>

Notice how the name of each message has to be the same as the one written in the message attribute of the <input> and <output> tags. However, it turns out messages are composed of <part>s! Our messages will only have one part, in which a single XML element is passed along. For example, the AddOutputMessage will contain the addResponse element (notice how it is part of the tns namespace, the target namespace).

A.1.4. The response and request types

The definition of these elements is done using XML Schema inside a new tag: the <types> tag. The following would be the definition of the add and addResponse elements:

<?xml version="1.0" encoding="UTF-8"?>
<definitions ... >

<types>
<xsd:schema targetNamespace="http://www.globus.org/namespaces/examples/core/MathService_instance"
    xmlns:tns="http://www.globus.org/namespaces/examples/core/MathService_instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    

	<!-- REQUESTS AND RESPONSES -->
	
	<xsd:element name="add" type="xsd:int"/>
	<xsd:element name="addResponse">
		<xsd:complexType/>
	</xsd:element>

	<!-- more type definitions -->
        
</xsd:schema>
</types>

<!-- Messages -->

<!-- PortType -->

</definitions>

The <types> tag contains an <xsd:schema> tag. The attributes of the <xsd:schema> should be copied verbatim, except the targetNamespace, which should be the same as the target namespace of the WSDL document.

The add element (which, remember, is part of the input message of the add operation) represents the single input parameter of our add operation, and thus has an attribute specifying its type (notice how the type attribute is equal to xsd:int, the integer type in XML Schema).

If we had wanted our add operation to receive two parameters, we would have to declare the add element like this:

<xsd:element name="add">
    <xsd:complexType>
    <xsd:sequence>
        <xsd:element name="a1" type="xsd:int"/>
        <xsd:element name="a2" type="xsd:int"/>
    </xsd:sequence>
    </xsd:complexType>
</xsd:element>

In this case we're saying that the add operation has two parameters (a1 and a2) of type integer. Notice that to specify multiple parameters we need to use the XML Schema complexType tag.

As for the addResponse element (part of the output message of the add operation, i.e. the return value), it contains an empty complexType, since the add operation doesn't return anything.

The type definitions for the subtract and getValueRP operation are defined similarly.

A.1.5. Declaring the resource properties

We are very nearly done. There is only one thing left to do: declare our service's resource properties. This is also done in the <types> part of the WSDL document, inside the <schema> tag along with all the declarations we have just seen.

First of all, let's take another quick look at our portType:

<portType name="MathPortType" 
    wsdlpp:extends="wsrpw:GetResourceProperty"
    wsrp:ResourceProperties="tns:MathResourceProperties">

	<!-- operations --">

</portType>

The wsrp:ResourceProperties attribute specifies what the service's resource properties are. In our case, the resource properties are contained in an element called MathResourceProperties which we must declare in the <types> part of the WSDL document.

<types>
<xsd:schema targetNamespace="http://www.globus.org/namespaces/examples/core/MathService_instance"
    xmlns:tns="http://www.globus.org/namespaces/examples/core/MathService_instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">


	<!-- Requests and responses declarations-->


	
	<xsd:element name="Value" type="xsd:int"/>
	<xsd:element name="LastOp" type="xsd:string"/>

	<xsd:element name="MathResourceProperties">
	<xsd:complexType>
		<xsd:sequence>
			<xsd:element ref="tns:Value" minOccurs="1" maxOccurs="1"/>
			<xsd:element ref="tns:LastOp" minOccurs="1" maxOccurs="1"/>
		</xsd:sequence>
	</xsd:complexType>
	</xsd:element>
	
        
</xsd:schema>
</types>

This declaration specifies that MathResourceProperties contains two resource properties, Value and LastOp, each of which appear only once (we could specify array resource properties by changing the values of maxOccurs).

A.1.6. Summing up...

The whole WSDL file would be:

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="MathService"
    targetNamespace="http://www.globus.org/namespaces/examples/core/MathService_instance"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:tns="http://www.globus.org/namespaces/examples/core/MathService_instance"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
    xmlns:wsrpw="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
    xmlns:wsdlpp="http://www.globus.org/namespaces/2004/10/WSDLPreprocessor"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<wsdl:import 
    namespace=
    "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
    location="../../wsrf/properties/WS-ResourceProperties.wsdl" />


<!==============================================================

                      T Y P E S
                      
  ==============================================================>
<types>
<xsd:schema targetNamespace="http://www.globus.org/namespaces/examples/core/MathService_instance"
    xmlns:tns="http://www.globus.org/namespaces/examples/core/MathService_instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    

	<!-- REQUESTS AND RESPONSES -->
	
	<xsd:element name="add" type="xsd:int"/>
	<xsd:element name="addResponse">
		<xsd:complexType/>
	</xsd:element>

	<xsd:element name="subtract" type="xsd:int"/>
	<xsd:element name="subtractResponse">
		<xsd:complexType/>
	</xsd:element>

	<xsd:element name="getValueRP">
		<xsd:complexType/>
	</xsd:element>
	<xsd:element name="getValueRPResponse" type="xsd:int"/>


	<!-- RESOURCE PROPERTIES -->

	<xsd:element name="Value" type="xsd:int"/>
	<xsd:element name="LastOp" type="xsd:string"/>

	<xsd:element name="MathResourceProperties">
	<xsd:complexType>
		<xsd:sequence>
			<xsd:element ref="tns:Value" minOccurs="1" maxOccurs="1"/>
			<xsd:element ref="tns:LastOp" minOccurs="1" maxOccurs="1"/>
		</xsd:sequence>
	</xsd:complexType>
	</xsd:element>
        
</xsd:schema>
</types>


<!==============================================================

                       M E S S A G E S
                      
  ==============================================================>
<message name="AddInputMessage">
	<part name="parameters" element="tns:add"/>
</message>
<message name="AddOutputMessage">
	<part name="parameters" element="tns:addResponse"/>
</message>

<message name="SubtractInputMessage">
	<part name="parameters" element="tns:subtract"/>
</message>
<message name="SubtractOutputMessage">
	<part name="parameters" element="tns:subtractResponse"/>
</message>

<message name="GetValueRPInputMessage">
	<part name="parameters" element="tns:getValueRP"/>
</message>
<message name="GetValueRPOutputMessage">
	<part name="parameters" element="tns:getValueRPResponse"/>
</message>



<!==============================================================

                       P O R T T Y P E
                      
  ==============================================================>
<portType name="MathPortType" 
    wsdlpp:extends="wsrpw:GetResourceProperty"
    wsrp:ResourceProperties="tns:MathResourceProperties">

	<operation name="add">
		<input message="tns:AddInputMessage"/>
		<output message="tns:AddOutputMessage"/>
	</operation>
        
	<operation name="subtract">
		<input message="tns:SubtractInputMessage"/>
		<output message="tns:SubtractOutputMessage"/>
	</operation>

	<operation name="getValueRP">
		<input message="tns:GetValueRPInputMessage"/>
		<output message="tns:GetValueRPOutputMessage"/>
	</operation>

</portType>

</definitions>

Summing up, the basic steps involved in writing a WSDL file for a WSRF web service would be the following:

  1. Write the root element <definitions>

  2. Write the <portType>

  3. Write an input and output <message> for each operation in the PortType.

  4. Write the <types>. This includes declaring the request and response elements, along with the resource properties.

As any experienced WSDL writer should be able to tell you, there are many ways of writing WSDL (ways that allow you to write more compact WSDL). However, this is the most step-by-step method, which is probably best for beginners. Furthermore, remember this is just a very brief guide on how to write very basic WSDL. You should have no trouble adding basic operations such as void multiply(int a), but more complex portTypes will require more advanced knowledge of WSDL and XML Schema.