[Previous] [Contents] [Next] [IONA Technologies]


Chapter 22
Smart Proxies


Contents

22.1 Proxy Classes and Smart Proxy Classes
22.2 Example: A Simple Smart Proxy
22.2.1 Creating a Smart Proxy



We have seen thlasses for IDL interfaces are automatically generated by the IDL compiler, and that these are used to support invocations on remote interfaces. Normally, therefore, proxy classes are hidden from programmers.

It is sometimes beneficial to be able to implement proxy classes manually. This is a useful option both for client programmers and the implementers of interfaces, as it allows client interaction with remote services to be optimized while hiding added levels of complexity.

For client programmers, a typical example is where it is desirable to introduce load balancing between several remote objects when invoking operations. For example, if multiple remote objects can satisfy a request for a computationally intensive operation, a client application may wish to route each invocation to the object which is currently least busy.

For interface implementers, it is often useful to implement smart proxies in order to cache some information from a remote object locally at a client site. In our simple bank application, we may wish, for example, to cache the balance of an account at a client. Requests to obtain the balance of the account could then be immediately satisfied, provided of course that we take care to ensure that withdrawals and deposits to the account cause the cached value to be refreshed.

In this chapter, we first consider the details of how proxy objects are actually generated, and the general steps needed to implement smart proxy support for a given interface. We then proceed to consider how a simple smart proxy can be built. This example will be based on a small load balancing application.

22.1 Proxy Classes and Smart Proxy Classes

This section describes how OrbixWeb manages proxies.

For each IDL interface, the OrbixWeb IDL compiler generates a Java interface which defines the client view of the IDL interface. It also generates a Java proxy class, which implements proxy functionality for the methods defined in the Java interface. The proxy class gives the code for standard proxies for that IDL interface–these proxies transmit requests to their real object and return the results they receive to the caller.

A smart proxy class is a user-defined alternative to the IDL generated proxy class. OrbixWeb implicitly constructs a standard proxy when an object reference enters the client address space1. However, a smart proxy cannot be implicitly created, so each smart proxy class depends on the implementation of a corresponding class which manufactures smart proxy objects when requested to by OrbixWeb. This class is called a smart proxy factory class.

To provide smart proxies for an IDL interface, a programmer must:

Note that, other than the introduction of new classes and the creation of the proxy factory object, no changes are required to existing clients in order to introduce smart proxy functionality. In particular their operation invocation code remains unchanged.

Once these steps are carried out, OrbixWeb will communicate with the smart proxy factory whenever it needs to create a proxy of that interface:

More than one smart proxy class (and associated smart proxy factory class) can be defined for a given IDL interface. OrbixWeb maintains a linear linked list of all of the proxy factories for a given IDL interface.

A chain of smart proxy factories is allowed for an IDL interface because the same IDL interface might be provided by a number of different servers in the system. It may be useful, therefore, to have different smart proxy code to handle each server, or set of servers. Each factory in turn can examine the marker and server name of the target object for which the proxy is to be created, and decide whether to create a smart proxy for it or to defer the request to the next proxy factory in the chain.

In more detail, the following steps must be carried out in order to create smart proxies:

1. Implement the smart proxy class.
The constructor(s) of this class will be used by the proxy factory. See step (2.) below.
2. Implement a new proxy factory class, derived from the OrbixWeb ProxyFactory class (defined in package IE.Iona.Orbix2.CORBA). It should redefine the New() method to create new smart proxy objects of the class in (1.) above; or return zero to indicate that it is not willing to create a smart proxy.
3. Declare an object of this new class. The inherited base class constructor will automatically register this new proxy factory with the factory manager object.
When a new proxy is required, OrbixWeb will call all of the registered proxy factories for the class until one of them successfully builds a new proxy. If none succeeds, a standard proxy will be implicitly constructed. Proxy factories are automatically added to the chain of factories as they are created, but there is no guarantee on the order of use of smart proxy factories.

The factory manager requests each proxy factory to manufacture a new proxy via its New() method:

One way to extract the target object's marker and server name is to simply decompose the object reference string. The format of this string is described in section 5.1.1.

If the New() method returns null, then OrbixWeb will try the next smart proxy factory in the chain.

Examples of these smart proxy implementation steps are given in the rest of this chapter.

22.2 Example: A Simple Smart Proxy

We will consider a very simple example of a load balancing system, based on the following IDL definition:

In this application, we assume that a number of objects exist which implement the NumberCruncher interface. Each of these objects is capable of exhibiting individual load characteristics (for example, this would be the case if each was located in a separate OrbixWeb server process).

We also assume that an OrbixWeb server exists which implements the NCManager interface. The NCManager implementation object is responsible for locating the currently least loaded NumberCruncher and returning the corresponding object reference to the client. The client can then invoke the crunch() operation (perhaps repeatedly) on the target object.

Of course, the load on each NumberCruncher object changes over time. If it is valid to direct each client crunch() invocation to any NumberCruncher object, then the performance perceived by the client can be improved by updating the target object before each operation call. In this example, we implement a smart proxy which takes advantage of this fact to optimize the performance of the crunch() operation.

22.2.1 Creating a Smart Proxy

Step A

We will define a smart proxy class, which we will call SmartNC, for Java proxy class NumberCruncher. Instances of this class will store a variable which holds a default proxy for the NumberCruncher object. This proxy variable will be updated before each call to crunch(), and the operation invocation will then be routed via the refreshed default proxy.

Class SmartNC inherits from the default proxy class generated by the IDL compiler. It therefore inherits all of the code required to make a remote invocation: if required, each SmartNC method could make a call-up to its base class's method to make a remote call. However, this functionality is not required in this example.

The constructor for the smart proxy class takes a full object reference string as a parameter. It must pass this to the constructor of its default proxy class. This call up is necessary to allow OrbixWeb to manage an internal table of available proxies.

In this case, the constructor also initialises a member variable which holds a proxy for the NCManager object by calling NCManager._bind().

The crunch() method first obtains a default proxy for the current least loaded NumberCruncher object by invoking NCManager.getNumberCruncher(). The implementation of the smart proxy factory class described in Step B will prevent this invocation from creating a second smart proxy. The smart crunch() method then simply invokes the default crunch() on the newly created object.

Step B

The next step is to define a new proxy factory to generate our smart proxies at the appropriate time. This is fairly easy–recall that the base class for all proxy factory classes is class ProxyFactory.

The member initialisation list of the constructor of class SmartNCFactory makes a call to the constructor of class ProxyFactory. The parameter passed is the return value of the static method NumberCruncher.OrbixIRName(). This automatically generated method returns a string which holds information about the IDL interface type for the proxy.

The proxy and proxy factory class hierarchies are shown in Figure 22.1.


Figure 22.1: Class hierarchy for smart proxy classes

The SmartNCFactory.New() method is called by OrbixWeb to signal that a smart proxy can be created. OrbixWeb passes it the object reference of the real object for which the proxy is required. If the method decides to create a smart proxy, it must instantiate the smart proxy, passing it the object reference (and any other constructor parameters agreed on by the smart proxy and the smart proxy factory).

In this example application, each client only requires a single smart proxy object to manage all invocations on class NumberCruncher. The New() method first checks the member variable createProxy member variable to determine if it needs to create a smart proxy. If the value of this variable is false, then the method simply returns null. This results in the invocation of the next smart proxy factory in the factory chain, or the creation of a default proxy object (if this is the last factory in the chain).

A Sample Client

Finally, we need to declare a single instance of the new proxy factory class in the client:

The inherited base class constructor will then register this new factory–entering it into the linked list of factories for interface NumberCruncher.

A sample client which communicates via this smart proxy could be coded as follows:

The client simply binds to the NCManager object, from which it obtains an object reference for the currently least loaded NumberCruncher. When this object reference enters the client address space, a smart proxy is created transparently to the client. The client invocations on operation crunch() are then automatically routed through the smart proxy, as described earlier in this chapter.



1 Experienced Orbix developers should note that OrbixWeb does not use proxy factory classes to construct standard proxy objects.



[Roadmap] [Introduction] [GS: Applications] [GS: Applets]
[IDL] [Mapping] [Programming OrbixWeb] [Publishing Objects] [Retrieving Objects] [IIOP]
[Running Clients] [Running Servers] [Exceptions] [Inheritance] [Callbacks] [Contexts]
[API Configuration] [TypeCode] [Any] [DII] [IR] [Filters] [Smart Proxies] [Loaders] [Locators]
[Index]