RMI-IIOP Programmer's Guide
This document discusses how to write Java Remote Method Invocation (RMI) programs that can access remote objects by using the Internet Inter-ORB Protocol (IIOP). By making your RMI programs conform to a small set of restrictions, your CORBA clients in any language can access RMI-IIOP servers. RMI-IIOP gives you RMI ease-of-use coupled with CORBA/IIOP language interoperability.
RMI lacks interoperability with other languages because it does not use CORBA-IIOP as the communication protocol.
The Java(TM) 2 Platform, Standard Edition (J2SE) CORBA/IIOP implementation is known as Java IDL. Along with the idlj compiler, Java IDL can be used to define, implement, and access CORBA objects from the Java programming language.
The Java IDL web page gives you a good, Java-centric view of CORBA/IIOP programming. To get a quick introduction to writing Java IDL programs, see the Getting Started: Hello World web page.
Here are the primary rmic flags that support the CORBA/IIOP functionality:
-iiop -- Generates IIOP stubs/ties.
-iiop -poa -- Generates IIOP stubs/ties that work with a Portable Object Adapter (POA).
-idl -- Generates IDL.
The following options are used in conjunction with the -idl option.
-noValueMethods -- Stops generation of IDL for methods and constructors within IDL valuetypes.
-always -- Forces regeneration even when existing stubs/ties/idl are newer than the input class. Only valid when -iiop and/or -idl flags are present.
-idlModule <fromJavaPackage<.class>> <toIDLModule> -- Specifies IDLEntity package mapping. For example: -idlModule foo.bar my::real::idlmod
-idlFile <fromJavaPackage<.class>> <toIDLFile> -- Specifies IDLEntity file mapping. For example: -idlFile test.pkg.X TEST16.idl
For more detailed information on the rmic compiler, read the rmic documentation.
Stub classes are also generated for abstract interfaces. An abstract interface is an interface that does not extend java.rmi.Remote, but whose methods all throw either java.rmi.RemoteException or a superclass of java.rmi.RemoteException. Interfaces that do not extend java.rmi.Remote and have no methods are also abstract interfaces.
QUESTION: I have a RMI-IIOP application which was running on J2SE 1.3. When I generate new stubs and skeletons using rmic -iiop -poa
, it does not work. Why ?
ANSWER: There are 2 different ways to compile and run RMI-IIOP programs, which are listed below. We do not recommend that you combine these.
- The default RMI-IIOP behavior. An example of an application that uses the default RMI-IIOP behavior can be found at Tutorial: Getting Started Using RMI-IIOP.
- POA-based RMI-IIOP. An example of an application that uses the non-standard POA-based RMI-IIOP behavior can be found at Getting Started Using RMI-IIOP: Example Using POA-based server-side model.
New to this release of Java SE is the -iiop -poa option. Using the -iiop flag with the -poa option changes the inheritance from org.omg.CORBA_2_3.portable.ObjectImpl to org.omg.PortableServer.Servant. This type of mapping is nonstandard and is not specified by the Java Language to OMG IDL Language Mapping Specification.
The PortableServer module for the Portable Object Adapter (POA) defines the native Servant type. In the Java programming language, the Servant type is mapped to the Java org.omg.PortableServer.Servant class. It serves as the base class for all POA servant implementations and provides a number of methods that may be invoked by the application programmer, as well as methods which are invoked by the POA itself and may be overridden by the user to control aspects of servant behavior.
Note: After the OMG IDL is generated using rmic -idl, use the generated IDL with an IDL-to-C++ or other language compiler, but not with the IDL-to-Java language compiler. "Round tripping" is not recommended and should not be necessary. The IDL generation facility is intended to be used with other languages such as C++. Java clients or servers can use the original RMI-IIOP types.
IDL provides a purely declarative, programming language independent means for specifying the API for an object. The IDL is used as a specification for methods and data that can be written in and invoked from any language that provides CORBA bindings. This includes Java and C++ among others. See the Java Language to IDL Mapping (OMG) document for a complete description.
Note: The generated IDL can only be compiled using an IDL compiler that supports the CORBA 2.3 extensions to IDL.
See the RMIC tool page (Solaris Version/Windows version) for a complete rmic description.
import javax.naming.*; ... Context ic = new InitialContext();
import java.rmi.*; ... Naming.rebind("MyObject", myObj);use:
import javax.naming.*; ... ic.rebind("MyObject", myObj);
import java.util.*; import javax.naming.*; ... Hashtable env = new Hashtable(); env.put("java.naming.applet", this); Context ic = new InitialContext(env);
On the server side, use the PortableRemoteObject.toStub() call to obtain a stub, then use writeObject() to serialize this stub to an ObjectOutputStream. The code to do this looks something like:
On the client side, use readObject() to deserialize a remote reference to the object from an ObjectInputStream, with code like:org.omg.CORBA.ORB myORB = org.omg.CORBA.ORB.init(new String, 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);
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, 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);
orbd -ORBInitialPort port#You must specify the port number when starting ORBD.
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop://<hostname>:1050 <appl_class>This example uses the name service port number of 1050. If you specified a different port in step 7, 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 in step 7.
java.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory java.naming.provider.url=iiop://<hostname>:1050This example uses the name service port number of 1050. If you specified a different port in step 7, 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 in step 7.
For tutorials that describe creating a new RMI-IIOP application, link to Getting Started Using RMI-IIOP: Example Using POA-based server-side model or Tutorial: Getting Started Using RMI-IIOP.
The PortableRemoteObject.exportObject() call only creates a tie object and caches it for future usage. The created tie does not have a delegate or an ORB associated. This is known as explicit invocation.
The PortableRemoteObject.exportObject() happens automatically when the servant instance is created. This happens when a PortableRemoteObject constructor is called as a base class. This is known as implicit invocation.
Later, when PortableRemoteObject.toStub() is called by the application, it creates the corresponding Stub object and associates it with the cached Tie object. But since the Tie is not connected and does not have a delegate, the newly created stub also does not have a delegate or ORB.
The delegate is set for the stub only when the application calls Stub.connect(orb). Thus, any operations on the stub made before the ORB connection is made will fail.
The Java Language to IDL Mapping Specification says the following about the Stub.connect() method:
The connect method makes the stub ready for remote communication using the specified ORB object orb. Connection normally happens implicitly when the stub is received or sent as an argument on a remote method call, but it is sometimes useful to do this by making an explicit call (e.g., following deserialization). If the stub is already connected to orb (i.e., has a delegate set for orb), then connect takes no action. If the stub is connected to some other ORB, then a RemoteException is thrown. Otherwise, a delegate is created for this stub and the ORB object orb.
For servants that are not POA-activated, Stub.connect(orb) is necessary as a required setup.
NOTE: Although it is true that ORBs written in different languages should be able to talk to each other, we haven't tested the interoperability of the Java ORB with other vendor's ORBs.
UnicastRemoteObject should be used as the superclass for the object implementation in RMI programming. PortableRemoteObject should be used in RMI-IIOP programming. If PortableRemoteObject is used, you can switch the transport protocol to either JRMP or IIOP during runtime.
ulimit -n 90