Java PrimerRMI Over IIOPWhen the Java and CORBA Worlds Collide

IN 1997, SUN Microsystems announced that Java RMI would support the CORBA Internet Inter-ORB Protocol (IIOP) as a transport protocol in addition to its native transport protocol. After some two years, a reference implementation of this version of Java RMI, called RMI over IIOP (RMI/IIOP), was finished and released in June 1999. The reference implementation of RMI over IIOP, developed jointly by Sun and IBM, can now be freely used by Java developers.

I discuss the advantages promised by RMI/IIOP, focusing on what it brings to distributed application development in Java, and show you how to develop a distributed application in a few steps with this new technology.

Java–CORBA Unification
CORBA is a specification produced by the Object Management Group (OMG) that defines a standard interoperability architecture within distributed heterogeneous environments. IIOP is CORBA's communication protocol over TCP/IP networks. IIOP makes it possible for different ORB implementations to interoperate. Java IDL from Sun adds CORBA capability to the Java platform by providing an ORB over IIOP communication.

Java RMI, on the other hand, is analogous to CORBA; still, it provides a much simpler model for distributed object computing based on the Java language. Java RMI uses a transport protocol called Java RMI Protocol (JRMP). JRMP is Java RMI-specific and cannot be used for interoperation with other languages. We will call this technology RMI/JRMP hereafter.

RMI/IIOP promises to bring the Java and CORBA worlds closer together than ever before. Java has already proved itself to be an ideal language in the development of CORBA applications. With the implementation of RMI/IIOP, Java RMI objects can be accessed by CORBA clients written in other languages. Moreover, Java RMI clients can access CORBA objects regardless of what language they are written in. This means Java RMI clients do not need to be IDL-aware to access CORBA objects.

Basically, RMI/IIOP is an integration of Java RMI and Java IDL that lets you implement and access CORBA objects without IDL.

To achieve the RMI over IIOP goals, some members of OMG (IBM, Inprise, Netscape, Oracle, and Sun) worked together to unify CORBA and Java RMI object models. As a result of this joint effort, the current version of CORBA (2.3) includes a Java-to-IDL specification that describes how Java RMI remote object interfaces should be translated to CORBA IDL, and an Objects-by-Value specification that brings pass-by-value semantics to the CORBA world.

Java-to-IDL solves the interoperability problem between Java RMI objects and CORBA objects by defining a strict subset of Java RMI that can be mapped to IDL. Now you can define an RMI object interface and translate it to an equivalent IDL interface using a Java-to-IDL compiler (for example, rmic). Then you have two choices to implement the interface: 1) either implement the RMI interface in Java language or 2) use the generated IDL and implement it as a CORBA object in another language.

Figure 1
Figure 1. Java RMI clients can access RMI/IIOP objects through ordinary RMI interfaces. CORBA clients need equivalent interfaces in IDL.

In the first case, you need the IDL interface only for your CORBA clients (Figure 1). In the second case, you also need the IDL interface to implement the RMI/IIOP object as a CORBA object (Figure 2). Your choice of implementation will make no difference to your object's Java RMI clients because the implementation details are kept hidden from them. What they see in both cases is only a remote interface defined in ordinary RMI syntax.

Figure 2
Figure 2. Java RMI clients can access RMI/IIOP objects implemented as CORBA objects through ordinary RMI interfaces. CORBA clients and RMI/IIOP object implementations need equivalent interfaces in IDL.

The introduction of the Objects-by-Value specification into CORBA was necessary for transporting programming language objects by value. Before that, the object types that could be transported by value via IIOP were limited to a specified set of primitive types. Now objects can be transported by value provided that both sending and receiving sides have the implementation (i.e., the class) or that the implementation can be dynamically loaded (as in the case of dynamic stub loading in Java RMI applications).

RMI/IIOP provides the following benefits to developers over RMI/JRMP:

  • Interoperability with objects written in other languages through the use of language-independent CORBA IDL.
  • Transaction and security contexts can be propagated implicitly because of the use of IIOP, which can implicitly propagate context information.
  • IIOP-based firewall support via IIOP proxies that can pass IIOP traffic in a controlled and manageable way.
With IIOP as the transport protocol, Java RMI finds the support it needs to promote industrial-strength distributed application development within a Java environment only. RMI/IIOP nevertheless has some weaknesses of its own compared to RMI/JRMP:

  • You do not have distributed garbage collection support any longer. Until the introduction (if any) of distributed garbage collection techniques into the CORBA architecture, you cannot rely on Java RMI/JRMP's features while using RMI/IIOP.
  • You cannot use Java's casting operator in your clients after getting a remote object reference. Instead, you need to use a special method to get the right type.
  • You are not allowed to inherit the same method name into your remote interface from different base remote interfaces.
  • All constant definitions in remote interfaces must be of primitive types or Strings and evaluated at compile time.
RMI/IIOP and EJB Relation
EJB is the key constituent of J2EE, which was introduced by Sun in the fall of 1998. J2EE is a standard architecture for the needs of enterprise developers and users, providing support for EJB components, Servlets, and JSPs. EJB is the component model of J2EE used to support development, deployment, and management of transactional business systems using distributed objects. Applications developed with the EJB technology are potentially scalable, transactional, and secure in multitier, multiuser distributed environments.

EJB components live within EJB containers that provide runtime environments for EJB components. EJB containers can be developed by multiple vendors provided that they implement the same API defined in the EJB specification. The EJB specification is transport protocol neutral. Each EJB container vendor is responsible for implementing his/her own preferred protocol. Nevertheless, EJB uses RMI semantics.

To help interoperability for EJB environments that include systems from multiple vendors, Sun has defined a standard mapping of EJB-to-CORBA, based on the specification of Java-to-IDL from OMG. That is, EJB interfaces are inherently RMI/IIOP interfaces. This is not coincidental if we think about the requirements of enterprise-class applications. Enterprise-class applications are transactional applications that operate in distributed environments. For these applications, scalability and security are of paramount importance.

Standard RMI fails to fulfill the requirements of enterprise-class applications because JRMP:

  • is specific for Java only;
  • does not support transaction and security context propagation across distributed JVMs (in fact, it does not support context propagation at all); and
  • is not as scalable as IIOP.
RMI/IIOP overcomes all the limitations of RMI/JRMP by leveraging enterprise-ready IIOP, which supports propagation of transaction and security context, and which is more scalable than JRMP. The EJB-to-CORBA mapping not only enables on-the-wire interoperability among multiple vendors' implementations of the EJB container, but also enables non-Java clients to access server-side applications written as EJB through standard CORBA APIs.

Figure 3 illustrates a scenario where EJB components hosted by two EJB containers from different vendors interoperate with each other through IIOP.

Figure 3
Figure 3. Example of interoperability scenario between different vendors of EJB containers.

Note that the use of EJB-to-CORBA mapping by the EJB containers is not a requirement in the current specification of EJB (1.1). However, it is likely that the next release of the specification will require EJB-to-CORBA mapping implemented by EJB container vendors.

RMI/IIOP in Action
Now that we've examined RMI/IIOP and its promises for the next generation of distributed applications, let's see how we can develop a distributed application using this technology. For the purposes of this article we will implement a fax machine whose services are available on the Internet.

For our example, we use Sun and IBM's coproduct rmic, which comes with JDK 1.3. rmic can now generate IIOP stubs and ties for remote object interfaces in addition to JRMP stubs and skeletons. The new rmic flags are:

  • iiop: generates stubs and ties for IIOP;
  • idl: generates IDL for CORBA clients and servers written in other languages.
If you do not specify any flag, rmic generates stubs and skeletons for JRMP.

To develop a distributed application using RMI/IIOP, we first need to define remote interfaces to our objects that we intend to have remotely accessible over IIOP. This is exactly the same as defining RMI/JRMP interfaces if we adhere to the Java-to-IDL specification while developing with RMI/IIOP.

Listing 1 shows a simplified version of an Internet fax machine interface that has two methods: send a document to a specified destination and get the size of the working queue of the fax machine. Document, the type of document that can be faxed, as well as PDFDocument, are defined elsewhere as serializable.

Next, we implement the interface in CanonInternetFax as we would implement it for RMI/JRMP (see Listing 2). However, this time, instead of inheriting from UnicastRemoteObject, our implementation inherits from PortableRemoteObject to give it a CORBA personality.

The next step is to write a server class that creates an InternetFax instance and registers it with the CORBA CosNaming service (CORBA's standard naming service), which then waits for client invocations (Listing 3).

The example client implementation uses JNDI to lookup our InternetFax server and faxes a PDF document through the object reference it received from JNDI. The client code is shown in Listing 4.

After compiling the sources, to generate stub and tie classes, we need to run rmic with -iiop flag, which works with the compiled Java class files:


rmic -iiop -d destination/directory fax.CanonInternetFax
This will generate the following Java classes:

  • _InternetFax_Stub.class: the client-side stub.
  • _CanonInternetFax_Tie.class: the server-side tie (delegation based skeleton).
We are now ready to start the server and client with the following commands:


Java -Djava.naming.factory.initial=
 com.sun.jndi.cosnaming.CNCtxFactory
-Djava.naming.provider.url=iiop://:900
  fax.iiop.InternetFaxServer

java -Djava.naming.factory.initial=
 com.sun.jndi.cosnaming.CNCtxFactory
-Djava.naming.provider.url=iiop://:900
  fax.iiop.InternetFaxClient
hostname is the name of the machine where a CosNaming service is running. Notice that we use Sun's implementation of JNDI/CosNaming provider to set the JNDI naming factory for initial contexts. To be able to use the CosNaming service, we also need to start the tnameserv, which is the CosNaming implementation from Sun included in the JDK 1.3 software.

Figure 4 shows the architecture of our application in the case of RMI/IIOP. Note that ORBs in this architecture can be from different vendors.

Figure 4
Figure 4. RMI/IIOP architecture.

Dual Export
RMI/JRMP and RMI/IIOP objects can live together in the same environment. In our example application, we use inheritance to develop RMI/IIOP object implementation. Figure 5 shows a UML class diagram for our example application, and Figure 6 shows another UML class diagram for the same application if we use RMI/JRMP. In both cases, our implementation class has to inherit from a transport-specific class. Fortunately, there is a second method to develop RMI objects without using inheritance and without being bound to a single transport protocol.

Figure 5
Figure 5. RMI/IIOP class hierarchy in UML.

 

 

Figure 6
Figure 6. RMI/JRMP class hierarchy in UML.

We will now use the so called dual export technique and make our CanonInternetFax available to both JRMP and IIOP clients. There are some changes we need to make to our existing implementations:

  1. CanonInternetFax implementation should not inherit from either UnicastRemoteObject (of JRMP) or PortableRemoteObject (of IIOP).
  2. The main method of InternetFaxServer needs to export the object explicitly to both JRMP (using UnicastRemoteObject) and IIOP (using PortableRemoteObject).
  3. To be available to both JRMP and IIOP clients, the name of the object has to be bound to both RMI registry and CosNaming.
  4. We will no longer pass the naming service provider as a command-line argument using *D when we start the server.
Listings 5 and 6 show the reworked CanonInternetFax and InternetFaxServer classes to support both JRMP and IIOP clients.

Please note that, for the sake of simplicity, this article does not address security and codebase issues.

RMI/IIOP or RMI/JRMP?
According to both Sun and IBM, RMI/IIOP is not intended as a replacement for RMI/JRMP. They both have their uses, and will continue to be supported and enhanced. Here are some heuristics if you are having a difficult time choosing one of them.

RMI/IIOP is for Java programmers who want to program with the ease of Java RMI but need interoperability with other languages and support for enterprise-class applications. RMI/IIOP can satisfy your needs with IIOP's scalability, and support security and transaction propagation. Also, if you want to leverage the scalability of IIOP, RMI/IIOP is a better choice than RMI/JRMP.

Use RMI/JRMP if you are implementing small-scale application and want to have seamless integration with Java object model (for example, automatic distributed garbage collection support). Or better, develop your remote object implementations without inheriting from either UnicastRemoteObject or PortableRemoteObject and then use dual export technique to serve clients in both worlds.

One word of caution for RMI/IIOP users: I've used the rmic version that comes with JDK 1.3 software for the purposes of the example application. JDK 1.3 includes an ORB that unfortunately does not support implicit context propagation. Support for implicit context propagation is planned for a future release. This means that the RMI/IIOP technology is not yet ready for production use, at least not the one available for free from Sun and IBM.

Conclusion
Increasingly, enterprise-scale applications make use of distributed-object technologies to gain competitive advantages in the rapidly evolving markets. More and more, these applications need support for rapid development, scalability, and interoperability. Using standards-based distributed object communication protocols introduces new possibilities to Java developers.

RMI over IIOP, which is the result of a cooperation between the Java and CORBA camps, retains RMI's ease-of-use while being coupled with IIOP interoperability and scalability.

Enterprise application developers who prefer to use Java are now free from the infrastructure issues of whether to use RMI or CORBA, and can begin to concentrate on application logic. In addition, enterprises gain the flexibility to deploy their applications with whatever technology they prefer—either RMI, CORBA, or both (implementing the application only once)!

URLs
Sun's free download of the RMI/IIOP product
http://java.sun.com/products/rmi-iiop/index.html

OMG's Java-to-IDL specification in PDF format
ftp://ftp.omg.org/pub/docs/ptc/99-03-09.pdf

OMG's Objects-by-Value specification in PDF format
ftp://ftp.omg.org/pub/docs/orbos/98-01-18.pdf

Sun's EJB-to-CORBA mapping download
http://java.sun.com/products/ejb/index.html

J2EE
http://java.sun.com/j2ee/index.html