The addition of the resource properties declaration has resulted in several changes to the generated code. We'll now examine the files where these changes have occured.
generated/MathService/services/MathService/MathService.py: The generated service skeleton consists of two special methods for resource context access(GetResourceContext) and creation(NewResourceContextMathPort). The other "wsa_" methods are not standard WSRF operations (eg. WS-RP getResourceProperty, WS-BaseNotification Notify), thus it remains up to you to define their functionality. We'll see in the next examples how pyGridWare handles the generation of standard WSRF operations. What does this generated service skeleton provide us with for these non-standard WSRF operations? It provides us with python object representations of the request and response messages.
class MathServiceWSRF(MathService): def GetResourceContext(ps, address): """get a resource context""" return ManagerHome.getInstance().getResourceContext(ps, address) GetResourceContext = staticmethod(GetResourceContext) def NewResourceContextMathPort(cls, url): """create a new resource context""" ctx = MathPortTypeContext() ctx.setAddress(url) home = ctx.getResourceHome() key = home.create() home.add(ctx, key) ctx.setResourceID(key) return ctx NewResourceContextMathPort = classmethod(NewResourceContextMathPort) def wsa_createResource(self, ps, address, **kw): #http://www.globus.org/namespaces/examples/core/MathService_instance CreateInputMessage request,response = MathService.wsa_createResource(self, ps, address) return request,response def wsa_add(self, ps, address, **kw): #http://www.globus.org/namespaces/examples/core/MathService_instance AddInputMessage request,response = MathService.wsa_add(self, ps, address) return request,response def wsa_subtract(self, ps, address, **kw): #http://www.globus.org/namespaces/examples/core/MathService_instance SubtractInputMessage request,response = MathService.wsa_subtract(self, ps, address) return request,response def wsa_getValueRP(self, ps, address, **kw): #http://www.globus.org/namespaces/examples/core/MathService_instance GetValueRPInputMessage request,response = MathService.wsa_getValueRP(self, ps, address) return request,response
generated/MathService/resource/MathService/MathService.py: The resource home and the resource context. A MathPortTypeContext instance will have an attribute properties that is an instance of the MathPortType resource properties class.
class ManagerHome(PersistentResourceHome, Singleton): def getResourceContext(self, ps, address): key = AddressingUtils.getResourceID(ps, Key.typecode) return self.get(key) class MathPortTypeContext(ResourceContext): def __init__(self, properties_class=MathPortType): ResourceContext.__init__(self, properties_class) def setResourceID(self, resourceID): ResourceContext.setResourceID(self, Key(resourceID)) MathPortTypeContext.home = ManagerHome.getInstance()
generated/MathService/properties/MathService/MathService/MathPort.py: The resource properties; each element of the resource property declaration is accessed and modified through a python property.
class MathPortType(ResourceProperties): declaration = GED("http://www.globus.org/namespaces/examples/core/MathService_instance","MathResourceProperties") def __init__(self): ResourceProperties.__init__(self) def getValue(self): return self.getResourceProperty("http://www.globus.org/namespaces/examples/core/MathService_instance","Value") def setValue(self, pyobj): return self.setResourceProperty("http://www.globus.org/namespaces/examples/core/MathService_instance","Value", pyobj) Value = property(getValue, setValue, None, "RP element Value") def getLastOp(self): return self.getResourceProperty("http://www.globus.org/namespaces/examples/core/MathService_instance","LastOp") def setLastOp(self, pyobj): return self.setResourceProperty("http://www.globus.org/namespaces/examples/core/MathService_instance","LastOp", pyobj) LastOp = property(getLastOp, setLastOp, None, "RP element LastOp")
The service class MathServiceWSRF has two special methods.
GetResourceContext: Uses an EPR to retrieve a resource context.
NewResourceContextMathPort: Creates a new resource context and return it, we need to call this method in our factory method(s).
Our client only needs to know the URI of the factory service (MathFactoryService). With it, it can invoke the createResource operation. This will return an endpoint reference, that contains the URI and key of the recently created resource.
The ResourceHome is used to create and store ResourceContexts.
The factory method createResource has to create a new resource. This necessarily has to be done through the resource home, which is in charge of managing all the resources. However, we have to locate our resource home first. Fortunately, we don't have to deal directly with the resource home, we call NewResourceContextMathPort in the factory method to get a new resource.
Finally, the EPR is returned to the client in the response instance.
Skip...
Once the createResource call has finished, the client will have the WS-Resource's endpoint reference. In all future calls, this endpoint reference will be passed along transparently in all our invocations. In other words, when we call add or subtract, the service class will know what resource we're referring to. So, let's take a close look at what happens when we invoke the add operation, as shown in Figure 4-4.
The client invokes the add operation for the (MathService).
The add operation is stateless. First the resource context must be retrieved. The resource identifier is in the endpoint reference that is included in the address parameter. Fortunately, the generated GetResourceContext(ps, address) method will read the EPR and return resource context it refers to.
Once we have the resource context, the service can directly access state information, such as the "Value" and the "LastOp", in the resource properties "ctx.properties".
Accessing "ctx.properties.Value" retrieves the state.
Modifying "ctx.properties.Value" saves the state.
Finally, set "ctx.properties.LastOp" to "ADDITION".