5.5. Client code

Our client application will make calls to some of the WS-ResourceProperties portTypes. The next example will use more complex resource properties and then we will see how to invoke the rest of the portTypes.

In the examples that follow instances of python stub classes are directly manipulated and access through attributes. The python attributes of an object represent XML Schema element declarations, there is a predictable mapping. Above the tests are a few relevant XML Schema samples.


#!/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.MathRPService.stubs import MathRPService as CLIENT


def GetResourceProperty(iport):
    # Replace 
    reactor.stop()

def SetResourceProperty(iport):
    # Replace 
    reactor.stop()

def GetMultipleResourceProperties(iport):
    # Replace 
    reactor.stop()


def main(*argv, **kw):
    locator = CLIENT.MathServiceLocator()
    port = locator.getMathPortType(**kw)

    msg = port.createResource(CLIENT.CreateInputMessage())
    iport = locator.getMathPortType(endPointReference=msg.EndpointReference, **kw)

    if len(argv) > 0:
        method = eval(argv[0])
        method(iport)

    reactor.stop()


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

Note

Copy & Paste to client.py, we'll add the missing sections below.

5.5.1. Invoking GetResourceProperty

XML Schema GetResourceProperty global element declaration(GED), its type is QName. XML Schema GetResourcePropertyResponse GED. It contains an element wildcard any, and the value of its maxOccurs facet is unbounded.


<!-- ========== Message Types for GetResourceProperty  ============ -->

       <xsd:element name="GetResourceProperty" 
                    type="xsd:QName" />

       <xsd:element name="GetResourcePropertyResponse" >
         <xsd:complexType>
           <xsd:sequence>
             <xsd:any  minOccurs="0" maxOccurs="unbounded" />
           </xsd:sequence>
         </xsd:complexType>
       </xsd:element>


def GetResourceProperty(iport):
    for i in range(10):
        iport.add(CLIENT.AddInputMessage(i))

    iport.subtract(CLIENT.SubtractInputMessage(10))

    msg = iport.GetResourceProperty(\(1)
        CLIENT.GetResourcePropertyRequest(\
            ("http://www.globus.org/namespaces/examples/core/MathService_instance_rp","Value"),
        )
    )

    print "MSG: ", msg (2)
    print "PROPERTIES: ", msg.Any
    print "PROPERTY: ", msg.Any[0] (3)
    print "CORRECT: ", msg.Any[0] == sum(range(10)) - 10

% ./client.py -u http://127.0.0.1:9080/wsrf/services/MathService -d 0 GetResourceProperty
MSG:  <pyGridWare.generated.types.resourceproperties.GetResourcePropertyResponse_Holder instance at 0x13480a8>
PROPERTIES:  [35]
PROPERTY:  35
CORRECT:  True
(1)
We first invoke the GetResourceProperty operation on our portType. Take into account that, since our MathPortType portType extends from the standard GetResourceProperty portType, our portType also includes a GetResourceProperty operation. The only parameter we have to include is the QName, which is specified as a namespace name tuple, of the RP we want to retrieve.
(2)
The return value is of type GetResourcePropertyResponse, a python stub class.
(3)
We can access the RPs' values from the GetResourcePropertyResponse python object. The GetResourcePropertyResponse's any wildcard element will contain zero, one, or many RPs. The RP values are set at the _any python attribute name, but it's easier to use the corresponding Any python property which works just like an attribute. Since the any element is repeatable (maxOccurs="unbounded"), the attribute's value will be a list.

5.5.2. Invoking SetResourceProperties to update

XML Schema Type Definiton and GED for Update and SetResourceProperties.


       <xsd:complexType name="UpdateType">
         <xsd:sequence>
           <xsd:any processContents="lax"
                    minOccurs="1" maxOccurs="unbounded" />
         </xsd:sequence>
       </xsd:complexType>
       <xsd:element name="Update" 
                    type="wsrp:UpdateType"/>

       <xsd:element name="SetResourceProperties">
         <xsd:complexType>
           <xsd:choice minOccurs="0" maxOccurs="unbounded">
             <xsd:element ref="wsrp:Insert"/>
             <xsd:element ref="wsrp:Update"/>
             <xsd:element ref="wsrp:Delete"/>
           </xsd:choice>
         </xsd:complexType>
       </xsd:element>

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

Note

Replace test function and add a SetResourceProperties call


def SetResourceProperties(iport):
    iport.add(CLIENT.AddInputMessage(111))

    # Take the Value ResourceProperty and create a new instance
    from generated.MathRPService.properties.MathRPService.MathService.MathPort import MathPortType
    properties = MathPortType() (1)
    properties.Value = 100 (2)
    req = CLIENT.SetResourcePropertiesRequest() (3)

    req.Update = req.new_Update() (4)
    req.Update.Any = properties.Value (5)

    smsg = iport.SetResourceProperties(req) (6)

    assert ("http://www.globus.org/namespaces/examples/core/MathService_instance_rp","Value") ==\
        (properties.Value.typecode.nspname, properties.Value.typecode.pname),\
        "Grab Value ResourceProperty GED's namespace, name."

    msg = iport.GetResourceProperty(\
        CLIENT.GetResourcePropertyRequest(\
            (properties.Value.typecode.nspname, properties.Value.typecode.pname),
        )
    )

    reactor.stop()
    print "SetResourceProperties MSG: ", smsg
    print "PROPERTIES: ", msg.Any
    print "CORRECT: ", msg.Any[0] == 100


%./client.py -u http://127.0.0.1:9080/wsrf/services/MathService -d 0 SetResourceProperties
SetResourceProperties MSG:  <pyGridWare.generated.types.resourceproperties.SetResourcePropertiesResponse_Holder instance at 0x107d080>
PROPERTIES:  [100]
CORRECT:  True
(1)
Create an instance of the ResourceProperties we would like to remotely access.
(2)
Set the new Value. This wraps the integer in a serializable object.
(3)
Create a SetResourcePropertiesRequest object which will represents the SetResourcePropertiesRequest message specified in the WSDL. This object can contain insert, update, and delete actions.
(4)
Create a python object and set it in the SetResourceProperties instance's _Update python attribute to specify an update. TODO: Use new metaclass for pyclass to make this transparent once I'm convinced it's stable.
(5)
Add the Value RP to the list of RP's to be updated.
(6)
Finally, we invoke SetResourceProperties.

5.5.3. Invoking GetMultipleResourceProperties

Note

Replace test function and add a GetMultipleResourceProperties call


def GetMultipleResourceProperties(iport):
    for i in range(10):
        iport.add(CLIENT.AddInputMessage(i))

    req = CLIENT.GetMultipleResourcePropertiesRequest() (1)

    req.ResourceProperty = ("http://www.globus.org/namespaces/examples/core/MathService_instance_rp","Value")(2)
    req.ResourceProperty.append(\ (3)
       ("http://www.globus.org/namespaces/examples/core/MathService_instance_rp","LastOp")
    )

    msg = iport.GetMultipleResourceProperties(req)

    reactor.stop()
    print "MSG: ", msg
    for any in msg.Any: (4)
        print "Resource Property(%s) = " %any.__class__,any

% ./client.py -u http://127.0.0.1:9080/wsrf/services/MathService -d 0 GetMultipleResourceProperties
MSG:  <pyGridWare.generated.types.resourceproperties.GetMultipleResourcePropertiesResponse_Holder instance at 0x134a468>
Resource Property(<class 'pyGridWare.generated.types.mathservicerp._Value_immutable_holder'>) =  45
Resource Property(<class 'pyGridWare.generated.types.mathservicerp._LastOp_immutable_holder'>) =  ADDITION
(1)
First, we need to create a GetMultipleResourcePropertiesRequest object that represents the WSDL input message for the GetMultipleResourceProperties operation.
(2)
The local element ResourceProperty is a repreatable QName type. Thus to specify the RPs Value and LastOp, we need to append (namespace, name) tuples representing these GEDs. This probably looks confusing because the underlying architecture will automatically put the tuple into a list because the maxOccurs facet is greater than one, so the append operation is actually appending to a list (legal) not a tuple (illegal).
(3)
Next, we invoke the GetMultipleResourceProperties. The return value is of a GetMultipleResourcePropertiesResponse_Holder instance, which represents the WSDL output message for the GetMultipleResourceProperties operation.
(4)
The RPs returned are accessed through the Any python property (it wraps the _any python attribute), which is a list representing the <any> wildcard element (WS-ResourceProperties). In this example we request and received two RPs. The RPs are instances of class _Value_immutable_holder and _LastOp_immutable_holder.