the cajo project
Free, simple, powerful: Transparent Distributed Computing
Proxy items distribute cajo functionality
In this framework, a proxy is actually any ordinary object, sent from one JVM to another, typically as a method argument, or result. (although they can even be sent in exceptions) In this page, we will look at proxies that derive from the utility class BaseProxy, though any serialisable class can be used as a proxy. Proxy objects are sent to a client by, and on behalf of, a server item. A BaseProxy subclass will arrive with a remote link back to its server item, on which it can asynchronously communicate with it. Proxies are often used to pre-process method invocations made by the client, using the computing resources of the client, rather than those of the server. They can most aptly be thought-of as "smart" references to remote objects.
Base proxies
A proxy can optionally provide a graphical user interface, if it is intended to be more than just a machine-to-machine interface. Architecturally a BaseProxy is very similar to a BaseItem. It has an optional MainThread, which is cannonically launched by the client, on its arrival. It also has string tables, which can be automatically loaded with the language appropriate to the locale of the client.

Each proxy is served by, and typically services, one server item. The server item binds itself and provides its proxy object using the static bind method of the ItemServer class. The server item can also announce its availablity to a collection of listening VMs via the multicast mechanism, described in the next section. It is generally necessary to start up a CodebaseServer, on which the client will automatically request, and receive the proxy class files. Whenever a VM serves proxies, it will require two TCP ports; one for communication with the server item itself, and another for sending the proxy codebase via the CodebaseServer. If a server does not use proxies, it only needs one port. A CodebaseServer can also be used to send complex objects to an client, which would use it to transparently load the necessary class definitions.
Requesting proxies
A proxy is typically obtained from a remote item reference by using its null argument getProxy method. The returned item will be its default proxy, if it supports one. Once a proxy item is received, the otrhodox initialisation procedure is to perform the following:
   Remote.invoke(proxy, "init", new Remote(proxy));
This would cause a BaseProxy to load its string table, create its main thread, and begin operating. It can use the provided remote reference to itself, to pass back to its server item, or to other remote items, on which they may asynchronously communicate with the proxy. The return of this invocation, if non-null, will be the proxy's default graphical user interface. The client can display this if it wishes. The framework specifies only the method to obtain the default proxy. If an item serves multiple proxies, the method or methods to obtain them are application specific. A suggestion would be, to use a string argument in a getProxy invocation, to specify the desired proxy. Note: as a general rule, it is considered elegant practice for a server item to support both a proxy interface to itself, and for that proxy to support a graphical interface. Clients then have the option to use the proxy, its user interface, or to manipulate the remote object directly. Minimally, an item should at least support a String getDescription() method, to describe its use and features.
Sending proxies
If a remote machine is willing to host proxies, another item can typically install a proxy, by invoking a remote item's installProxy method, passing its proxy as the argument. The default implementation will invoke the proxy's init method, passing a reference to the proxy, remoted within the context of the BaseItem's VM, to start its operation. It will then return the same reference back to the calling VM, on which it may asynchronously communicate with its proxy. Receiving too many proxies could overload a client VM, therefore acceptance of proxies is disabled by default. It can be enabled by invoking the acceptProxies method of the ItemServer class. Attempting to send a proxy to an VM that does not accept them will result in a ClassNotFoundException being automatically thrown to the sender. BaseItem's setProxy method is often extended, to provide additional application specific resources to the arriving proxy. A fascinating capability of this technique, is that proxies can even be sent, from one host to another, to perform distributed data gathering and process control. The proxy is effectively cloned, and running at both places simultaneously. Proxies offer an exciting dynamic approach to what is popularly called mobile agent computing these days.
Conclusion
The diagramme below illustrates the four step process to using proxies:
  1. Client requests remote item reference
  2. Client receives remote item reference
  3. Client requests proxy from remote item
  4. Client receives proxy codebase
  5. Client initialises proxy (receiving optional GUI)
cajo proxy architecture

A very enlightening "bare-bones" example, of just how easy it is to use proxies, can be found in the project examples wiki; here.

One of the most important features of a proxy is to mitigate network latency. This can be of critical importance, if the remote item is very far away, or linked over a slow network. Generally it is a recommended practice for remote items to provide a proxy. At a minimum, it would serve to reduce network traffic, and possibly pre-fetch needed objects contextually. It also allows server functionally to scale more easily, by using proxies to offload more of the individual clients computational requirements to the client.

Another major benefit to this proxy hosting architecture, is that it allows multiple remote servers to provide their graphical user interfaces to operate within a single client JVM. This provides a tremendous reduction in compute requirements, and memory consumption, as well as significant performance improvement compared to hosting each server proxy in a separate virtual machine. Similarly, this architecture also allows a single server VM to host multiple item objects, to realise the very same benefits.

Both the proxy, and its serving item, can in turn give their remote references to other items. As a result, an item calling another item does not know, or need even care, if it is invoking a local item, a remote item, a local proxy, or a remote proxy.

The next section multicast, will show how items can send or receive, remote item references, using a method analogous to a radio broadcast!

Proxies are just objects, sent by the server, to run at the client, on the server's behalf.

© 2004 John Catherino, GNU FDL