Using Cajo as a layer above RMI is a very easy way to go remote. Cajo does not require the remoted objects to implement the Remote interface. So you for instance just export the “top”-object and Cajo does the rest. Serializable objects are sent by value and the non-Serializable objects by reference. There are some limitations when it comes to e.g. Arraylists, which implements the Serializable interface. That means the list will be sent by value, which means that the collected objects also must be Serializable. This is not always the case. Neither do you always want to serialize the whole collection. So what to do? Callbacks are also a “problem”. How to add a callback completely transparently seen from the client?
Callbacks:
Imagine your domain model has a serverObj.addMyObserver(…) method. Then you want to just call serverObj.addObserver(…) transparently without doing any extras to create the neccesary proxy for the serverObj in your client code. The trick lays in wrapping the CajoProxy with another Proxy. My proxy wrapper has a method that lets me search the parameters and add the classtypes i want to proxie with a cajoproxy, e.g. Observer (ProxiedCajoProxy.registerCallbackClass(…)).
So what happens is: The client calls serverObj.addObserver(new MyObserver()) as usual. The ProxiedCajoProxy checks its internal table for method parameters to proxie.
The ProxiedCajoProxy then replaces myObserver object with a CajoProxy. The CajoProxy is sent to the server and when an observed event occurs, the server calls the client through this proxy. (Will not work with a firewall because of RMIs architecture)
Collections (serializable)
When it comes to Collections the problem is that ArrayList is serializable and cajo will send it by value. To “fix” this problem you need to intercept cajo as above. When a collection is returned the ProxiedCajoProxy will create a new proxy and implement all the interfaces, except for java.io.Serializable. Then we wrap this object in a cajo proxy and return this instead of the first object. Now cajo will send the collection by reference and not by value.
To make this work on the whole object hierarchy the ProxiedCajoProxy must add a proxy to all objects returned from method calls. This way you can control all object invocation through the invocation handler before Cajo receives the objects. Also remember that all remote objects MUST have a corresponding interface to be exportable (could be fixed by some creative AOP).
Nice indeed.