Making RMI programs use IIOP

A general guide to converting an RMI application to use RMI-IIOP.

Before you begin

To use these instructions, your application must already use RMI.

Procedure

  1. If you are using the RMI registry for naming services, you must switch to CosNaming:
    1. In both your client and server code, create an InitialContext for JNDI. For a Java™ application use the following code:
      import javax.naming.*;
      ...
      Context ic = new InitialContext();
      For an applet, use this alternative code:
      import java.util.*;
      import javax.naming.*;
      ...
      Hashtable env = new Hashtable();
      env.put("java.naming.applet", this);
      Context ic = new InitialContext(env);
    2. Modify all uses of RMI registry lookup(), bind(), and rebind() to use JNDI lookup(), bind(), and rebind() instead. Instead of:
      import java.rmi.*;
      ...
      Naming.rebind("MyObject", myObj);
      use:
      import javax.naming.*;
      ...
      ic.rebind("MyObject", myObj);
  2. If you are not using the RMI registry for naming services, you must have some other way of bootstrapping your initial remote object reference. For example, your server code might be using Java serialization to write an RMI object reference to an ObjectOutputStream and passing this to your client code for deserializing into an RMI stub. When doing this in RMI-IIOP, you must also ensure that object references are connected to an ORB before serialization and after deserialization.
    1. On the server side, use the PortableRemoteObject.toStub() call to obtain a stub, then use writeObject() to serialize this stub to an ObjectOutputStream. If necessary, use Stub.connect() to connect the stub to an ORB before serializing it. For example:
      org.omg.CORBA.ORB myORB = org.omg.CORBA.ORB.init(new String[0], null);
      Wombat myWombat = new WombatImpl();
      javax.rmi.CORBA.Stub myStub = (javax.rmi.CORBA.Stub)PortableRemoteObject.toStub(myWombat);
      myStub.connect(myORB);
      // myWombat is now connected to myORB.  To connect other objects to the
      // same ORB, use PortableRemoteObject.connect(nextWombat, myWombat);
      FileOutputStream myFile = new FileOutputStream("t.tmp");
      ObjectOutputStream myStream = new ObjectOutputStream(myFile);
      myStream.writeObject(myStub);
    2. On the client side, use readObject() to deserialize a remote reference to the object from an ObjectInputStream. Before using the deserialized stub to call remote methods, it must be connected to an ORB. For example:
      FileInputStream myFile = new FileInputStream("t.tmp");
      ObjectInputStream myStream = new ObjectInputStream(myFile);
      Wombat myWombat = (Wombat)myStream.readObject();
      org.omg.CORBA.ORB myORB = org.omg.CORBA.ORB.init(new String[0], null);
      ((javax.rmi.CORBA.Stub)myWombat).connect(myORB);
      // myWombat is now connected to myORB.  To connect other objects to the
      // same ORB, use PortableRemoteObject.connect(nextWombat, myWombat);
    The JNDI approach is much simpler, so it is preferable to use it whenever possible.
  3. Either change your remote implementation classes to inherit from javax.rmi.PortableRemoteObject, or explicitly to export implementation objects after creation by calling PortableRemoteObject.exportObject(). For more discussion on this topic, read Connecting IIOP stubs to the ORB.
  4. Change all the places in your code where there is a Java cast of a remote interface to use javax.rmi.PortableRemoteObject.narrow().
  5. Do not depend on distributed garbage collection (DGC) or use any of the RMI DGC facilities. Use PortableRemoteObject.unexportObject() to make the ORB release its references to an exported object that is no longer in use.
  6. Regenerate the RMI stubs and ties using the rmic command with the -iiop option. This will produce stub and tie files with the following names:

    _<implementationName>_Tie.class
    _<interfaceName>_Stub.class

  7. Before starting the server, start the CosNaming server (in its own process) using the tnameserv command The CosNaming server uses the default port number of 2809. If you want to use a different port number, use the -ORBInitialPort parameter.
  8. When starting client and server applications, you must specify some system properties. When running an application, you can specify properties on the command line:
    java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
         -Djava.naming.provider.url=iiop://<hostname>:2809
         <appl_class>
  9. If the client is an applet, you must specify some properties in the applet tag. For example:
    java.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
    java.naming.provider.url=iiop://<hostname>:2809
    This example uses the default name service port number of 2809. If you specify a different port in the previous step, you need to use the same port number in the provider URL here. The <hostname> in the provider URL is the host name that was used to start the CosNaming server.

Results

Your application can now communicate with CORBA objects using RMI-IIOP.