Home

fussel4711 Johannes Dürr

Remote Method Call

The Remote Method Call (RMC) framework provides a way to easily communicate with remote objects. In principle it provides the same functionality as Java's Remote Method Invocation (RMI), but it is more flexible.

Imagine the following scenario

You want to access an Object model provided on a remote system. Model in this scenario means that you have a root element having child elements. Those child elements may also contain child elements, etc. When the data of an element within that model changes the particular element notifies it's parent object. The parent object itself notifies it's parent and so on. This means the notification will be forwarded from bottom to the top. Thus the root element will also be informed of that change.

Each element supports to add a listener for listening to changes. You can add one listener at the root element if you only want to be informed that something has changed or you can listen for changes of a particular element. You than want to manipulate some elements which in turn will fire notifications.

Accessing this model from remote means, that you want to invoke methods on the remote model, e.g. retrieving it's child elements. You also want to manipulate those children from remote which must update the particular children on the server in order to have a consistent data model. Remember you might also want to listen for changes within the element even if you access the model from remote. This means that the model on the server must also be able to pass back events to your system.

How about RMI?

RMI only supports to invoke methods in one direction. The object you want to access must be explicitly bound. Applied to the above example this means you can access the model from remote. You are also able to retrieve it's children, their children, and so on. When you modify the data on the model the invocations
will be passed to the model on the server. When you modify the data on a child element it will not be updated on the server. When you add a listener to the model this invocation is forwarded to the server model, but when the listener on the server receives a notification it will handle it on the server side. When you add a listener on a child element it is not passed to the server model.

The problem with RMI is, that only objects can be accessed remotely which are exported on the server and bound on the client. When you bind to a remote object you will get a copy of this object using serialization. When you invoke a method on this object the method call is serialized, passed to the server and invoked on the object. The result is passed back to the client using serialization. Thus when you call for the children of the server model you will get a copy of those. Thus the child elements on the server can not be modified by the client.

Remote Method Call

When you want a real 1:1 connection to a remote data model you need Remote Method Call. RMC differs from RMI in several ways:

  • Bind one remote object and access all elements of it which are marked as de.brainchild.rmc.Remote or java.rmi.Remote
  • RMC supports two-way-synchronization: Changes on the server side are also forwarded to the client and vice versa.
  • Explicitly declare methods to by invoked locally by annotating them with de.brainchild.rmc.Local
  • Connections are independent from the transport media. The de.brainchild.rmc.ConnectionFactory is responsible for creating de.brainchild.rmc.internal.Connections. Thus provide a factory for a particular
    media and RMC can communicate over it.
  • Has not yet a registry to look up objects by name.

Example

// Configure RMC to use Sockets for communication.
Properties p = System.getProperties();
p.put(SocketConnectionFactory.HOST_PROPERTY, "localhost");
p.put(SocketConnectionFactory.PORT_PROPERTY, "5000");
p.put(ServerSocketConnectionFactory.HOST_PROPERTY, "localhost");
p.put(ContextFactory.SERVER_CONNECTION_FACTORY_PROPERTY, ServerSocketConnectionFactory.class.getName());
p.put(ContextFactory.CLIENT_CONNECTION_FACTORY_PROPERTY, SocketConnectionFactory.class.getName());

//Setup server model - should be done on the server side 
ServerContext serverContext = ContextFactory.getServerContext(p);
DataModel serverModel = new DataModel();
DataModel exportedModel = serverContext.export(serverModel);

// Setup client
ClientContext clientContext = ContextFactory.getClientContext(p);
DataModel clientModel = clientContext.bind(DataModel.class);

// do something with the model ...

// Release allocated resources
// on the client
clientContext.unbind(clientModel);

// on the server
serverContext.unexport(exportedModel);