(For more resources on Spring, see here.)
With the explosion of the Internet into e-commerce in recent years, companies are under pressure to support lots of simultaneous customers. With users wanting richer interfaces that perform more business functions, this constantly leads to a need for more computing power than ever before, regardless of being web-based or thick-client. Seeing the slowdown of growth in total CPU horsepower, people are looking to multi-core CPUs, 64-bit chips, or at adding more servers to their enterprise in order to meet their growing needs.
Developers face the challenge of designing applications in the simple environment of a desktop scaled back for cost savings. Then they must be able to deploy into multi-core, multi-server environments in order to meet their companies business demands.
Different technologies have been developed in order to support this. Different protocols have been drafted to help communicate between nodes. The debate rages on whether talking across the network should be visible in the API or abstracted away. Different technologies to support remotely connecting client process with server processes is under constant development.
Introduction to Pyro (Python Remote Objects)
Pyro is an open source project (pyro.sourceforge.net) that provides an object oriented form of RPC. As stated on the project’s site, it resembles Java’s Remote Method Invocation (RMI). It is less similar to CORBA (http://www.corba.org), a technology-neutral wire protocol used to link multiple processes together, because it doesn’t require an interface definition language, nor is oriented towards linking different languages together. Pyro supports Python-to-Python communications. Thanks to the power of Jython, it is easy to link Java-to-Python, and vice versa.
Python Remote Objects is not to be confused with the Python Robotics open source project (also named Pyro).
Pyro is very easy to use out of the box with existing Python applications. The ability to publish services isn’t hard to add to existing applications. Pyro uses its own protocol for RPC communication.
Fundamentally, a Pyro-based application involves launching a Pyro daemon thread and then registering your server component with this thread. From that point on, the thread along with your server code is in stand-by mode, waiting to process client calls. The next step involves creating a Pyro client proxy that is configured to find the daemon thread, and then forward client calls to the server. From a high level perspective, this is very similar to what Java RMI and CORBA offer. However, thanks to the dynamic nature of Python, the configuration steps are much easier, and there are no requirements to extend any classes or implement any interfaces..
As simple as it is to use Pyro, there is still the requirement to write some minimal code to instantiate your objects and then register them. You must also code up the clients, making them aware of Pyro as well. Since the intent of this article is to dive into using Spring Python, we will skip writing a pure Pyro application. Instead, let’s see how to use Spring Python’s out-of-the-box Pyro-based components, eliminating the need to write any Pyro glue code. This lets us delegate everything to our IoC container so that it can do all the integration steps by itself. This reduces the cost of making our application distributed to zero.
Converting a simple application into a distributed one on the same machine
For this example, let’s develop a simple service that processes some data and produces a response. Then, we’ll convert it to a distributed service.
First, let’s create a simple service. For this example, let’s create one that returns us an array of strings representing the Happy Birthday song with someone’s name embedded in it.
def happy_birthday(self, name):
results =  for i in range(4):
if i == 2:
results.append("Happy Birthday Dear %s!" % name)
results.append("Happy Birthday to you!")
Our service isn’t too elaborate. Instead of printing the data directly to screen, it collects it together and returns it to the caller. This allows us the caller to print it, test it, store it, or do whatever it wants with the result. In the following screen text, we see a simple client taking the results and printing them a little formatting inside the Python shell.
As we can see, we have defined a simple service, and can call it directly. In our case, we are simply joining the list together with a newline character, and printing it to the screen.
Fetching the service from an IoC container
from springpython.config import *
from simple_service import *
Creating a client to call the service
Now let’s write a client script that will create an instance of this IoC container, fetch the service, and use it.
from springpython.context import *
from simple_service_ctx import *
if __name__ == "__main__":
ctx = ApplicationContext(HappyBirthdayContext())
s = ctx.get_object("service")
Running this client script neatly creates an instance of our IoC container, fetches the service, and calls it with the same arguments shown earlier.