ZSI and namespaces
As the next test, you will expand the ZSI client so that it does
support methods inside of a namespace. There are some hurdles to
overcome to do this; but Rich Salz, the author of the ZSI package, says
that support for namespaces on methods is coming soon. He says that his
intended approach is to use a new feature in Python 2.2 that allows you
to define arbitrary attributes to functions. You would add a
attribute on a function definition, and then the ZSI-dispatching code
would query for this attribute to determine which namespace the method
is defined in. For future reference, you can add any attribute to a
function by setting it on the function object. Below is a short example:
Salz also mentioned that he might add support for other attributes on functions besides namespace information, such as argument typing information. This would allow ZSI to typecheck incoming arguments before the function is called.
At any rate, to make the ZSI server namespace aware, you need to add a bit of logic to the
getMonth method (and any other method that we would like to be in a namespace). The first thing that you can try is to get a
for the current invocation. This contains all of the relevant
information about the call, including its namespace. (By default, ZSI
ignores the namespace.) You can then compare the namespace from the
to the namespace that you are expecting. If there is a match, then you
can return the proper results; if not, you can throw an exception to
say that the method was not defined. Listing 3 shows an example of how the refactored
getMonth method would look.
Unfortunately, to use this technique, you would need to add this logic to every function that is defined in the module. Listing 4
takes a more general approach that will allow all of the functions that
you define in a module to be easily defined inside of a namespace. You
can even easily define the same method in multiple namespaces, or
multiple methods with different namespaces (but the same method names).
To accomplish this, the function called
generically map a request using a mapping dictionary. The dictionary is
keyed off a namespace, and each entry references a function to be
invoked when a request in the corresponding namespace is received.
Then, to give the appearance of top-level functions in the module (as
required by ZSI), you use a simple lambda that will stand in the place
of the actual function definition. In the case of
getMonth lambda is called; this calls
which looks at the namespace of the call, as well as the mapping of
functions available. If a match is found, the function is invoked; if
not, an exception is raised. Now, to add new functions to the module,
you would define a function and a corresponding lambda.
One thing to note: you need to put a reference to
in the defaulted arguments of each lambda definition. This is because
when you are done creating the lambdas, you want to delete the module's
reference to the
_functionMap function; if you don't,
this function would be exposed over your Web services interface, as ZSI
allows any method defined at the top level to be called.
Listing 4 shows the file
zsi-ns-server.py, which implements the namespace-aware server in ZSI.
In the next installment of this column, we will compare some different
distributed programming technologies and look at some of the
performance characteristics of each. We will compare SOAP, CORBA
(Common Object Request Broker Architecture), XML-RPC, and a
roll-your-own implementation written with the
library. We will look at the message overhead, application memory
footprint, message transmission times, and relative source code size
needed when implementing each of these methods.