Skip to main content

Using server-side objects with XML-RPC

XML-RPC is a very handy little standard. It's straightforward, lightweight, and implementations exist for pretty much every language out there.

One thing I've found a bit lacking with it however is that it's kind of a pain to deal with objects. The standard itself supports some very basic types like strings, integers, arrays, and structures. But there's no way of handling more complicated types. A project I've been working on involves manipulating server-side objects over a network connection, so I figured that XML-RPC would be a good place to start.

I believe I've come up with a good way of allowing clients to build proxies for server side objects, while still being compatible with regular XML-RPC implementations.

I've been experimenting a little bit with an XML-RPC server written in Python, and a JavaScript client (using jsolait). I considered adding a new type of parameter (<object>?), but decided against it since it would break older implementations. Instead, the client and server agree to a few conventions:

  • A two-tuple whose first element begins with "types." should be interpreted as a reference to an object on the server, where the first element specifies the type of the object, and the second is a unique identifier for that object.
  • The server exposes object methods as functions with names of the format "typeMethods.typeName.methodName".

When the client receives a two-tuple object reference, it can now look in the list of methods supported by the server, and create a new object with wrappers for all the appropriate class methods bound to that object. For example, the following python code:

class MyClass: def doSomething(self, x, y): pass

def makeObj(): return MyClass()

would be exposed as these XML-RPC functions:

makeObj() / returns an object reference: ("types.MyClass", objectId) /

typeMethods.MyClass.doSomething(objectRef, x, y) / objectRef should be ("types.MyClass", objectId) /

When the client sees a two-tuple of the form ("types.MyClass", objectId), it can create a new object along the lines of:

var o = {

"objectId" = objectId,

"typeName" = "types.MyClass",

"doSomething" = function(x,y) { typeMethods.MyClass.doSomething([this.typeName, this.objectId], x, y); }}

(JavaScript isn't my strong suit, so I appologize if this isn't exactly right. Hopefully the intent is clear!)

So now you've got a first-class object in your client, with methods that behave just like you would expect! You can now write:

o.doSomething(x,y);

instead of something along the lines of:

serverproxy.MyClass_doSomething(objectId, x, y);

Using the system.listMethods() function to get a list of all methods supported by the server enables you to bind all of a type's methods to an object.

Generating objectId's is application specific, so I won't go into that here. I would like to see a generic way for a user to extend Python's SimpleXMLRPCServer to marshall and unmarshall new data types. The pickle methods (getstate, setstate) seem promising, but those are intended to serialize the entire representation of an object, not simply a reference to the object.

Comments