What is RMI over IIOP?
RMI over IIOP (RMI-IIOP hereafter), developed jointly by IBM and Sun, is a new version of RMI (Remote Method Invocation) for IIOP (Internet Inter-ORB Protocol) that combines RMI's easy programming features with CORBA's interoperability. This new version of RMI was officially released in June and made freely available from Sun's Web site (see the Resources section below for information on where you can download it). The Sun reference implementation runs on Windows 9x/NT and Solaris. It is a standard extension that supports both JDK 1.1.6 and the Java 2 Platform.
RMI and CORBA have developed independently as distributed-objects programming models. RMI, a foundation of the EJB and Jini technologies, was introduced as a Java-based, easy-to-use programming model for distributed objects. CORBA (the Common Object Request Broker Architecture), defined by the OMG (Object Management Group), is a well-known distributed-object programming model that supports a number of languages. The IIOP protocol connects CORBA products from different vendors, ensuring interoperability among them. RMI-IIOP is, in a sense, a marriage of RMI and CORBA.
For the purposes of this article, we assume that you are already familiar with the basics of CORBA. If you need further assistance in getting up to speed, there is a helpful link in the Resources section below.
Look at Figure 1 below. The space above the central horizontal line represents the original domain of RMI; the lower region represents the world of CORBA and IIOP. These two separate worlds, having developed independently, have not historically been capable of communicating with each other. For example, RMI's native protocol, JRMP (Java Remote Method Protocol), cannot connect with other protocols.
If the only programming language that you require in a new project is Java, the use of RMI and JRMP -- a combination referred to as RMI (JRMP) for the remainder of this article -- has traditionally been the best choice. Unlike CORBA, which requires use of the rather complicated Interface Definition Language (IDL), RMI (JRMP) offers easy programming for Java lovers. CORBA, on the other hand, allows for distributed-objects programming across different platforms and different programming languages. Developers need distributed-objects programming not only for new projects, but also for utilizing legacy software resources. Of course, legacy software is in most cases programmed in languages other than Java; in such situations, developers need CORBA, not RMI (JRMP).
Thus we have our central dilemma: RMI (JRMP) has the advantage of easy programming, whereas CORBA provides interoperability between multiple programming languages across various platforms. Unfortunately, however, there has not traditionally been a way to use both of these excellent technologies. This is shown by the chart in Figure 2, in which a circle stands for a situation in which a client can call a server, and an X stands for a case in which this is not possible
The best of both worlds
It used to be difficult to choose between RMI (JRMP) and CORBA when starting a new project. If you selected RMI (JRMP), you got easy programming, but lost interoperability across multiple languages. If you selected CORBA, you got interoperability, but faced a more daunting programming task. Both RMI (JRMP) and CORBA users, tired of making this decision, have said with one voice: "Please connect the two."
In Figure 3 below, the top section represents the RMI (JRMP) model, the middle section the RMI-IIOP model, and the bottom section the CORBA model. An arrow represents a situation in which a client can call a server. RMI-IIOP belongs in the IIOP world below the horizontal line. What may look strange are the diagonal arrows that cross the border between the JRMP world and the IIOP world, which implies that an RMI (JRMP) client can call an RMI-IIOP server, and vice versa. It's natural for readers to think these diagonal arrows are wrong -- after all, different protocols can never talk to each other, right? However, these arrows are in fact in the right place. RMI-IIOP supports both JRMP and IIOP protocols.
A server binary (i.e., a class file) created using RMI-IIOP APIs can be exported as either JRMP or IIOP. You don't have to rewrite its Java source code, or recompile it when changing from JRMP to IIOP, or vice versa. You need only change parameters such as Java system properties when running it. Alternatively, you can determine the protocol used by specifying it in the Java source code. The same flexibility applies to RMI-IIOP client code.
There is one more important fact to keep in mind when deciding between the JRMP and IIOP protocols. When you export an RMI-IIOP object on your server, you do not necessarily have to choose between JRMP and IIOP. If you need a single server object to support both JRMP and IIOP clients, you can export your RMI-IIOP object to both JRMP and IIOP simultaneously. In RMI-IIOP terminology, this is called dual export.
The diagonal arrows in Figure 3 are possible because RMI-IIOP APIs support both JRMP and IIOP protocols. This means that, without rewriting the source code of an RMI (JRMP) object, it can be called by a new RMI-IIOP client. Similarly, without rewriting the source code of an RMI (JRMP) client, you can replace an RMI (JRMP) server object with a new RMI-IIOP object that a CORBA client can also call. Thus, RMI-IIOP preserves existing investment in RMI (JRMP) binaries, because RMI-IIOP can communicate with them without any source-code changes or recompilation.
This interoperability with RMI (JRMP) was one of the design principles of RMI-IIOP. The RMI-IIOP designers avoided the temptation to displace CORBA and RMI with a third programming model, since this would have only confused distributed-objects programmers and made migration from RMI (JRMP) all the more difficult.
Interoperability with CORBA
Look at Figure 3 again. The section below the horizontal line is the IIOP world, where an RMI-IIOP client calls a CORBA server, and a CORBA client calls an RMI-IIOP server. By an RMI-IIOP client, we mean a client program that was written by an RMI programmer who knows nothing about CORBA or IDL. Likewise, a CORBA client is a client program that was written by a CORBA programmer ignorant of RMI. Separation of interface from implementation is a well-established technique for allowing programmers to access different resources without needing to know how those resources are implemented; if this technique is followed, users of both RMI-IIOP and CORBA can use the services of the other protocol, if they can get access to its interface. An RMI Java interface file is the interface to RMI-IIOP users, while IDL is the interface to CORBA users; interoperability between RMI-IIOP and CORBA in Figure 3 is achieved by providing each user with his expected interface, while keeping the actual implementation hidden.
The last detail to be explained in Figure 3 is the dotted arrow indicating an RMI-IIOP client calling a CORBA server. Why is only this arrow dotted? An RMI-IIOP client cannot necessarily access all existing CORBA objects. The semantics of CORBA objects defined in IDL are a superset of those of RMI-IIOP objects, which is why an existing CORBA object's IDL cannot always be mapped into an RMI-IIOP Java interface. It is only when a specific CORBA object's semantics happen to correspond with those of RMI-IIOP that an RMI-IIOP client can call a CORBA object. The dotted arrow indicates a connection that is sometimes -- but not always -- possible.
However, the incompatibility here shouldn't be overstated. The restrictions indicated by the dotted arrow apply only when dealing with existing CORBA objects. Suppose you design a brand-new distributed object with an RMI-IIOP Java interface. In this case, you can automatically generate its corresponding IDL with the
rmic tool. From this IDL file, you can implement it as a CORBA object -- in C++, for example. This C++ object is a pure CORBA object that can be called by a CORBA client and can be also called by an RMI-IIOP client without any limitations. To the RMI-IIOP client, this C++ CORBA object appears as a pure RMI-IIOP object because it is defined by an RMI-IIOP Java interface. In short, the difference between a CORBA object and an RMI-IIOP object is only an implementation matter. Likewise, if an object is implemented in RMI-IIOP, the object appears as a CORBA object to a CORBA client because a CORBA client accesses it through its IDL.
Figure 4 below shows the matrix that summarizes the arrows in Figure 3. The dotted circle means the same thing as the dotted arrow in Figure 3. Figure 4 demonstrates that, if you implement your server in RMI-IIOP, you have the broadest choice of clients. Likewise, if you implement your client in RMI-IIOP, you can talk to the largest range of servers, though there are some restrictions in the case of existing CORBA objects, as indicated by the dotted circle.
RMI-IIOP design policy
There were two major prerequisites that shaped the design of the RMI-IIOP protocol: the RMI semantics had to be left as intact as possible, and CORBA needed to be enhanced so that RMI semantics could be implemented using the CORBA infrastructure. This was easier said than done. If a third programming model was introduced, it would only confuse programmers. To produce a happy marriage of RMI and CORBA, it was necessary to reach a compromise between the different backgrounds of these marriage partners -- if both partners rejected any compromise, the marriage would get nowhere. Fortunately, the CORBA community recognized this and accepted certain changes so that RMI-IIOP could become a reality.
The two major changes CORBA accepted were the Objects by Value and the Java-to-IDL Mapping specifications. The former, already available to RMI users in the form of Java object serialization, is a CORBA specification intended to make other languages implement a similar capability. The latter is the mapping used to convert RMI Java interfaces into CORBA IDL definitions, and must not be confused with the IDL-to-Java mapping already defined in CORBA 2.2. (See Resources for links to these two new CORBA specifications.)
OMG has already officially accepted both specifications for CORBA 2.3, but CORBA implementations will have to catch up with this new version before the new marriage of CORBA and RMI described here becomes a widespread reality. For example, an IDL-to-Java compiler that conforms to CORBA 2.3 is available from Sun for use in conjunction with the RMI-IIOP ORB (object request broker), but it is currently an early access version suitable only for exploring the interoperability of CORBA and RMI-IIOP, and not for production use. Furthermore, the IDL-to-Java compiler distributed by Sun for use with the Java IDL ORB in Java 1.2 does not conform to CORBA 2.3, so it cannot be used to test interoperability with RMI-IIOP. This situation will be resolved over the next few months as CORBA vendors introduce new versions of their products that support CORBA 2.3. For example, the next release of the Java 2 Platform, Standard Edition will include both RMI-IIOP and a production-quality IDL-to-Java compiler that supports CORBA 2.3.
Figure 5 below shows the development procedures for both RMI-IIOP servers and clients. You will notice that they are almost the same as those of RMI (JRMP). Just as in RMI (JRMP), a distributed object's definition is its RMI Java interface (
MyObject.java in Figure 5). A difference is the
-iiop parameter of the
rmic compiler. This option is used to make
rmic generate the stubs and tie that support the IIOP protocol. Without this
rmic generates a stub and a skeleton for the JRMP protocol. Although the development procedure for RMI-IIOP is close to that for RMI (JRMP), the runtime environment is different in that communication is made through a CORBA 2.3-compliant ORB, using IIOP for communication between servers and clients.
If you are considering converting RMI (JRMP) code to RMI-IIOP, you should be aware that there are some implementation differences when running over IIOP. Distributed garbage collection is not supported by CORBA, which uses explicit destruction and persistent object references with transparent passivation and activation. The RMI registry is replaced by JNDI with the
CosNaming or LDAP service provider, and RMI activation is replaced by the portable object adapter. Remote object references must be downcast using a programmatic
narrow() method instead of a direct Java language cast. Other RMI semantics, such as object serialization, are fully supported over IIOP.
CORBA interoperability procedure
Figure 6 shows how to achieve interoperability between RMI-IIOP and CORBA. To make our discussion simpler, let's consider two aspects of such interoperability: a CORBA client using an RMI-IIOP object, depicted in the leftmost section of Figure 6, and an RMI-IIOP client using a CORBA object, depicted in the rightmost section. In the center of the figure are those shared processes that allow both forms of interoperability to work.