I am trying to export a Ruby framework via XML-RPC. However I am having some problems when trying to call a method from a class not directly added as a handler to the XML-RPC server. Please see my example below:
I have a test Ruby XML-RPC server as follows:
require 'xmlrpc/server' class ExampleBar def bar() return 'hello world!' end end class ExampleFoo def foo() return ExampleBar.new end def test() return 'test!' end end s = XMLRPC::Server.new( 9090 ) s.add_introspection s.add_handler( 'example', ExampleFoo.new ) s.serve
And I have a test Python XML-RPC Client as follows:
import xmlrpclib s = xmlrpclib.Server( 'http://127.0.0.1:9090/' ) print s.example.foo().bar()
I would expect the python client to print ‘hello world!’ as it is the equivalent of the following ruby code:
example = ExampleFoo.new puts example.foo().bar()
However it generates an error: ‘xmlrpclib.ProtocolError: <ProtocolError for 127.0.0.1:9090/: 500 Internal Server Error>’.
print s.example.test() works fine.
I dont expect the new ExampleBar object to go over the wire but I would expect it to be ‘cached’ server side and the subsequent call to bar() to be honoured.
Can XML-RPC support this kind of usage or is it too basic?
So I guess my question really is; how can I get this working, if not with XML-RPC what with?
Your client (s in you Python code) is a ServerProxy object. It only accepts return values of type boolean, integers, floats, arrays, structures, dates or binary data.
However, without you doing the wiring, there is no way for it to return another ServerProxy, which you would need for accessing another class. You could probably implement an object cache on the Ruby side, but it would involve keeping track of active session and deciding when to remove objects, how to handle missing objects, etc.
Instead I would suggest exposing a thin wrapper on the ruby side that does atomic operations like: