Recipe 22.4. Remoting a Class Transparently Using RMIProblemYou want to use Java Remote Method Invocation (RMI) to remote calls on a local object to an instance on another machine without making changes to how the original local object is used. SolutionCreate an RMI server application that contains an instance of the class, as shown in Example 22-8. Example 22-8. Declaring an instance of BusinessClass that is contained within an RMI Server implementationimport java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class ThisOrThatServerImpl extends UnicastRemoteObject implements ThisOrThatServer { BusinessClass businessClass = new BusinessClass( ); public ThisOrThatServerImpl( ) throws RemoteException { } public void foo( ) throws RemoteException { this.businessClass.foo( ); } } Within the client application, create an aspect that intercepts the calls to a specific instance of the class that has been remoted and route those calls to the corresponding RMI server, as shown in Example 22-9. Example 22-9. Intercepting calls to a local instance and channeling those calls to the remotely managed instanceimport java.rmi.*; public aspect RemoteBusinessClassAspect { public pointcut callBusinessClassFooInMain( ) : call(public void BusinessClass.foo( )) && withincode(public void MainApplication.main(String[])); void around( ) : callBusinessClassFooInMain( ) { try { ThisOrThatServer rmtServer = (ThisOrThatServer) Naming.lookup("rmi://localhost/TTServer"); rmtServer.foo( ); } catch (Exception e) { System.err.println("Problems occured when attempting " + "to use remote object, default to local"); proceed( ); } } } DiscussionUsing Java RMI can intrude on your application's classes in terms of new interfaces, new exceptions, and new code that must be incorporated. Traditionally, the object-oriented façade design pattern could be used to hide these complexities, but by using aspects, you are given the ability to use RMI to remote areas of your application transparently to your existing code and without the addition of a complex façade. The RemoteBusinessClass aspect in Example 22-9 captures when the foo( ) method is called on the BusinessClass instance within the execution of the application's main(..) method. The corresponding around( ) advice overrides that call and attempts to pass the message to the remote instance of BusinessClass as managed by the RMI Server and identified as TTServer in this case. If any exceptions occur when attempting to use the remote object, then the aspect reverts to using the original local instance by making the call to proceed( ).
See AlsoThe foundation of this example was supplied by Java Enterprise in a Nutshell by William Crawford, Jim Farley, and David Flanagan (O'Reilly); the call(Signature) pointcut is described in Recipe Recipe 4.1; the withincode(Signature) pointcut is described in Recipe 9.3; the around( ) form of advice is covered in Recipe 13.4. |