Chapter 3. Writing a NON-WSRF Stateful Web Service

MathService

In this chapter we are going to write and deploy a simple stateful web service. This service does not use WSRF to keep state information, we'll explore that in the next chapter. Our first web service is an extremely simple calculator, which we'll refer to as MathService. It will provide the following operations:

MathService's internal logic is very simple. When it, a new resource, is created, its stored integer value is initialized to zero. The addition and subtraction operations modify this stored value.

Finally, this first example will be limited to having only one instance, or resource. In the next chapter we will see how we can write a WSRF service that has several resources associated with it, as seen in .

High-tech stuff, huh? Don't worry if this seems a bit lackluster. Since this is going to be our first stateful web service, it's better to start with a small didactic service which we'll gradually improve by adding more complex resource properties, notifications, etc.

The Four Steps

Writing and deploying a WSRF Web Service is easier than you might think. You just have to follow five simple steps.

  1. Define the service's interface. This is done with WSDL.

  2. Create a New WSRF Site. This is done with wsdl2web.py tool.

  3. Implement the service functionality. This is done with Python.

  4. Deploy the service. This is done with Python.

In this first example we're going to go through each step in great detail, explaining what each step accomplishes, and giving detailed instructions on how to perform each step. The rest of the examples in the tutorial will also follow these four steps, but won't repeat the whole explanation of what each step is. So, if you ever find that you don't understand a particular step, you can always come back to this chapter ("Writing Your First Stateful Web Service in 4 Simple Steps") to review the details of that step.

3.1. Step 1: Defining the interface in WSDL

The first step in writing any web service is to define the service interface. We need to specify what our service is going to provide to the outer world. At this point we're not concerned with the inner workings of that service (what algorithms it uses, other systems it interacts with, etc.). We just need to know what operations will be available to our users. In Web Services lingo, the service interface is usually called the port type (usually written portType, to match the XML element name).

As we saw in , there is a special XML language which can be used to specify what operations a web service offers: the Web Service Description Language (WSDL). So, what we need to do in this step is write a description of our MathService using WSDL.

WSDL can be automatically generated from other interface languages, or source code. But at this time, these methods still tend to be buggy and generate overly complex WSDL files. In addition, for a dynamically typed language like Python, it is difficult to generate WSDL from the class definitions. For these and didactic purposes, we will start by generating the WSDL directly.

The goal of this page is not to give a detailed explanation of how to write a WSDL file, but rather to present the WSDL file for this particular example. If you have no idea whatsoever of how to write WSDL, now is a good time to take a look at . Come on, go take a look at the appendix. We'll be waiting for you right here.

3.1.1. The WSDL code

Ok, so supposing you either know WSDL or have visited the WSDL appendix, take a good thorough look at this WSDL code:


<?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:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">


<!--============================================================

                      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:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

        <!-- IMPORT WS-ADDRESSING -->
        <xsd:import namespace="http://schemas.xmlsoap.org/ws/2004/03/addressing" 
             schemaLocation="http://schemas.xmlsoap.org/ws/2004/03/addressing"/>

	<!-- 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"/>

        <!-- UNCOMMENT FOR CHAPTER 4 FACTORY METHOD
	<xsd:element name="create">
		<xsd:complexType/>
	</xsd:element>
	<xsd:element name="createResponse">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element ref="wsa:EndpointReference"/>
                </xsd:sequence>
            </xsd:complexType>
	</xsd:element>
        UNCOMMENT FOR CHAPTER 4 FACTORY METHOD -->

        <!-- UNCOMMENT FOR CHAPTER 4 FACTORY METHOD 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"/>
                    <xsd:element ref="tns:LastOp"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
        UNCOMMENT FOR CHAPTER 4 FACTORY METHOD RESOURCE PROPERTIES -->

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

<!-- UNCOMMENT FOR CHAPTER 4 FACTORY METHOD
<message name="CreateInputMessage">
	<part name="parameters" element="tns:create"/>
</message>
<message name="CreateOutputMessage">
	<part name="parameters" element="tns:createResponse"/>
</message>
UNCOMMENT FOR CHAPTER 4 FACTORY METHOD -->

<!--============================================================

                       P O R T T Y P E
                      
  ============================================================-->

<portType name="MathPortType"
>
<!-- REMOVE PREVIOUS > & UNCOMMENT FOR CHAPTER 4 FACTORY METHOD 
    wsrp:ResourceProperties="tns:MathResourceProperties">
UNCOMMENT FOR CHAPTER 4 FACTORY METHOD -->

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

        <!-- UNCOMMENT FOR CHAPTER 4 FACTORY METHOD
	<operation name="createResource">
		<input message="tns:CreateInputMessage"/>
		<output message="tns:CreateOutputMessage"/>
	</operation>
        UNCOMMENT FOR CHAPTER 4 FACTORY METHOD -->


</portType>

<!--============================================================

                       B I N D I N G
                      
  ============================================================-->
<binding name="MathBinding" type="MathPortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>

    <wsdl:operation name="add">
      <soap:operation soapAction=""/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>

    <wsdl:operation name="subtract">
      <soap:operation soapAction=""/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>

    <wsdl:operation name="getValueRP">
      <soap:operation soapAction=""/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>

    <!-- UNCOMMENT FOR CHAPTER 4 FACTORY METHOD
    <wsdl:operation name="createResource">
      <soap:operation soapAction=""/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
    UNCOMMENT FOR CHAPTER 4 FACTORY METHOD -->
</binding>

<!--============================================================

                       S E R V I C E
                      
  ============================================================-->
<service name="MathService">
    <port name="MathPort" binding="MathBinding">
       <soap:address location="http://localhost:8080/wsrf/services/"/>
    </port>
</service>

</definitions>

If you know WSDL, you'll recognize this as a pretty straightforward WSDL file which defines three operations: add, subtract, and getValueRP (along with all the necessary messages and types). By the way, the "RP" in getValueRP stands for "Resource Property" because, in a Web Services terminology, the integer value is a property of the MathService resource.