THE Java™ Programming Language, Fourth Edition

(Jeff_L) #1

To use RMI you must first design one or more remote interfacesinterfaces whose methods can be invoked
remotely. A remote interface extends the Remote interface, and its methods throw RemoteException in
addition to any other exceptions. Here, for example, is a simple definition of a compute server interface that
will accept Task objects for execution, returning the resulting Object:


import java.rmi.*;


public interface ComputeServer extends Remote {
Object compute(Task task) throws RemoteException;
}


The Task interface is generic, allowing a ComputeServer to do any computation requested of it:


public interface Task extends java.io.Serializable {
Object run();
}


Task itself is not a remote interface. Each ComputeServer object will run on a host and will be asked to
execute tasks locally on its own host and return any results. (Traditionally, the application invoking a remote
method is called the client of the invocation, and the application executing the method is called the server,
although a client of one invocation may be the server of another.) Task extends Serializable because all
local types passed to or returned from a remote method must be serializable.


Each method of a remote interface is required to throw RemoteException because any invocation of a
remote method can have failures that must be signaled. Recovery from these failures is unlike recovery in
local computation, where methods always arrive at their intended objects and either results are always
returned or you clearly know that they were not returned.


When you invoke a remote method, network failures create new uncertaintiesif the network fails after the
request is transmitted from the client, the client doesn't know whether the request was received. The failure
may have happened before the invocation reached the server, or it may have happened after it reached the
server but before results could be returned. There is no way for the client to know which of these two cases
actually happened. If the request is to withdraw money from your bank account, you would not want to simply
retransmit the requestit might get there twice. Remote interfaces must be designed to allow clients to recover
from such partial failures. Methods may be idempotentmeaning the method can safely be reinvokedor some
other recovery method may be provided for the interface, such as transactions that can be aborted when
non-idempotent methods fail. The users of a remote object must recover from such failures, and the declared
RemoteException helps them do so.


Here is a simple implementation of the ComputeServer interface:


import java.rmi.;
import java.rmi.server.
;


public class ComputeServerImpl
extends UnicastRemoteObject
implements ComputeServer
{
public ComputeServerImpl() throws RemoteException { }


public Object compute(Task task) {
return task.run();
}


public static void main(String[] args)

Free download pdf