We will see how we can add notifications to a service so clients can be notified each time a certain RP is modified. As we did in and , our example will be based, for simplicity, on the SimpleResourceHome resource home.
Our portType will need to extend from a standard WS-Notifications portType called NotificationProducer, which exposes a Subscribe operation that consumers can use to subscribe themselves to a particular topic. Since this examples takes an existing resource property and exposes it as a topic, no additional WSDL code is required beyond extending the NotificationProducer portType. Copy & paste the WSDL at the end of this chapter to "/tmp/MathNPService.wsdl".
% mkdir /tmp/MathNPSite % mv MathNPService.wsdl /tmp/MathNPSite % cd /tmp/MathNPSite % wsdl2web.py --script=client.py --rpy=MathService.rpy MathNPService.wsdl % cat /tmp/MathLTSite/services/MathService.rpy | sed s/MathLTService/MathNPService/g > services/MathService.rpy
![]() | Site is finished! |
![]() | This class has been generated for you, it implements the WS-BaseNotification NotificationProducer operations. |
class MathServiceWSRF(MathService): def GetResourceContext(ps, address): """get a resource context""" return ManagerHome.getInstance().getResourceContext(ps, address) GetResourceContext = staticmethod(GetResourceContext) ... ... def wsa_Subscribe(self, ps, address, **kw):#http://docs.oasis-open.org/wsn/2004/06/wsn-WS-BaseNotification-1.2-draft-01.wsdl SubscribeRequest request,response = MathService.wsa_Subscribe(self, ps, address)
ctx = self.GetResourceContext(ps, address)
assert SubscriptionManager._isInstantiated(),"SubscriptionManager is not instantiated" manager = SubscriptionManager.getInstance()
response._SubscriptionReference = manager.subscribe(request, ctx)
return request,response
![]()
![]() | 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 ZSI.fault import Fault from pyGridWare.utility.scripts.client import GetBasicOptParser, GetPortKWArgs, SetUp from pyGridWare.wsrf.notification import SubscribeUtility from pyGridWare.wsrf.notification.NotificationConsumer import \ NotificationConsumer, NotificationConsumerService from pyGridWare.wsrf.faults.PropertiesFaults import ResourceUnknownFault from generated.MathNPService.stubs import MathNPService as CLIENT def failure(iport): print "Attempt to access Destroyed Resource" try: msg = iport.add(CLIENT.AddInputMessage(1)) except Fault, ex: print "RESOURCE DESTROYED..", exprint '\tcode -- ', ex.code print '\tstring -- ', ex.string print '\tdetail' for d in ex.detail: print '\t\tstring -- %s' %d.string print '\t\ttrace -- %s' %d.trace except Fault, ex: print "Unexpected SOAP Fault...", ex.__class__ reactor.stop() def main(**kw): target = 10 locator = CLIENT.MathServiceLocator() port = locator.getMathPortType(**kw) msg = port.createResource(CLIENT.CreateInputMessage())
print 'Created instance.' iport = locator.getMathPortType(endPointReference=msg.EndpointReference, **kw)
class _NCService(NotificationConsumerService):
def wsa_Notify(self, ps, address, **kw):
request,response = NotificationConsumerService.wsa_Notify(self, ps, address) pyobj = request.NotificationMessage[0].Message value = pyobj.ResourcePropertyValueChangeNotification.NewValue.Any print "NewValue", value if pyobj.ResourcePropertyValueChangeNotification.NewValue.Any != target:
msg = iport.add(CLIENT.AddInputMessage(1)) return request,response print 'Destroy instance.' msg = iport.Destroy(CLIENT.DestroyRequest()) reactor.callLater(0.1, failure, iport) return request,response consumer = NotificationConsumer(notificationClass=_NCService)
consumer.start() request = CLIENT.SubscribeRequest() SubscribeUtility.SimpleTopicExpression(request, consumer,
"http://www.globus.org/namespaces/examples/core/MathService_instance_rp", "Value") msg = iport.Subscribe(request)
msg = iport.add(CLIENT.AddInputMessage(1))
if __name__ == '__main__': op = GetBasicOptParser() (options, args) = op.parse_args() SetUp(options) kw = GetPortKWArgs(options) reactor.callWhenRunning(main, **kw) reactor.run()
![]() | Make sure to start the server first... |
./client.py -u http://127.0.0.1:9080/wsrf/services/MathService -d 0 FtWarning: Creation of InputSource without a URI /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/ZSI-2.0_rc2-py2.4.egg/ZSI/__init__.py:187: SyntaxWarning: The null string should be None, not empty. Created instance. NewValue 1 NewValue 2 NewValue 3 NewValue 4 NewValue 5 NewValue 6 NewValue 7 NewValue 8 NewValue 9 NewValue 10 Destroy instance. Attempt to access Destroyed Resource 'HTTP Error 500' RESOURCE DESTROYED.. Processing Failure pyGridWare.wsrf.faults.PropertiesFaults:ResourceUnknownFault <pyGridWare.wsrf.faults.PropertiesFaults.pyGridWare.wsrf.faults.PropertiesFaults.ResourceUnknownFault instance 178baf8 <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-15T19:40:37Z</ns1:Timestamp></ns2:ResourceUnknownFault>> [trace: build/bdist.darwin-8.5.0-Power_Macintosh/egg/ZSI/twisted/WSresource.py:341:render_POST build/bdist.darwin-8.5.0-Power_Macintosh/egg/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/MathNPSite/services/MathService.rpy:11:wsa_add /private/tmp/MathNPSite/generated/MathNPService/services/MathNPService/MathService.py:20:GetResourceContext /private/tmp/MathNPSite/generated/MathNPService/resource/MathNPService/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] code -- (u'http://schemas.xmlsoap.org/soap/envelope/', u'Server') string -- Processing Failure detail string -- pyGridWare.wsrf.faults.PropertiesFaults:ResourceUnknownFault <pyGridWare.wsrf.faults.PropertiesFaults.pyGridWare.wsrf.faults.PropertiesFaults.ResourceUnknownFault instance 178baf8 <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-15T19:40:37Z</ns1:Timestamp></ns2:ResourceUnknownFault>> trace -- build/bdist.darwin-8.5.0-Power_Macintosh/egg/ZSI/twisted/WSresource.py:341:render_POST build/bdist.darwin-8.5.0-Power_Macintosh/egg/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/MathNPSite/services/MathService.rpy:11:wsa_add /private/tmp/MathNPSite/generated/MathNPService/services/MathNPService/MathService.py:20:GetResourceContext /private/tmp/MathNPSite/generated/MathNPService/resource/MathNPService/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
After subscribing the notification consumer is ready to receive notifications about changes to the Value resource property. After the initial add, control is released to the reactor. Each add will cause a Notify message to be sent to the notification consumer. In this example I keep adding one to the service instance until I'm notified that the Value resource property matches my target value (10). Once this target has been reached, the service instance is destroyed and the function failure is queued to test if the service instance is still available.