The recent issuance of an RFP for "Unreliable Multicast" in CORBA got me thinking about the many network semantics available in a combined CORBA/Java environment. There are at least five already, not counting Unreliable Multicast: Java RMI invocations; CORBA synchronous invocations; CORBA asynchronous and messaging-mode invocations; one-way notifications using the CORBA event and notification services; and the Java Messaging Service (JMS). In this column I'll review the basic characteristics of these services side by side. I'm not planning to rate them as "better" or "worse" on any scale - they're more different than better or worse, and you should choose among them based on the requirements of a particular application. The discussion will be confined to invocation semantics. While there are a lot of interesting contrasts between object activation semantics, I'll save that topic for a separate column.
Java RMI Invocations
Java RMI extends your client applications' reach, allowing them to invoke a subset of your Java objects remotely over the network. Only objects that extend java.rmi.Remote (either directly or indirectly) may be invoked via RMI, but local and remote invocations take the same form. In addition, methods must include either java.rmi.RemoteException or one of its superclasses, such as java.io.IOException. Remember, remote invocations can fail in more ways than local invocations, so it's critical to catch both system and application-specific exceptions when you return from a call.
In a Java RMI invocation there is one sender and one receiver, and the sender selects the receiver. The invocation is synchronous: the client blocks the invocation call, at least on the calling thread, until the response comes back from the remote object (or some error condition times out). The network transport is based on socket connections, with a fallback to HTTP's POST command that can penetrate through firewalls under some circumstances. There's only one quality of service (QoS), the default; you can't specify priority or time-out values for an invocation.
If you set your RMI compiler to all defaults, your RMI objects are available only from Java clients. However, if you set your flags for RMI/IDL, the compiler will generate CORBA IIOP network interfaces for your object, which will have a CORBA object reference. It'll also output the IDL corresponding to your Java object, allowing it to be invoked by CORBA clients (which may include CORBA objects acting as clients for part of their function) in the various supported programming languages.
Synchronous CORBA Invocations
This is what you get with current (2.3 and earlier) implementations of CORBA if you restrict yourself to the static invocation interface - that is, compiled IDL invoking via the client stubs. If you code to the dynamic invocation interface (DII), an interpreted version of every IDL interface that all ORBs are required to support, you have a deferred synchronous option. I won't devote space to it here because the new CORBA asynchronous method invocation provides a better alternative for most programming situations.
All CORBA objects are accessible either locally or remotely from any CORBA application that can reach them over the network, so in this respect the CORBA and Java RMI invocations are the same. There are at least two differences:
- Certain CORBA invocations - in particular, ones with a void return value and no out or inout parameters - may be declared ONEWAY in their IDL. For these, control returns to the calling client right away, while the ORB makes a "best effort" attempt to invoke the remote object.
- CORBA is usable from many programming languages, with standard mappings now defined for Java, C, C++, Smalltalk, COBOL, Ada, Lisp, Python and IDLscript, and nonstandardized but nevertheless useful mappings available for Objective C, Eiffel and other languages. Interfaces are written in OMG IDL rather than in a programming language; this unifies the multilanguage environment but means you can't code strictly in a single language as you can with Java RMI. At the very least you have to learn OMG IDL. I may be biased, but I think IDL is a very elegant and transparent way of defining interfaces, and compilers automatically generate client and server-side mappings for your programming language.
The mandatory protocol IIOP guarantees interoperability, while a flexible architecture allows a network to support multiple protocols. For CORBA 2.2 and prior versions there's no client-accessible API for protocol selection - or, in fact, for any network characteristic. Instead, you indicate your desired or preferred protocol in a configuration file or command-line argument at client and server start-up. As with Java, there's only one quality of service at this level, but this changes in CORBA 3.
CORBA 3 Invocation Options
The CORBA Messaging Specification, a part of CORBA 3, adds capabilities in two main areas: asynchronous method invocation and quality-of-service control, including a provision for CORBA routers that changes the network into a reliable transport. This is a very elegantly architected specification with many capabilities, so the treatment here may end up more like a list of features than a description.
The specification defines two models: a programming model and a communications model.
The programming model (Figure 1) affects only client-side interfaces. It first divides invocation space into synchronous and asynchronous. If you choose the former, you can still pick between normal invocation and the ONEWAY form mentioned earlier. If you choose the latter, you pick between callback and polling result return. Each has a different invocation API, but all are generated from your original CORBA 2-format IDL file. To make a callback invocation, program and instantiate a callback object and insert its object reference as the first argument in your asynchronous call, which immediately returns control to your client. When the invocation completes, your callback object is called with the results. When you make a polling-mode invocation, you receive a CORBA valuetype as the return. You poll the valuetype to find out if your results are back; when it tells you they are, you invoke additional operations on it to retrieve your results.
The communications model defines CORBA routers. Each router is basically an ORB that accepts CORBA invocations, stores them and forwards them onward. Information about router locations near the server is contained in the object reference of the target; client ORBs may also be configured to know the location of routers near them. Routers may have persistent storage, enabling reliable network transport of CORBA requests and replies. (Network transmission becomes transactional, the way the best message-oriented middleware works.)
The specification goes further to define an extensive set of QoS parameters and levels, including time-outs for invocation, return or round-trip; priority levels; ordering (temporal, priority or deadline); and routing (none, forward or store_and_forward). Even though QoS is defined in the messaging specification along with asynchronous invocation semantics, its settings apply (where this make sense) to synchronous as well as asynchronous invocations.
By selecting various combinations of the programming model, communications model and QoS settings, you can vary your invocation semantics across a wide spectrum. At the simplest level you can specify basic synchronous or asynchronous invocation; at the most elaborate level you can make CORBA invocations across a network transport as robust and reliable as message-oriented middleware (MOM). Another setting allows time-independent invocations, allowing you to stage CORBA invocations to a router on your laptop while offline and having them automatically upload to the network and execute on the server the next time you connect up. (In fact, the time-independent protocol supports disconnected operation at both client and server ends!)
Real-time CORBA defines additional network QoS control. I won't give details here since space is short and real time is a specialized software area, but I will point out that it defines priority-banded connections, nonmultiplexed connections between a single client and server, and even client- and object-negotiated protocol selection. If you're writing a distributed real-time application, check this out.
CORBA Event Service
Java RMI and CORBA invocations invoke application-specific methods on objects written specifically for that object's interfaces in a one-to-one semantic where the invoker selects the target. Now let's turn to distributed event and eventlike services that typically invoke general, service-defined interfaces (perhaps carrying an application-specific payload stuffed into a generic type such as an any) and allow multicast or multicastlike semantics in which event suppliers and consumers subscribe to an intervening channel and may not be aware of exactly who each other is. The biggest difference between event and messaging services on the one hand and invocations on the other is that invocations use an object-oriented-type system to narrow the available operations on an object and the parameters in each operation, while event and messaging services do not. While this leaves messaging inherently more flexible, it makes invocation the more reliable choice. In large-scale systems I like to use invocation wherever I can, but move to messaging when I have to.
The CORBA Event Service, in its most widely used form, provides channels to which event suppliers and consumers connect. Push and pull semantics are supported at both supplier and consumer ends of the channel. (At the supplier end a push supplier calls a channel object while a pull supplier provides a callback object that's polled periodically by the channel for events. At the consumer end a push consumer provides a callback object to which the channel sends events as soon as they arrive, while a pull consumer polls the channel object periodically to see if any events have arrived.) Because event delivery interfaces are defined in OMG IDL, this is a distributed service intended to serve distributed (perhaps widely distributed) applications; you probably wouldn't want to use typical implementations as the basis for your desktop GUI. Event payload is an IDL any, unless you define an application-specific Typed Event, which then requires a specialized version of the service. QoS is specifically not defined, even though many service items might benefit - how timely events are delivered to push consumers, length of queue and length of time events are held on queue for pull consumers, and so forth. For this, OMG members later defined the Notification Service, which we'll look at next.
CORBA Notification Service
Defined by the Telecommunications Domain Task Force, the CORBA Notification Service adds structured events, typing and filtering, and QoS control to the Event Service, which it inherits in its entirety. (Note: This inheritance means only that Notification Service implementations support the entire Event Service interface set, not that they inherit a previous implementation of the Event Service. More likely, Notification Service implementations will provide Event Service functionality using code in their own implementation.)
The service defines a structured event that supports definition and application of standard filters using a constraint language. Filtering can substantially lessen the load of events on a network or a client of the service. Channels and channel maintenance are also defined. A set of discovery interfaces allows suppliers to temporarily stop supplying, or consumers to stop polling, channels that have no consumers or suppliers. QoS settings are also provided for delivery reliability, priority, various time-outs and other aspects of event delivery.
Since its definition a few years ago, the Notification Service has proved popular. Implementations are available on the software market, and its interfaces have been inherited and used in a number of subsequent OMG specifications, including the CORBA Component Model.
Java Messaging Service
The final service we'll review is a kind of hybrid. A number of third-party vendors market messaging services that provide reliable network message exchange around a central dispatcher to which all clients connect. Referred to either as Enterprise messaging systems or message-oriented middleware, these products vary significantly in the number and type of services they build on a common peer-to-peer messaging foundation. The (JMS) defines a standard API that these vendors can layer on top of their services, allowing them to service the Java runtime environment in a way that is more or less interchangeable, depending on how much the services of one vary from those of another.
Messaging-based applications may be composed of any number of clients (of the messaging service, that is) who interact by exchanging messages. Although messages aren't invocations, JMS clients (and CORBA objects) may be programmed to take certain actions when they receive certain messages, and (according to the JMS 1.0.2 specification) a future version of EJB will include a bean that's automatically invoked by a JMS message.
Semantics vary, with some messaging services supporting point-to-point semantics, while others provide multicastlike anonymous multipoint delivery using a queuing algorithm. JMS supports both, but not interchangeably. The JMS specification points out that you won't be able to port code from one type of service to the other without substantial changes. Finally, remember that JMS works only in a Java environment.
Before I compare the various invocation modes and services, I want to give a few more details about the OMG specification effort currently underway to define unreliable multicast invocation semantics. Unreliable doesn't mean that the multicast service sometimes shows up late for work and occasionally on Monday doesn't show up at all. It signifies that the invocation semantics are "best effort," which means that message delivery isn't guaranteed, and message loss won't be detected by the transport infrastructure. (Packet loss and reordering on the other hand may be detected and corrected.) Intended primarily as a more efficient transport for the event and notification services, its underlying transport will be IP multicast rather than the connection-oriented TCP, and the IOR (Interoperable Object Reference) will specify a multicast group rather than a specific CORBA object as its target. The service also asks for definitions of object groups and methods to maintain group membership in order to support the actual multicast invocations. This will enable an event or notification service to scale to a far larger installation than currently, where each transmission of an event to a consumer is a separate CORBA invocation. Although this may not be a factor for a small number of consumers and small payloads, many installations have large numbers of consumers (I'm thinking primarily of telecommunications and other service networks here) or large payloads, such as graphics images.
In this survey we've seen that distributed applications in Java and CORBA are rapidly becoming quite capable citizens of our new networked world and that a wide variety of options are available for both invocation and notification semantics. Both have synchronous invocations, and both take advantage of reliable network transport, although CORBA does this for invocations while Java does it for messaging. CORBA has an edge in distributed event and notification delivery and works in a multilanguage environment. Of course, Java programmers can contribute objects to the CORBA environment by using RMI/IDL, which allows you to generate IDL interfaces automatically for Java objects that speak IIOP over the network while programming in pure Java. There's no corresponding magic on the client side, however, so you'll have to code your Java clients to the IDL Java language mapping to make invocations of CORBA objects on your network.
Jon Siegel, director of
technology transfer for the Object Management Group, has extensive
experience in distributed computing, OO software development and
He holds a Ph.D. from Boston University.
Jon can be contacted at: [email protected]