gnu.cajo.utils.extra
Class TransparentItemProxy

java.lang.Object
  extended by gnu.cajo.utils.extra.TransparentItemProxy
All Implemented Interfaces:
java.io.Serializable, java.lang.reflect.InvocationHandler

public final class TransparentItemProxy
extends java.lang.Object
implements java.lang.reflect.InvocationHandler, java.io.Serializable

This class creates an object, representing a local or remote service object. The returned object will implement a list of interfaces defined by the client. The interfaces are completely independent of interfaces the server object actually implements, if any; they are simply logical groupings of methods, of interest solely to the client.

Clients can dynamically create object proxy objects implementing any combination of interfaces. Combining interfaces provides a very important second order of abstraction. Whereas an interface is considered to be a grouping of functionality; the 'purpose' of an item, could be determined by the group of interfaces it implements. Clients can customise the way they use local/remote objects as a function of the interfaces implemented.

The proxy instances returned from this class are serialisable. Proxies can be persisted to storage for later use, and passed to other JVMs over the network.

Note: Unfortunately, this class only works with JREs 1.3 and higher. Therefore I was reluctant to include it in the official codebase. However, some very convincing discussion in the cajo project Developer's forum, with project member Bharavi Gade, caused me to reconsider.

Update: For users of JRE 1.5+
It you wish to invoke time consuming methods asynchronously, simply declare that the method returns a java.util.Concurrent.Future of the required return type. The invocation will return immediately, and the future will contain the result when the invocation is completed. You can then peridocally check to see if it is done, and extract the result.

Author:
John Catherino
See Also:
Serialized Form

Field Summary
static java.lang.Object handler
          An optional centralised invocation error handler.
 
Method Summary
static java.lang.Object getItem(java.lang.Object item, java.lang.Class[] interfaces)
          This generates a class definition for a any object reference at runtime, and returns a local object instance.
static java.lang.Object getItem(java.lang.String url, java.lang.Class[] interfaces)
          This method fetches a server item reference, generates a class definition for it at runtime, and returns a local object instance.
 java.lang.Object invoke(java.lang.Object proxy, java.lang.reflect.Method method, java.lang.Object[] args)
          This method, inherited from InvocationHandler, simply passes all object method invocations on to the wrapped object, automatically and transparently.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

handler

public static java.lang.Object handler
An optional centralised invocation error handler. If an invocation on a remote object results in a checked or unchecked exception being thrown; this object, if assigned, will be called to deal with it. This allows all retry/recovery/rollback logic, etc. to be located in a single place. It is expected that this object will implement a method of the following signature:

public Object handle(Object item, String method, Object args[], Throwable t) throws Exception;

The first arguments are as follows:

The handler will either successfully recover from the error, and return a substitute result, or throw a hopefully more descriptive exception.

Method Detail

invoke

public java.lang.Object invoke(java.lang.Object proxy,
                               java.lang.reflect.Method method,
                               java.lang.Object[] args)
                        throws java.lang.Throwable
This method, inherited from InvocationHandler, simply passes all object method invocations on to the wrapped object, automatically and transparently. This also allows the local runtime to perform remote item invocations, while appearing syntactically identical to local ones.

Specified by:
invoke in interface java.lang.reflect.InvocationHandler
Parameters:
proxy - The locallly created proxy object on which the method was originally invoked.
method - The method to invoke on the object, in this case the local or remote service object.
args - The arguments to provide to the method, if any.
Returns:
The resulting data from the method invocation, if any.
Throws:
java.rmi.RemoteException - For network communication related reasons with a remote service.
java.lang.NoSuchMethodException - If no matching method can be found on the service object.
java.lang.Exception - If the service object rejected the invocation, for application specific reasons.
java.lang.Throwable

getItem

public static java.lang.Object getItem(java.lang.Object item,
                                       java.lang.Class[] interfaces)
This generates a class definition for a any object reference at runtime, and returns a local object instance. The resulting dynamic proxy object will implement all the interfaces provided.

Parameters:
item - A reference to a either a remote object, or a local one
Note: a non-serialisable local item will be automatically remoted when serialised, so as to support proxies being freely passed between JVMs.
interfaces - The list of interface classes for the dynamic proxy to implement. Typically, these are provided thus; new Class[] { Interface1.class, Interface2.class, ... }
Returns:
A reference to the provided object, wrapping the local object, it can then be typecast into any of the interfaces, as needed by the client.

getItem

public static java.lang.Object getItem(java.lang.String url,
                                       java.lang.Class[] interfaces)
                                throws java.rmi.RemoteException,
                                       java.rmi.NotBoundException,
                                       java.io.IOException,
                                       java.lang.ClassNotFoundException,
                                       java.lang.InstantiationException,
                                       java.lang.IllegalAccessException,
                                       java.net.MalformedURLException
This method fetches a server item reference, generates a class definition for it at runtime, and returns a local object instance. The resulting dynamic proxy object will implement all the interfaces provided. Technically, it invokes the other getItem method, after fetching the object reference from the remote JVM specified.

Parameters:
url - The URL where to get the object: //[host][:port]/[name]. The host, port, and name, are all optional. If missing the host is presumed local, the port 1099, and the name "main". If the URL is null, it will be assumed to be ///.
interfaces - The list of interface classes for the dynamic proxy to implement. Typically, these are provided thus; new Class[] { Interface1.class, Interface2.class, ... }
Returns:
A reference to the server item, wrapping the object created at runtime, implementing all of the interfaces provided. It can then be typecast into any of the interfaces, as needed by the client.
Throws:
java.rmi.RemoteException - if the remote registry could not be reached.
java.rmi.NotBoundException - if the requested name is not in the registry.
java.io.IOException - if the zedmob format is invalid.
java.lang.ClassNotFoundException - if a proxy was sent to the VM, and proxy hosting was not enabled.
java.lang.InstantiationException - when the URL specifies a class name which cannot be instantiated at runtime.
java.lang.IllegalAccessException - when the url specifies a class name and it does not support a no-arg constructor.
java.net.MalformedURLException - if the URL is not in the format explained