3.3. Step 3: Implement the service

After generating the Site, we need to actually provide some implementation of the service's advertised functionality. Recall that in the example WSDL we defined one service, called MathService. The generation step created a service skeleton stub named MathServiceWSRF Now we will create a new class that subclasses this generated service skeleton stub and overrides all the methods prefixed with the special 4-character sequence "wsa_". One of these methods should be present for each "operation" defined in the WSDL file. Put another way, these methods represent the WSDL operations of the service. For example, "wsa_add" represents the service's "add" operation.

To understand the code you can see in these methods, we must first understand something about Web Service request and response objects.

The important thing to get out of the above is that both requests and responses are objects with the attribute "typecode". But in Python everything is an object, so they could be subclasses of integers or strings or floating-point numbers that just have an extra "typecode" attribute tagging along for the ride. In fact, with this simple service this is exactly the case, and understanding that helps understand some details of the code.

SimpleMathService.py: Save this file somewhere in your PYTHONPATH


from generated.SimpleMath.services.SimpleMath.MathService import MathServiceWSRF

class StatefulWebService(MathServiceWSRF):

    def __init__(self, *args, **kw):
        MathServiceWSRF.__init__(self, *args, **kw)
        self.value = 0(1)

    def wsa_add(self, ps, address, **kw):(2)
        request,response = MathServiceWSRF.wsa_add(self, ps, address, **kw)(3)
        self.value += request(4)
        return request,response

    def wsa_subtract(self, ps, address, **kw):
        request,response = MathServiceWSRF.wsa_subtract(self, ps, address, **kw)
        self.value -= request
        return request,response

    def wsa_getValueRP(self, ps, address, **kw):
        request,response = MathServiceWSRF.wsa_getValueRP(self, ps, address, **kw)
        return request,response.__class__(self.value)(5)
    
(1)
The attribute (self.value) is used to save the state.
(2)
"wsa_" prefixed methods are expected to take these parameters
(3)
Each wsa method is expected to return a python object representing the output message of the corresponding WSDL operation. The base class returns an appropriate instance to us.
(4)
The base class returns a python object representing the input message of the corresponding WSDL operation, this is the request python instance. For the add operation the request is an integer type element, so the request can be added to self.value.
(5)
This one is a little tricky. The response object is just an integer with an additional "typecode" attribute (see request/response discussion above). Integers are immutable, so in order to set the proper value, self.value, a new instance must be created that contains this value. To do this, we get the class of the response with response.__class__, and provide the integer self.value to the class constructor.