Making RMI programs use IIOP
A general guide to converting an RMI application to use RMI-IIOP.
Before you begin
Procedure
- If you are using the RMI registry for naming services,
you must switch to CosNaming:
- 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); - Modify all uses of RMI registry lookup(), bind(),
and rebind() to use JNDI lookup(), bind(),
and rebind() instead. Instead of:
use:import java.rmi.*; ... Naming.rebind("MyObject", myObj);import javax.naming.*; ... ic.rebind("MyObject", myObj);
- In both your client and server code, create an InitialContext
for JNDI.
- 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.
- 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); - 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. - 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.
- 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.
- Change all the places in your code where there is a Java cast of a remote interface to use javax.rmi.PortableRemoteObject.narrow().
- 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.
- 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 - 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.
- 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> - If the client is an applet, you must specify some properties
in the applet tag. For example:
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.java.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory java.naming.provider.url=iiop://<hostname>:2809The <hostname> in the provider URL is the host name that was used to start the CosNaming server.