...write a GWSDL description of your Grid Service

This "How to..." appendix shows how to write a simple GWSDL description of a PortType in a step-by-step fashion. Although it should be easy to extrapolate from the example we are going to see and create other simple GWSDL files, this is not meant as an exhaustive guide of GWSDL or WSDL. 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.

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

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

  public void subtract(int a);

  public int getValue();
}

This is the interface of many of the examples of the tutorial.

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

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="MathService"
  targetNamespace="http://www.globus.org/namespaces/2004/02/progtutorial/MathService"
  xmlns:tns="http://www.globus.org/namespaces/2004/02/progtutorial/MathService"
  xmlns:ogsi="http://www.gridforum.org/namespaces/2003/03/OGSI"
  xmlns:gwsdl="http://www.gridforum.org/namespaces/2003/03/gridWSDLExtensions"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://schemas.xmlsoap.org/wsdl/">

</definitions>

This tag has two important attributes:

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 an OGSI GWSDL file with definitions we'll need later on.

<import location="../../ogsi/ogsi.gwsdl"
  namespace="http://www.gridforum.org/namespaces/2003/03/OGSI"/>

Now we're going to define our PortType, using the <gwsdl:portType> tag (if this were ordinary WSDL, we would simply use a <portType> tag). Notice how we declared the gwsdl namespace in the root element.

<definitions ... ">

<gwsdl:portType name="MathPortType" extends="ogsi:GridService">
  <operation name="add">
    <input message="tns:AddInputMessage"/>
    <output message="tns:AddOutputMessage"/>
    <fault name="Fault" message="ogsi:FaultMessage"/>
  </operation>
  <operation name="subtract">
    <input message="tns:SubtractInputMessage"/>
    <output message="tns:SubtractOutputMessage"/>
    <fault name="Fault" message="ogsi:FaultMessage"/>
  </operation>
  <operation name="getValue">
    <input message="tns:GetValueInputMessage"/>
    <output message="tns:GetValueOutputMessage"/>
    <fault name="Fault" message="ogsi:FaultMessage"/>
  </operation>
</gwsdl:portType>

</definitions>

The <gwsdl:portType> tag has two important attributes:

Inside the <gwsdl:portType> we have an <operation> tag for each method in our PortType: add, subtract, and getValue. They are all very similar, so let's take a closer look at the add <operation> tag:

<operation name="add">
  <input message="tns:AddInputMessage"/>
  <output message="tns:AddOutputMessage"/>
  <fault name="Fault" message="ogsi:FaultMessage"/>
</operation>

The <operation> tag has an <input> tag, an <output> tag and a <fault> tag. These three tags have a message attribute, which specifies what message should be passed along when the operation is invoked (input message), when it returns successfully (output message) or when an error occurs (fault message). The fault message is defined in the OGSI GWSDL we included earlier. However, we'll need to define the messages of our operations. The following are the messages for the add operation. The messages for the subtract operation are identical (just change 'add' for 'subtract' :-)

<?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>

&lt!-- 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).

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:

<types>
<xsd:schema targetNamespace="http://www.globus.org/namespaces/2004/02/progtutorial/MathService"
  attributeFormDefault="qualified"
  elementFormDefault="qualified"
  xmlns="http://www.w3.org/2001/XMLSchema">

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

  <xsd:element name="addResponse">
    <xsd:complexType/>
  </xsd:element>

</xsd:schema>
</types>

&lt!-- Messages -->

&lt!-- 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 GWSDL document.

The add element (which, remember, is part of the input message of the add operation) contains an element called value which is the parameter of the add operation (notice how the type attribute is equal to xsd:int, the integer type in XML Schema).

On the other hand, the addResponse element (part of the output message of the add operation, i.e. the return value) contains no elements at all, since the add operation doesn't return anything.

The rest of the <messages> and element types are defined in a similar fashion. The whole GWSDL file would be:

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="MathService"
  targetNamespace="http://www.globus.org/namespaces/2004/02/progtutorial/MathService"
  xmlns:tns="http://www.globus.org/namespaces/2004/02/progtutorial/MathService"
  xmlns:ogsi="http://www.gridforum.org/namespaces/2003/03/OGSI"
  xmlns:gwsdl="http://www.gridforum.org/namespaces/2003/03/gridWSDLExtensions"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://schemas.xmlsoap.org/wsdl/">

<import location="../../ogsi/ogsi.gwsdl"
  namespace="http://www.gridforum.org/namespaces/2003/03/OGSI"/>

<types>
<xsd:schema targetNamespace="http://www.globus.org/namespaces/2004/02/progtutorial/MathService"
  attributeFormDefault="qualified"
  elementFormDefault="qualified"
  xmlns="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="add">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="value" type="xsd:int"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="addResponse">
    <xsd:complexType/>
  </xsd:element>
  <xsd:element name="subtract">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="value" type="xsd:int"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="subtractResponse">
    <xsd:complexType/>
  </xsd:element>
  <xsd:element name="getValue">
    <xsd:complexType/>
  </xsd:element>
  <xsd:element name="getValueResponse">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="value" type="xsd:int"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
</types>

<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="GetValueInputMessage">
  <part name="parameters" element="tns:getValue"/>
</message>
<message name="GetValueOutputMessage">
  <part name="parameters" element="tns:getValueResponse"/>
</message>

<gwsdl:portType name="MathPortType" extends="ogsi:GridService">
  <operation name="add">
    <input message="tns:AddInputMessage"/>
    <output message="tns:AddOutputMessage"/>
    <fault name="Fault" message="ogsi:FaultMessage"/>
  </operation>
  <operation name="subtract">
    <input message="tns:SubtractInputMessage"/>
    <output message="tns:SubtractOutputMessage"/>
    <fault name="Fault" message="ogsi:FaultMessage"/>
  </operation>
  <operation name="getValue">
    <input message="tns:GetValueInputMessage"/>
    <output message="tns:GetValueOutputMessage"/>
    <fault name="Fault" message="ogsi:FaultMessage"/>
  </operation>
</gwsdl:portType>

</definitions>

Summing up, the basic steps involved in writing a GWSDL file would be the following:

  1. Write the root element <definitions>

  2. Write the <gwsdl:PortType>

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

  4. Write the <types>

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 GWSDL. 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.