Chapter 21. Remote Method Invocation
This
chapter presents examples of the remote method invocation (RMI)
capabilities of the java.rmi and
java.rmi.server packages. Remote method invocation
is a powerful technology for developing networked applications
without having to worry about the low-level networking details. RMI
transcends the client/server model of computing with a more general
remote object model. In this model, the server defines objects that
clients can use remotely. Clients invoke methods of a remote object
exactly as if it were a local object running in the same virtual
machine as the client. RMI hides the underlying mechanism for
transporting method arguments and return values across the network.
An argument or return value can be a primitive value or any
Serializable object.
To develop an RMI-based application,
you need to follow these steps:
Create an interface that extends the
java.rmi.Remote interface. This interface defines
the exported methods that the remote object implements (i.e., the
methods the server implements and clients can invoke remotely). Each
method in this interface must be declared to throw a
java.rmi.RemoteException,
which is the superclass of many more specific RMI exception classes.
Every remote method must declare that it can throw a
RemoteException, because there are quite a few
things that can go wrong during the remote method invocation process
over a network. (Actually, in Java 1.2 and later, this requirement is
loosened: remote methods may instead throw one of the superclasses of
RemoteException: IOException or
Exception.) Define a subclass of
java.rmi.server.UnicastRemoteObject (or sometimes
a related class) that implements your Remote
interface. This class represents the remote object (or server
object). Other than declaring its remote methods to throw
RemoteException objects, the remote object
doesn't need to do anything special to allow its
methods to be invoked remotely. The
UnicastRemoteObject and the rest of the RMI
infrastructure handle this automatically. Write a program (a server) that creates
an instance of your remote object. Export the object, making it
available for use by clients, by registering the object by name with
a registry service. This is usually done with the
java.rmi.Naming class and the
rmiregistry program. A server program may also
act as its own registry server by using the
LocateRegistry class and
Registry interface of the
java.rmi.registry package. After you compile the server program
with javac, use rmic to
generate a stub and a skeleton for the remote object. With RMI, the
client and server don't communicate directly. On the
client side, the client's reference to a remote
object is implemented as an instance of a stub class. When the client
invokes a remote method, it is a method of this stub object that is
actually called. The stub does the necessary networking to pass that
invocation to a skeleton class on the server. This skeleton
translates the networked request into a method invocation on the
server object, and passes the return value back to the stub, which
passes it back to the client. This can be a complicated system, but
fortunately, application programmers never have to think about stubs
and skeletons; they are generated automatically by the
rmic tool. Invoke rmic with
the name of the remote object class (not the interface) on the
command line. It creates and compiles two new classes with the
suffixes _Stub and _Skel. If the server uses the default
registry service provided by the Naming class, you
must run the registry server, if it is not already running. You can
run the registry server by invoking the
rmiregistry program. Now
you can write a client program to use the remote object exported by
the server. The client must first obtain a reference to the remote
object by using the Naming class to look up the
object by name; the name is typically an rmi:
URL. The remote reference that is returned is an instance of the
Remote interface for the object (or more
specifically, a stub object for the remote object). Once the client
has this remote object, it can invoke methods on it exactly as it
would invoke the methods of a local object. The only thing that it
must be aware of is that all remote methods can throw
RemoteException objects, and that in the presence
of network errors, this can happen at unexpected times. Finally, start up the server program, and run the client!
The following sections of this chapter provide two complete RMI
examples that follow the steps outlined here. The first example is a
relatively simple remote banking program, while the second example is
a complex and lengthy multiuser domain (MUD) system (a kind of
extensible chat-room universe). These examples are followed by a
short discussion of advanced RMI features that are not demonstrated
in this chapter.
|