Hello, I've been playing a bit with the current implementation of WebService that is availalble from Zope.org. I have tried to adapt the ServiceProxy to a Zope Product, so that a user can simply drop such a WebServiceProxy in a Folder, type-in the URL of a WSDL file and then call the methods described in the WSDL on the WebServiceProxy.
A first prototype incorporated a ServiceProxy instance and offered hard-coded methods: def __init__(self, id): self.id = id self.gsp = ServiceProxy("http://api.google.com/GoogleSearch.wsdl") security.declarePublic('doSpellingSuggestion') def doSpellingSuggestion(self, key, phrase): "Checks the phrase for correct spelling" return self.gsp.doSpellingSuggestion(key, phrase) It works well, except for a persistence problem that got me stuck for a while. The WebService package makes use of weakrefs, and I guess this caused problems. However, removing the usage of weakrefs in ServiceProxy alone seemed to solve the problem. (If someone can explain that to me, I'm listening!) While this small test worked well, I wanted to do better: notably, I want the user to be able to change the WSDL on the fly, without needing to destroy the object and to add a new one, and also, I want the user to be able to alter the permission settings for each method in the Web Service. Well, it seems my wishes have made me enter quite a strange realm of low-level Zope mechanisms, which I don't always fully grasp! My current implementation suffers from heavy persistence problems, and contains the following significant code: def setWSDL(self, wsdl, service=None, port=None): """ Sets the Web Service this object proxies. This resets all the Web Service methods information, notably the security settings. """ # Remove old WSDL data if hasattr(self, '_serializer'): binding = self._port.getBinding() portType = binding.getPortType() for item in portType.operations: delattr(self, item.name) delattr(self, item.name+'__roles__') del self._wsdl del self._name del self._port del self._service del self._transport del self._serializer # Add new WSDL data self._security = ClassSecurityInfo() declareStaticPermissions(self._security) # This code mostly comes from WebService.ServiceProxy if not hasattr(wsdl, 'targetNamespace'): wsdl = WSDLReader().loadFromURL(wsdl) self._serializer = Serializer() self._transport = HTTPTransport() for item in wsdl.types.items(): self._serializer.loadSchema(item) self._service = wsdl.services[service or 0] self._port = self._service.ports[port or 0] self._name = self._service.name self._wsdl = wsdl binding = self._port.getBinding() portType = binding.getPortType() for item in portType.operations: callinfo = callInfoFromWSDL(self._port, item.name) method = MethodProxy(self, callinfo) setattr(self, item.name, method) # Default security for the Web Service methods self._security.declareProtected('Use Web Service', item.name) self._security.apply(self) InitializeClass(self) declareStaticPermissions() is a module-level function that declares the security settings for my so-called "static" methods, such as setWSDL, which are intended to always be present in the WebServiceProxy. Now, when I use this product, it works well the first time. I can set the WSDL to the Google Web Service, and then call its spellchecking method successfully. However, as soon as persistence comes into play, I'm toast. Simply switching directories a few times is enough for that. I then get the following error: 2002-11-20T12:20:45 ERROR(200) ZODB Couldn't load state for '\x00\x00\x00\x00\x00\x00\n\xa5' Traceback (innermost last): Module ZODB.Connection, line 533, in setstate TypeError: ('expected 1 arguments, got 0', <extension class AccessControl.cAccessControl.PermissionRole at 00E35258>, ()) I have spent quite some time debugging this last night. Line 533 in ZODB.Connection is state = unpickler.load() and the message means (it took some time to understand!) that unpickler.load() did not return anything. Also, once this happens, I find myself with two copies of my WebServiceProxy. From the extreme details of the cache: 1 '\x00\x00\x00\x00\x00\x00\n\xa5' 0 G Products.WebServiceProxy.WebServiceProxy.WebServiceProxy 3 '\x00\x00\x00\x00\x00\x00\n\xa5' 4 L Products.WebServiceProxy.WebServiceProxy.WebServiceProxy (google) which I guess is very bad from a consistency point-of-view. Well, I hope you're still reading me. Here are my questions: * Am doing something obviously wrong or stupid? * Is delattr(self, item.name+'__roles__') enough to remove all permission information about a method? The persistence error seems to be linked to a PermissionRole problem, which is usually what is contained in a m__roles__ field. * It is my understanding (after long analysis of the source) that what I'm doing with self._security is okay. I mean, it seems to me I should be able to redeclare my permission settings at run-time. Is this correct, or am I missing something? Acquisition is still rough to me. * Is it a good idea anyway to remove and add methods from a Product at run-time? (delattr(self, item.name), etc.)? I hope you will be able to give me some insights into this matter. I'd really like to be able to finish this Product somewhat, even as it is, it could have some value to the Zope community! :) _______________________________________________ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )