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.
Let's look at the first case in more detail.
MyObject.java, shown at the top left of Figure 6, is the RMI Java interface file that was used to define the RMI-IIOP object in Figure 5. When you pass this Java interface file to the
rmic compiler and specify the
rmic automatically generates the corresponding IDL file (
MyObject.idl). Next, using a CORBA 2.3-compliant IDL compiler, you can generate its stub in your language of choice. (We're using C++ for our example, as you can see here.) Then, through the C++ stub, a C++ CORBA client can access the RMI-IIOP object that was created in Figure 5.
Our second case is an RMI-IIOP client using a CORBA object. Using the same IDL file generated above, you can produce a skeleton in a language such as C++, as shown on the right side of Figure 6. Using this C++ skeleton, you can then produce a pure CORBA C++ object. This CORBA object, which originated from a RMI Java interface file, can be accessed by the RMI-IIOP client in Figure 5.
RMI-IIOP and Java IDL
As explained previously, an RMI-IIOP client cannot necessarily access an existing CORBA object. If you do want to use Java to access CORBA objects that have already been written, Java IDL is an alternative to RMI-IIOP. Using Java IDL (a core part of the Java 2 Platform), you can access any CORBA object from Java. Figure 7 shows Sun's recommendation for usage of RMI-IIOP and Java IDL. If you want to use Java to access existing CORBA resources, Java IDL is recommended. If, conversely, you want to export Java RMI resources to CORBA users, you should use RMI-IIOP.
Because RMI-IIOP supports both the JRMP and IIOP protocols, there has been much speculation that RMI (JRMP) will be integrated into RMI-IIOP. However, at this year's JavaOne conference, Sun announced that it would continue supporting all three protocols, i.e., Java IDL, RMI (JRMP), and RMI-IIOP. To existing RMI users, RMI-IIOP, as the marriage of RMI and CORBA, has some of the restrictions inevitable in any marriage; on the other hand, RMI (JRMP) is not limited by any compromises with CORBA, and so enjoys the freedom unique to single life.
Differences in development procedure
To conclude, let's examine an overview of major differences in development procedures between RMI (JRMP) and RMI-IIOP. The points here also represent work items necessary to convert RMI (JRMP) code to RMI-IIOP code. First, because the usual base class of RMI-IIOP servers is
PortableRemoteObject, you must change this import statement accordingly, as well as the derivation of the implementation class of the remote object. Next, because the class used as the naming service has changed to
InitialContext, you must also change this import statement and use an
InitialContext to request naming registration of a remote object. After completing the Java coding, you must generate a tie for IIOP, using the
rmic compiler with the
-iiop option. Next, run the CORBA
CosNaming tnameserv as a name server instead of
rmiregistry. For CORBA clients, you must also generate IDL from the RMI Java interface, using the
rmic compiler with the
To summarize differences in server development:
Implementation class of a remote object
public class MyObjectImpl extends PortableRemoteObject implements MyObject
Name registration of a remote object
Generate a tie for IIOP with
tnameserv.exeas a name server
- Generate IDL with
rmic -idlfor CORBA clients
Next, let's turn to differences in client development. All the changes in the import statement for server development, discussed above, apply here; in addition, you must also create a local object reference from the registered object name. The new class on which you call a
lookup() method is
lookup() method returns a
java.lang.Object, and you must then use the
narrow() method of
PortableRemoteObject to cast its type. You generate stubs for IIOP using the
rmic compiler with the
A summary of differences in client development:
Identify a remote object by name
InitialContext IC = new InitialContext(env);
Object obj = IC.lookup("Robocop");
MyObject myobj = (MyObject)PortableRemoteObject.narrow(obj,MyObject.class);
- Generate a stub for IIOP with
RMI-IIOP combines RMI's ease of use with CORBA's interoperability and mission-critical infrastructure. Its RMI-centric programming model enables interoperability with, and migration from, existing RMI code. The ability to use IIOP and generate IDL allows seamless integration into a CORBA infrastructure. Its close association with EJB and its inclusion (starting with the next release) in the core Java 2 Platform will establish it as a foundation technology for enterprise middleware. By bringing Java and CORBA together as a strong and well-integrated combination, RMI-IIOP enhances the value of both technologies. This protocol offers developers access to the best of both worlds, and makes both worlds better.
Learn more about this topic
- "Introduction to CORBA, Part 1," Mike Olson (LinuxWorld, September 1999) -- a good overview of CORBA basics
- RMI-IIOP was officially released in June 1999 as a free download from Sun's Website
- The Objects By Value CORBA specification, in PDF formatftp://ftp.omg.org/pub/docs/orbos/98-01-18.pdf
- The Java-to-IDL Mapping CORBA specification, in PDF formatftp://ftp.omg.org/pub/docs/ptc/99-03-09.pdf