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 classes. Fortunately, you need to be familiar with only a few of these 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 Remote Server. Any remote objects you write will likely either extend or use 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.

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 Object 
 implements Remote, Serializable

You can think of this class as a special version of 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 remote object. 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 remote object. 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.

Starting in Java 1.2, there’s one other instance method in this class, getRef( ) :

public RemoteRef getRef(  ) // Java 1.2

This returns a remote reference to the class:

public abstract interface RemoteRef extends Externalizable

Java 1.2 also adds one static method, RemoteObject.toStub( ):

public static Remote toStub(Remote ro) // Java 1.2
 throws NoSuchObjectException

RemoteObject.toStub( ) converts a given remote object into the equivalent stub object for use in the client virtual machine. This can help you dynamically generate stubs from within your server without using rmic.

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 RemoteObject

In Java 1.1, UnicastRemoteObject is the only subclass of RemoteServer included in the core library. Java 1.2 adds the java.rmi.activation.Activatable and java.rmi.activation.ActivationGroup classes. You can add others (for example, a UDP or multicast remote server) by writing your own subclass of RemoteServer.

Constructors

There are two constructors for this class:

protected RemoteServer(  ) 
protected RemoteServer(RemoteRef r)

However, you won’t instantiate this class yourself. Instead, you will instantiate a subclass like UnicastRemoteObject. That class’s constructor will call one of these protected constructors from the first line of its constructor.

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 ServerNotActiveException

RemoteServer.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.

Logging

For debugging purposes, it is sometimes useful to see the calls that are being made to your remote object and the object’s responses. You can get a log for your 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);

For example, 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:
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)]

If you want to add extra information to the log, in addition to 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.");

The UnicastRemoteObject Class

The UnicastRemoteObject class is a concrete subclass of RemoteServer. To create a remote object, you can extend UnicastRemoteObject in your own subclass and declare that your subclass implements some subclass of the java.rmi.Remote interface. The methods of the interface provide functionality specific to the class, while the methods of UnicastRemoteObject handle general remote object tasks like marshaling and unmarshaling 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, you would extend RemoteServer directly and implement the abstract methods of that class. However, if you don’t need anything so esoteric, you will find it much easier to subclass UnicastRemoteObject.

The UnicastRemoteObject class has three protected constructors:

protected UnicastRemoteObject(  ) throws RemoteException
protected UnicastRemoteObject(int port)               // Java 1.2
 throws RemoteException
protected UnicastRemoteObject(int port, RMIClientSocketFactory csf, 
 RMIServerSocketFactory ssf) throws RemoteException  // Java 1.2

The noargs constructor creates a UnicastRemoteObject that listens on an anonymous port chosen at runtime.[31] Java 1.2 adds two more constructors that listen on the specified port. The third constructor also allows you to specify the socket factories used by this UnicastRemoteObject. When you write a subclass of UnicastRemoteObject, 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 UnicastRemoteObject class has several public methods:

public Object clone(  ) throws CloneNotSupportedException
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

The clone( ) method simply creates a clone of the remote object. You call the UnicastRemoteObject.exportObject( ) to use the infrastructure that Unicast RemoteObject provides for an object that can’t subclass Unicast RemoteObject Similarly, you pass an object UnicastRemoteObject.unexportObject( ) to stop a particular remote object from listening for invocations.

Exceptions

The java.rmi.server package defines six new exceptions. The exceptions and their meanings are listed in Table 18.3. All except 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.

Table 18-3. java.rmi.server Exceptions

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.

SkeletonNotFoundException

The server is unable to load the skeleton it needs to respond to a remote method invocation. This can mean several things: the skeleton class file may not be anywhere in the codebase; the skeleton is in the codebase but has a name conflict with another class; the URL given may be incorrect; or the skeleton may be of the wrong class. This is deprecated starting in Java 1.2 because skeletons are no longer used.

SkeletonMismatchException

The skeleton and the stub for a class don’t match. This is unusual but may happen if different versions of the source code are used to make the stub and the skeleton. This is deprecated starting in Java 1.2 because skeletons are no longer used.

This chapter has been a fairly quick look at Remote Method Invocation. For a more detailed treatment, see Java Distributed Computing, by Jim Farley (O’Reilly & Associates, Inc., 1998).



[31] By the way, this is an example of an obscure situation I mentioned in Chapter 10, and Chapter 11. The server is listening on an anonymous port. Normally, this would be next to useless because it would be impossible for clients to locate the server. In this case, clients locate servers by using a registry, which keeps track of what servers are available and what ports they are listening to.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.140.185.170