18.6 The java.rmi.server Package
The java.rmi.server package is the most complex of all
the RMI packages; it contains the scaffolding for building remote
objects and thus is used by objects whose methods will be invoked by
clients. The package defines 6 exceptions, 9 interfaces, and 10-12
classes (depending on the Java version). Fortunately, you only need
to be familiar with a few of these in order to write remote objects.
The important classes are the RemoteObject class,
which is the basis for all remote objects; the
RemoteServer class, which extends
RemoteObject; and the
UnicastRemoteObject class, which extends
RemoteServer. Any remote objects you write will
likely either use or extend UnicastRemoteObject.
Clients that call remote methods but are not themselves remote
objects don't use these classes and therefore
don't need to import
java.rmi.server.
18.6.1 The RemoteObject Class
Technically, a remote object is not an
instance of the RemoteObject class but an instance
of any class that implements a Remote interface.
In practice, most remote objects will be instances of a subclass of
java.rmi.server.RemoteObject:
public abstract class RemoteObject extends ObjectYou can think of this class as a special version of
implements Remote, Serializable
java.lang.Object for remote objects. It provides
toString( ), hashCode( ),
clone( ), and equals( ) methods
that make sense for remote objects. If you create a remote object
that does not extend RemoteObject, you need to
override these methods yourself.The equals( ) method compares the remote object
references of two RemoteObjects and returns true
if they point to the same RemoteObject. As with
the equals( ) method in the
Object class, you may want to override this method
to provide a more meaningful definition of equality.The toString( ) method returns a
String that describes the
RemoteObject. Most of the time, toString() returns the hostname and port from which the remote
object came as well as a reference number for the object. You can
override this method in your own subclasses to provide more
meaningful string representations.The hashCode( ) method maps a presumably unique
int to each unique object; this integer may be
used as a key in a Hashtable. It returns the same
value for all remote references that refer to the same remote object.
Thus, if a client has several remote references to the same object on
the server, or multiple clients have references to that object, they
should all have the same hash code.The final instance method in this class is getRef():
public RemoteRef getRef( ) // Java 1.2This returns a remote reference to the class:
public abstract interface RemoteRef extends ExternalizableThere's also one static method,
RemoteObject.toStub( ):
public static Remote toStub(Remote ro) // Java 1.2RemoteObject.toStub( ) converts a given remote
throws NoSuchObjectException
object into the equivalent stub object for use in the client virtual
machine, which can help you dynamically generate stubs from within
your server without using rmic.
18.6.2 The RemoteServer Class
The RemoteServer class extends
RemoteObject; it is an abstract superclass for
server implementations such as
UnicastRemoteObject. It provides a few simple
utility methods needed by most server objects:
public abstract class RemoteServer extends RemoteObjectUnicastRemoteObject is the most commonly used
subclass of RemoteServer included in the core
library. Two others, Activatable and
ActivationGroup, are found in the
java.rmi.activation package. You can add others
(for example, a UDP or multicast remote server) by writing your own
subclass of RemoteServer.
18.6.2.1 Constructors
RemoteServer has two constructors:
protected RemoteServer( )However, you won't instantiate this class yourself.
protected RemoteServer(RemoteRef r)
Instead, you will instantiate a subclass like
UnicastRemoteObject. That class's
constructor calls one of these protected constructors from the first
line of its constructor.
18.6.2.2 Getting information about the client
The RemoteServer class has one method to locate
the client with which you're communicating:
public static String getClientHost( ) throws ServerNotActiveExceptionRemoteServer.getClientHost() returns a String that
contains the hostname of the client that invoked the currently
running method. This method throws a
ServerNotActiveException if the current thread is
not running a remote method.
18.6.2.3 Logging
For debugging purposes, it is sometimes useful to see the calls that
are being made to a remote object and the object's
responses. You get a log for a RemoteServer by
passing an OutputStream object to the
setLog( ) method:
public static void setLog(OutputStream out)Passing null turns off logging. For example, to
see all the calls on System.err (which sends the
log to the Java console), you would write:
myRemoteServer.setLog(System.err);Here's some log output I collected while debugging
the Fibonacci programs in this chapter:
Sat Apr 29 12:20:36 EDT 2000:RMI:TCP Accept-1:[titan.oit.unc.edu:If you want to add extra information to the log along with
sun.rmi.transport.DGCImpl[0:0:0, 2]: java.rmi.dgc.Lease
dirty(java.rmi.server.ObjID[], long, java.rmi.dgc.Lease)]
Fibonacci Server ready.
Sat Apr 29 12:21:27 EDT 2000:RMI:TCP Accept-2:[macfaq.dialup.cloud9.net:
sun.rmi.transport.DGCImpl[0:0:0, 2]: java.rmi.dgc.Lease
dirty(java.rmi.server.ObjID[], long, java.rmi.dgc.Lease)]
Sat Apr 29 12:22:36 EDT 2000:RMI:TCP Accept-3:[macfaq.dialup.cloud9.net:
sun.rmi. transport.DGCImpl[0:0:0, 2]: java.rmi.dgc.Lease
dirty(java.rmi.server.ObjID[], long, java.rmi.dgc.Lease)]
Sat Apr 29 12:22:39 EDT 2000:RMI:TCP Accept-3:[macfaq.dialup.cloud9.net:
FibonacciImpl[0]: java.math.BigInteger getFibonacci(java.math.BigInteger)]
Sat Apr 29 12:22:39 EDT 2000:RMI:TCP Accept-3:[macfaq.dialup.cloud9.net:
FibonacciImpl[0]: java.math.BigInteger getFibonacci(java.math.BigInteger)]
what's provided by the
RemoteServer class, you can retrieve the
log's PrintStream with the
getLog( ) method:
public static PrintStream getLog( )Once you have the print stream, you can write on it to add your own
comments to the log. For example:
PrintStream p = RemoteServer.getLog( );
p.println("There were " + n + " total calls to the remote object.");
18.6.3 The UnicastRemoteObject Class
The
UnicastRemoteObject class is a concrete subclass of
RemoteServer. To create a remote object, you can
extend UnicastRemoteObject and declare that your
subclass implements some subinterface of
java.rmi.Remote. The methods of the interface
provide functionality specific to the class, while the methods of
UnicastRemoteObject handle general remote object
tasks like marshalling and unmarshalling arguments and return values.
All of this happens behind the scenes. As an application programmer,
you don't need to worry about it.A UnicastRemoteObject runs on a single host, uses
TCP sockets to communicate, and has remote references that do not
remain valid across server restarts. While this is a good
general-purpose framework for remote objects, it is worth noting that
you can implement other kinds of remote objects. For example, you may
want a remote object that uses UDP, or one that remains valid if the
server is restarted, or even one that distributes the load across
multiple servers. To create remote objects with these properties,
extend RemoteServer directly and implement the
abstract methods of that class. However, if you
don't need anything so esoteric,
it's much easier to subclass
UnicastRemoteObject.The UnicastRemoteObject class has three protected
constructors:
protected UnicastRemoteObject( ) throws RemoteExceptionWhen you write a subclass of UnicastRemoteObject,
protected UnicastRemoteObject(int port) // Java 1.2
throws RemoteException
protected UnicastRemoteObject(int port, RMIClientSocketFactory csf,
RMIServerSocketFactory ssf) throws RemoteException // Java 1.2
you call one of these constructors, either explicitly or implicitly,
in the first line of each constructor of your subclass. All three
constructors can throw a RemoteException if the
remote object cannot be created.The noargs constructor creates a
UnicastRemoteObject that listens on an anonymous
port chosen at runtime. By the way, this is an example of an obscure
situation I mentioned in Chapter 9 and Chapter 10. The server is listening on an anonymous
port. Normally, this situation is next to useless because it is
impossible for clients to locate the server. In this case, clients
locate servers by using a registry that keeps track of the available
servers and the ports they are listening to.The downside to listening on an anonymous port is that
it's not uncommon for a firewall to block
connections to that port. The next two constructors listen on
specified ports so you can ask the network administrators to allow
traffic for those ports through the firewall.If the network administrators are uncooperative,
you'll need to use HTTP tunneling or a proxy server
or both. The third constructor also allows you to specify the socket
factories used by this UnicastRemoteObject. In
particular, you can supply a socket factory that returns sockets that
know how to get through the firewall.The UnicastRemoteObject class has several public
methods:
public Object clone( ) throws CloneNotSupportedExceptionThe clone( ) method simply creates a clone of the
public static RemoteStub exportObject(Remote r) throws RemoteException
public static Remote exportObject(Remote r, int port)
throws RemoteException // Java 1.2
public static Remote exportObject(Remote r, int port,
RMIClientSocketFactory csf, RMIServerSocketFactory ssf)
throws RemoteException // Java 1.2
public static boolean unexportObject(Remote r, boolean force)
throws NoSuchObjectException // Java 1.2
remote object. You call the
UnicastRemoteObject.exportObject( ) to use the
infrastructure that UnicastRemoteObject provides
for an object that can't subclass
UnicastRemoteObject. Similarly, you pass an object
UnicastRemoteObject.unexportObject( ) to stop a
particular remote object from listening for invocations.
18.6.4 Exceptions
The
java.rmi.server package defines a few more
exceptions. The exceptions and their meanings are listed in Table 18-2. All but
java.rmi.server.ServerNotActiveException extend,
directly or indirectly, java.rmi.RemoteException.
All are checked exceptions that must be caught or declared in a
throws clause.
Exception | Meaning |
|---|---|
ExportException | You're trying to export a remote object on a port that's already in use. |
ServerNotActiveException | An attempt was made to invoke a method in a remote object that wasn't running. |
ServerCloneException | An attempt to clone a remote object on the server failed. |
SocketSecurityException | This subclass of ExportException is thrown when the SecurityManager prevents a remote object from being exported on the requested port. |
Invocation. For a more detailed treatment, see Java
RMI, by William Grosso
(O'Reilly).
• Table of Contents• Index• Reviews• Reader Reviews• Errata• AcademicJava Network Programming, 3rd EditionBy
Elliotte Rusty Harold Publisher: O'ReillyPub Date: October 2004ISBN: 0-596-00721-3Pages: 706
Thoroughly revised to cover all the 100+ significant updates
to Java Developers Kit (JDK) 1.5, Java Network
Programming is a complete introduction to
developing network programs (both applets and applications)
using Java, covering everything from networking fundamentals
to remote method invocation (RMI). It includes chapters on
TCP and UDP sockets, multicasting protocol and content
handlers, servlets, and the new I/O API. This is the
essential resource for any serious Java developer.