The Java TM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search

Trail: RMI
Lesson: Using Java RMI

## Designing a Remote Interface

> At the heart of the compute engine is a protocol that allows jobs to be submitted to the compute engine, the compute engine to run those jobs, and the results of the job to be returned to the client. This protocol is expressed in interfaces supported by the compute engine and by the objects that are submitted to the compute engine, as shown in the following figure.

> Each of the interfaces contains a single method. The compute engine's interface, `Compute`, allows jobs to be submitted to the engine; the client interface, `Task,` defines how the compute engine executes a submitted task.

> The `compute.Compute` interface defines the remotely accessible part--the compute engine itself. Here is the remote interface with its single method:

> >     package compute;

> >     import java.rmi.Remote;
> >     import java.rmi.RemoteException;

> >     public interface Compute extends Remote {
> >         Object executeTask(Task t) throws RemoteException;
> >     }

> By extending the interface `java.rmi.Remote`, this interface marks itself as one whose methods can be called from any virtual machine. Any object that implements this interface becomes a remote object.

> As a member of a remote interface, the `executeTask` method is a remote method. Therefore the method must be defined as being capable of throwing a `java.rmi.RemoteException`. This exception is thrown by the RMI system during a remote method call to indicate that either a communication failure or a protocol error has occurred. A `RemoteException` is a checked exception, so any code making a call to a remote method needs to handle this exception by either catching it or declaring it in its `throws` clause.

> The second interface needed for the compute engine defines the type `Task`. This type is used as the argument to the `executeTask` method in the `Compute` interface. The `compute.Task` interface defines the interface between the compute engine and the work that it needs to do, providing the way to start the work.

> >     package compute;

> >     import java.io.Serializable;

> >     public interface Task extends Serializable {
> >         Object execute();
> >     }

> The `Task` interface defines a single method, `execute`, which returns an `Object`, has no parameters, and throws no exceptions. Since the interface does not extend `Remote`, the method in this interface doesn't need to list `java.rmi.RemoteException` in its `throws` clause.

> The return value for the `Compute`'s `executeTask` and `Task`'s `execute` methods is declared to be of type `Object`. This means that any task that wants to return a value of one of the primitive types, such as an `int` or a `float`, needs to create an instance of the equivalent wrapper class for that type, such as an `Integer` or a `Float`, and return that object instead.

> Note that the `Task` interface extends the `java.io.Serializable` interface. RMI uses the object serialization mechanism to transport objects by value between Java virtual machines. Implementing `Serializable` marks the class as being capable of conversion into a self-describing byte stream that can be used to reconstruct an exact copy of the serialized object when the object is read back from the stream.

> Different kinds of tasks can be run by a `Compute` object as long as they are implementations of the `Task` type. The classes that implement this interface can contain any data needed for the computation of the task and any other methods needed for the computation.

> Here is how RMI makes this simple compute engine possible. Since RMI can assume that the `Task` objects are written in the Java programming language, implementations of the `Task` object that were previously unknown to the compute engine are downloaded by RMI into the compute engine's virtual machine as needed. This allows clients of the compute engine to define new kinds of tasks to be run on the server machine without needing the code to be explicitly installed on that machine. In addition, because the `executeTask` method returns a `java.lang.Object`, any type of object can be passed as a return value in the remote call.

> The compute engine, implemented by the `ComputeEngine` class, implements the `Compute` interface, allowing different tasks to be submitted to it by calls to its `executeTask` method. These tasks are run using the task's implementation of the `execute` method. The compute engine reports results to the caller through its return value: an `Object`.

| Start of Tutorial > Start of Trail > Start of Lesson | Search