Previous | Next | Trail Map | Java Objects and the Directory | Storing Objects in the Directory

Remote Objects

The RMI (Java Remote Method Invocation) system is a mechanism that enables an object on one Java virtual machine to invoke methods on an object in another Java virtual machine. Any object whose methods can be invoked in this way must implement the java.rmi.Remote interface. When such an object is invoked, its arguments are marshalled and sent from the local virtual machine to the remote one, where the arguments are unmarshalled and used. When the method terminates, the results are marshalled from the remote machine and sent to the caller's virtual machine.

To make a remote object accessible to other virtual machines, a program typically registers it with the RMI registry. The program supplies to the registry the string name of the remote object as well as the remote object itself. When a program wants to access a remote object, it supplies the object's string name to the registry that is on the same machine as the remote object. The registry returns to the caller a reference (called stub) to the remote object. When the program receives the stub for the remote object, it can invoke methods on the object (through the stub).

A program can also obtain references to remote objects as a result of remote calls to other remote objects or from other naming services. For example, the program can look up a reference to a remote object from an LDAP server that supports the schema defined RFC 2713.

The string name accepted by the RMI registry has the syntax "rmi://hostname:port/remoteObjectName", where hostname and port identify the machine and port, respectively, on which the RMI registry is running and remoteObjectName is the string name of the remote object. hostname, port, and the prefix, "rmi:", are optional. If hostname is not specified, then it defaults to the local host. If port is not specified, then it defaults to 1099. If remoteObjectName is not specified, then the object being named is the RMI registry itself. See the RMI specification for details.

RMI can be supported by using the Java Remote Method Protocol (JRMP) and the Internet Inter-ORB Protocol (IIOP). The JRMP is a specialized protocol designed for RMI; the IIOP is the standard protocol for communication between CORBA objects. RMI over IIOP allows Java remote objects to communicate with CORBA objects that might be written in a non-Java programming language.

Some service providers, such as Sun's LDAP service provider, support the binding of java.rmi.Remote objects into directories. When java.rmi.Remote objects and/or RMI registries are bound into an enterprise-wide shared namespace such as the LDAP, RMI clients can look up java.rmi.Remote objects without knowing on which machine the objects are running.

Binding a Remote Object


Before you go on: To run this example, you need the Java 2 Platform, v1.2 or higher release. You also need ldapbp.jar, as stated in the introduction of this lesson.

The following example defines a java.rmi.Remote interface Hello that has one method, sayHello().

public interface Hello extends Remote {
    public String sayHello() throws RemoteException;
}
It also defines an implementation of this interface, HelloImpl.
public class HelloImpl extends UnicastRemoteObject implements Hello {
    public HelloImpl() throws RemoteException {
    }

    public String sayHello() throws RemoteException {
        return ("Hello, the time is " + new java.util.Date());
    }
}

This example also creates an instance of HelloImpl and binds it in the directory, assigning it the name "cn=RemoteHello".

// Create the remote object to be bound, and give it a name
Hello h = new HelloImpl();

// Bind the object to the directory
ctx.bind("cn=RemoteHello", h);

After the object has been bound in the directory, an application can look it up by using the following code.

Hello h2 = (Hello)ctx.lookup("cn=RemoteHello");
h2.sayHello();

To run this example, you must do the following.

  1. Compile Hello.java, HelloImpl.java and this example:
    # javac Hello.java HelloImpl RemoteObj.java
    
  2. Run rmic with HelloImpl as the argument to produce the stubs for the remote object:
    # rmic HelloImpl
    
  3. Copy Hello.class, HelloImpl.class and the class files generated by rmic to a directory on a Web server.
  4. Specify this directory as the codebase to the Java interpreter.
    # java -Djava.rmi.server.codebase=http://web1/example/classes/ RemoteObj
    
RemoteObj does not terminate, because it created the remote object HelloImpl that other RMI clients can contact and use. However, this program will terminate eventually, when the remote object becomes garbage collected. To prevent the object's being garbage collected, you must maintain a (live) reference to the remote object. If you had registered the object in the RMI registry instead, then maintaining a reference would not be necessary because the registry would automatically maintain a reference to the object.

When you later look up this object from the directory, the directory will return the bound HelloImpl remote object. The RMI will automatically download the necessary class files from the codebase specified in the "java.rmi.server.codebase" property. See the Reading Objects from the Directory (in the Java Objects and the Directory trail) lesson for an example.

Binding a Remote Object by Using a Reference


Before you go on: This example requires that you have started the RMI registry on your machine. You also need rmiregistry.jar, as stated in the introduction of this lesson.
The following example uses the same Hello and HelloImpl classes used in the previous example. It creates a Reference(in the API reference documentation) containing an RMI URL ("rmi://mymachine/hello") and binds it in the directory.
String rmiurl = "rmi://mymachine/hello";

// Create the reference containing the (future) location of the object
Reference ref = new Reference("Hello", new StringRefAddr("URL", rmiurl));

// Bind the object to the directory
ctx.bind("cn=RefHello", ref);

It then creates an instance of HelloImpl and binds it in the local RMI registry by using the same RMI URL ("rmi://mymachine/hello").

// Create the remote object to be bound
Hello h = new HelloImpl();

// Bind the object to the RMI registry
ctx.rebind(rmiurl, h);

After the object has been bound in both the directory and the RMI registry, an application can look up the object by using the following code.

Hello h2 = (Hello)ctx.lookup("cn=RefHello");
System.out.println(h2.sayHello());

In effect, this method has one more level of indirection than the previous example offered. The information stored in the directory (the Reference) is actually a pointer to information stored in another naming service (the RMI registry), which in turn, contains the reference to the java.rmi.Remote object.

To run this example, you must do the following.

  1. Perform Steps 1-3 from the previous example.
  2. Compile this example:
    # javac RemoteRef.java
    
  3. Specify the codebase directory as the codebase to the Java interpreter.
    # java -Djava.rmi.server.codebase=http://web1/example/classes/ RemoteRef
    
RemoteRef does not terminate, because it created the remote object HelloImpl that other RMI clients can contact and use.

When you later look up this object from the directory, the directory will return the bound HelloImpl remote object. The RMI will automatically download the necessary class files from the codebase specified in the "java.rmi.server.codebase" property. See the Reading Objects from the Directory (in the Java Objects and the Directory trail) lesson for an example.

Binding a Remote Object That Uses IIOP


Before you go on: This example requires that you have ldapbp.jar, as stated in the introduction of this lesson. If you are not using the Java 2 SDK, v1.3, then you also need to install the RMI-IIOP Standard Extension. If you are not using the Java 2 SDK, v1.2 or higher release, then you also need to install Java IDL, a version of which comes with the RMI-IIOP Standard Extension.
The procedure for binding a java.rmi.Remote object that uses IIOP or JRMP is identical as far as the JNDI is concerned. From the user/application's perspective, they differ only in how the stubs for the java.rmi.Remote object are generated. Looking up the object presents a bigger difference: When the object is looked up from the directory (or some other naming service), the result must be narrowed by using javax.rmi.PortableRemoteObject.narrow() instead of the Java type cast operator.

The following example uses the Hello interface from the JRMP example. It defines an implementation of this interface, RiHelloImpl, that is analogous to HelloImpl, except that it extends from javax.rmi.PortableRemoteObject instead of from java.rmi.server.UnicastRemoteObject.

public class RiHelloImpl extends PortableRemoteObject implements Hello {
    public RiHelloImpl() throws RemoteException {         
    }

    public String sayHello() throws RemoteException {
        String date = new String((new java.util.Date()).toString());
        return ("RMI/IIOP hello | " + date);
    }
}
The example creates an instance of RiHelloImpl and binds it in the directory, assigning it the name "cn=RmiiiopHello".
// Create the remote object to be bound, and give it a name
Hello h = new RiHelloImpl();

// Bind the object to the directory
ctx.bind("cn=RmiiiopHello", h);

After the object has been bound in the directory, an application can look it up by using the following code.

// Look up the object
org.omg.CORBA.Object cobj = (org.omg.CORBA.Object)ctx.lookup("cn=RmiiiopHello");

// Narrow the object to the desired type
Hello robj = (Hello)PortableRemoteObject.narrow(cobj, Hello.class);

// Invoke the method
System.out.println(robj.sayHello());
To run this example, you must do the following.
  1. Compile Hello.java, RiHelloImpl.java and this example:
    # javac Hello.java RiHelloImpl RmiiiopObj.java
    
  2. Run rmic with RiHelloImpl as the argument and the "-iiop" option to produce the IIOP stubs for the remote object:
    # rmic -iiop RiHelloImpl
    
  3. Copy Hello.class, RiHelloImpl.class and the class files generated by rmic to a directory on a Web server.
  4. Specify this directory as the codebase to the Java interpreter.
    # java -Djava.rmi.server.codebase=http://web1/example/classes/ RmiiiopObj
    
RmiiiopObj does not terminate, because it created the remote object RiHelloImpl that other RMI clients can contact and use.

When you later look up this object from the directory, the directory will return the bound RiHelloImpl remote object. The RMI will automatically download the necessary class files from the codebase specified in the "java.rmi.server.codebase" property. See the Reading Objects from the Directory (in the Java Objects and the Directory trail) lesson for an example.


Previous | Next | Trail Map | Java Objects and the Directory | Storing Objects in the Directory