A new and exciting possibility for connecting RMI objects to non-Java objects is the ability for RMI objects to communicate directly with remote CORBA objects using IIOP, the CORBA network interface protocol.[4] The standard RMI implementation provided with Java uses an RMI-specific protocol, JRMP, to communicate over the network. RMI/IIOP allows RMI objects to use the CORBA network protocol, IIOP, to communicate with other objects. This means that an RMI object using RMI/IIOP can communicate with a remote CORBA object, regardless of the implementation language of the CORBA object. Likewise, a CORBA object can interact with your Java RMI objects directly. This really gives you the best of both worlds, since you can then implement your remote clients using RMI and use either CORBA or RMI/JNI on the server to interface to any native legacy code.
[4]The RMI-IIOP tools and classes are an extension to the standard Java platform that has to be downloaded separately from http://java.sun.com/products/rmi-iiop/.
In order to convert your RMI objects to use IIOP, there are some changes you need to make:
Any implementation classes should extend the javax.rmi.PortableRemoteObject class, rather than java.rmi.server.UnicastRemoteObject.
All your stub and skeleton classes need to be regenerated using the updated rmic compiler provided with the RMI/IIOP installation. This updated compiler has an -iiop option that produces stubs and ties (ties refers to skeletons in the CORBA vernacular). These stubs and ties handle the link between client and server objects, but using IIOP rather than JRMP.
All use of the RMI Naming registry has to be converted to use JNDI to talk to a CORBA Naming Service. Objects that you export are bound to names in the CORBA Naming Service through the JNDI context, and remote objects you look up are accessed from the Naming Service through the JNDI context.
Instead of using the standard Java casting operator on remote objects you look up, you should use the javax.rmi.PortableRemoteObject.narrow() method.
To give you a taste for how to use RMI/IIOP with your RMI classes, let's convert our first Account example to use RMI/IIOP. First, we need to update the AccountImpl class to extend PortableRemoteObject. The following fragment of the IIOPAccountImpl class does that:
import javax.rmi.PortableRemoteObject; import java.rmi.RemoteException; import java.util.List; import java.util.ListIterator; public class IIOPAccountImpl extends PortableRemoteObject implements Account { // Remainder of implementation is identical
We can compile the updated IIOPAccountImpl using the regular Java compiler, then use the extended rmic compiler included with RMI/IIOP to generate IIOP stubs and ties:
% rmic -iiop -d /home/myclasses IIOPAccountImpl
This generates an IIOPAccountImpl_Stub class and an IIOPAccountImpl_Tie class, which act as the IIOP stub and tie for the remote object.
In the CORBA world, remote objects are looked up using the CORBA Naming Service, so we need to update the RegAccount class to use JNDI to register an Account object with a CORBA Naming Service, rather than the RMI registry. The updated IIOPRegAccount class looks like this:
import javax.naming.*; import java.rmi.*; public class IIOPRegAccount { public static void main(String argv[]) { try { // Make an Account with a given name IIOPAccountImpl acct = new IIOPAccountImpl("JimF"); // Get a reference to CORBA naming service using JNDI Hashtable props = new Hashtable(); props.put("java.naming.factory.initial", "com.sun.jndi.cosnaming.CNCtxFactory"); props.put("java.naming.provider.url", "iiop://objhost.org:900"); Context ctx = new InitialContext(props); // Register our Account with the CORBA naming service ctx.rebind("JimF", acct); System.out.println("Registered account."); } catch (Exception e) { e.printStackTrace(); } } }
Refer to Chapter 6, "JNDI", for details on the properties used to create the JNDI context and what they mean. All you need to glean from this is that we're trying to connect to a naming service running on objhost.org, listening to port 900. Once we are connected, we register the new IIOPAccountImpl object with the naming service using the Context.rebind() method.
Finally, we need to update our client so that it works with RMI/IIOP. Instead of using an RMI registry to look up the remote Account object, the client needs to use JNDI to connect to the same CORBA Naming Service that now hosts our Account object and ask for the Account by name. The updated IIOPAccountClient is shown here. Notice that we've also changed the client to use the PortableRemoteObject.narrow() method, instead of just casting the object returned from the lookup:
import javax.naming.*; import java.rmi.RMISecurityManager; public class IIOPAccountClient { public static void main(String argv[]) { try { // Lookup account object Hashtable props = new Hashtable(); props.put("java.naming.factory.initial", "com.sun.jndi.cosnaming.CNCtxFactory"); props.put("java.naming.provider.url", "iiop://objhost.org:900"); Context ctx = new InitialContext(props); Account jimAcct = (Account)PortableRemoteObject.narrow(ctx.lookup("JimF"), Account.class); // Make deposit jimAcct.deposit(12000); // Report results and balance. System.out.println("Deposited 12,000 into account owned by " + jimAcct.getName()); System.out.println("Balance now totals: " + jimAcct.getBalance()); } catch (Exception e) { System.out.println("Error while looking up account:"); e.printStackTrace(); } } }
In order to register the server object, we need a CORBA Naming Service running, just like we need an RMI registry with standard RMI. The RMI/IIOP package includes a special naming service that is started using the tnameserv utility. This tool is similar to the naming service provided with Java IDL (and discussed in Chapter 4, "Java IDL"), but this version is a CORBA Naming Service that also provides JNDI access. On objhost.org, we need to start the naming service like so:
objhost% tnameserv -ORBInitialPort 900
Now we can run IIOPRegAccount to register the Account object with the naming service, then run our IIOPAccountClient to access the Account and make a deposit. All network communications are now taking place using IIOP rather than the RMI protocol.
Since our Account object is now speaking IIOP, we can also access it from other, non-Java CORBA clients. First, we need to get an IDL interface for the Account interface, which can be done using the rmic compiler provided with RMI/IIOP. The -idl option generates an IDL mapping of a Java RMI interface using the Java-to-IDL mapping defined by the CORBA standard. With this IDL mapping, we can generate language-specific stubs that lets any CORBA client talk to our Java remote object. See Chapter 4, "Java IDL" for more details on using IDL and generating language-specific interfaces from it.
Copyright © 2001 O'Reilly & Associates. All rights reserved.