Chapter 6. Lifecycle Management

In this chapter we will see the two lifecycle management solutions offered by the WS-ResourceLifetime specification. Since lifecycle management mainly makes sense when we have several resources, the examples will focus on explaining what modifications are necessary to the example seen in (the factory/instance example).

6.1. Immediate destruction

Immediate destruction is the simplest type of lifecycle management. It allows us to request that a resource be destroyed immediately by invoking a destroy operation in the instance service. Notice how, even though the factory service is responsible for creating the resources, destruction must be requested to each individual resource through the instance service.

6.1.1. Overview: Directions to add immediate destruction to our service

Note

The WSDL presented in the last section of this chapter describes a service with WS-ResourceLifetime properties. You can skip most of this section and just generate and install the math service bindings. In this section I present a high level explanation of how to add immediate destruction to the math service.

To add immediate destruction to our service, we need to add the standard WSRF ImmediateResourceTermination portType to our service through compositional inheritance. This portType adds a Destroy operation to our portType that will instruct the current resource to terminate itself immediately. In sum, we need to copy the WSRF ImmediateResourceTermination portType Destroy operation to the MathPortType and add a Destroy binding operation to MathBinding.

Note

After making these changes to the MathService WSDL (or just grab the WSDL at the end of this chapter), save it as "/tmp/MathLTService.wsdl" and use the WSDL to create a new site. Then grab the "MathService.rpy" from the last chapter. The WS-ResourceLifetime operations are implemented for us. This RPY script will work with one modification to an import statement since the directory structure of our generated code is a little different. I'll accomplish this using sed.


% mkdir /tmp/MathLTSite 
% cd /tmp/MathLTSite 
% mv /tmp/MathLTService.wsdl .
% wsdl2web.py --script=client.py --rpy=MathService.rpy MathLTService.wsdl
  ...
  ...
% grep MathLTService services/MathService.rpy 
from generated.MathLTService.services.MathLTService.MathService import MathServiceWSRF

% cat /tmp/MathRPSite/services/MathService.rpy | sed s/MathRPService/MathLTService/g > services/MathService.rpy


6.1.2. Generated WSRF Service: generated/MathLTService/services/MathLTService/MathService.py

Note

This class has been generated for you. The WSRF operations specified in the WSDL definition are implemented in this layer.


class MathServiceWSRF(MathService):

    def GetResourceContext(ps, address):
        """get a resource context"""
        return ManagerHome.getInstance().getResourceContext(ps, address)
    GetResourceContext = staticmethod(GetResourceContext)

    ...
    ...

    def wsa_Destroy(self, ps, address, **kw): (1)
        #http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl DestroyRequest
        request,response = MathService.wsa_Destroy(self, ps, address) (2)
        ctx = MathServiceWSRF.GetResourceContext(ps, address) (3)
        ImmediateResourceTermination.Destroy(ctx) (4)
        return request,response (5)
(1)
Fully functional WSRF Destroy operation, immediately destroys the instance referenced by the EPR.
(2)
Call lower-level service binding stub to set up the response and request python objects.
(3)
Retrieve the ResourceContext of the service instance.
(4)
Request immediate destruction of the service instance.
(5)
Return python object representing the WS-ResourceLifetime Message DestroyResponse

6.1.3. Sample Client

Note

Copy & Paste example..


#!/usr/bin/env python
############################################################################
# Automatically generated by wsdl2web.py
# See LBNLCopyright for copyright notice!
###########################################################################
from twisted.python import log
from twisted.internet import reactor

import ZSI
from pyGridWare.utility.scripts.client import GetBasicOptParser, GetPortKWArgs, SetUp
from generated.MathLTService.stubs import MathLTService as CLIENT


def main(**kw):
    locator = CLIENT.MathServiceLocator() (1)
    port = locator.getMathPortType(**kw) (2)

    msg = port.createResource(CLIENT.CreateInputMessage()) (3)
    iport = locator.getMathPortType(endPointReference=msg.EndpointReference, **kw) (4)
    iport.add(CLIENT.AddInputMessage(100)) (5)
    iport.Destroy(CLIENT.DestroyRequest()) (6)
    try:
        iport.subtract(CLIENT.SubtractInputMessage(99)) (7)
    except ZSI.fault.Fault, ex:
        pass

    reactor.stop()
    print "EXCEPTION: ", ex.__class__ (8)
    print '\tcode   -- ', ex.code
    print '\tstring -- ', ex.string
    print '\targs   -- ', ex.args
    print '\tdetail -- ', ex.detail
    print '\tactor  -- ', ex.actor
    print '\theaderdetail -- ', ex.headerdetail
    print
    print "ZSI Fault:\n", ex.detail[0]
    print

if __name__ == '__main__':
    op = GetBasicOptParser()
    (options, args) = op.parse_args()
    SetUp(options)
    kw = GetPortKWArgs(options)
    reactor.callWhenRunning(main, **kw)
    reactor.run()

(1)
Here we obtain a reference to a MathPortType instance. Notice the factory's URI, where the service is located, and the WS-Addressing URI, which specifies the WS-Addressing version the client should use.
(2)
Once we have the MathPortType, we use it to invoke the createResource operation. This operation returns an endpoint reference, inside a CreateResourceResponse object. This endpoint reference includes both the instance service's URI and the new resource's identifier. In the next client we will take a peek inside the endpoint reference.
(3)
Call the createResource factory method, this returns a CreateOutputMessage instance.
(4)
The CreateOutputMessage contains an EPR, use it to obtain a new MathPortType which will now refer to the instance service.
(5)
We now use the iport to invoke add, this returns successfully.
(6)
We now use the iport to invoke destroy, which immediately destroys the resource.
(7)
Any calls made by the iport will fail now since the resource has been destroyed. Invoking subtract fails, the server returns a SOAP Fault containing a WSRP ResourceUnknownFault.
(8)
ZSI.fault.Fault, SOAP Fault Exception.

6.1.4. Run the client:

Note

Make sure to start the server first...


% ./client.py -u http://127.0.0.1:9080/wsrf/services/MathService -d 0

EXCEPTION:  ZSI.fault.Fault
        code   --  (u'http://schemas.xmlsoap.org/soap/envelope/', u'Server')
        string --  Processing Failure
        args   --  ((u'http://schemas.xmlsoap.org/soap/envelope/', u'Server'), u'Processing Failure', None, [>ZSI.fault.ZSIFaultDetail o140ecb0<], None)
        detail --  [>ZSI.fault.ZSIFaultDetail o140ecb0<]
        actor  --  None
        headerdetail --  None

ZSI Fault:
pyGridWare.wsrf.faults.PropertiesFaults:ResourceUnknownFault
<pyGridWare.wsrf.faults.PropertiesFaults.pyGridWare.wsrf.faults.PropertiesFaults.ResourceUnknownFault instance 16388a0 
<ns2:ResourceUnknownFault xmlns:ns1="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-BaseFaults-1.2-draft-01.xsd" xmlns:ns2="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"><ns1:Timestamp xmlns:ns3="http://www.w3.org/2001/XMLSchema" xmlns:ns4="http://www.w3.org/2001/XMLSchema-instance" ns4:type="ns3:dateTime">2006-04-14T21:27:52Z</ns1:Timestamp></ns2:ResourceUnknownFault>>
[trace: /Users/boverhof/Desktop/Workspace/Python/zsi/ZSI/twisted/WSresource.py:341:render_POST
/Users/boverhof/Desktop/Workspace/Python/zsi/ZSI/twisted/WSresource.py:254:processRequest
/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/pyGridWare-1.2.0rc3-py2.4.egg/pyGridWare/utility/web/resource.py:77:processRequest
/private/tmp/MathLTSite/services/MathService.rpy:19:wsa_subtract
/private/tmp/MathLTSite/generated/MathLTService/services/MathLTService/MathService.py:19:GetResourceContext
/private/tmp/MathLTSite/generated/MathLTService/resource/MathLTService/MathService.py:24:getResourceContext
/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/pyGridWare-1.2.0rc3-py2.4.egg/pyGridWare/resource/ResourceHome.py:52:get]



When subtract is invoked, the endpoint reference that is in the call to GetResourceContext refers to a resource that no longer exists, thus a ResourceUnknownFault is thrown and returned in a SOAP fault exception (ZSI.fault.Fault) to the client.