Jini technology has become the hot topic for anyone interested in connecting a wide range of information devices to a network. When you plug any Jini technology-enabled device into a network, its services and resources are immediately available. Part of the reason is Jini technology's distributed event mechanisms. This article discusses methods of handling distributed events.
Jini technology provides simple mechanisms that enable devices to plug together to form an impromptu communitya community put together without any planning, installation, or human intervention. Each device provides services that other devices in the community may use. These devices provide their own interfaces, which ensures reliability and compatibility.
The Java programming language is the key to making Jini technology work. Devices in a network employing Jini technology are tied together using Java Remote Method Invocation (RMI). By using the Java programming language, a Jini connection architecture is secure. The discovery and join protocols, as well as the lookup service, depend on the ability to move Java objects, including their code, between Java 1 virtual machines (JVM).
Jini technology not only defines a set of protocols for discovery, join, and lookup, but also a leasing and transaction mechanism to provide resilience in a dynamic networked environment. The underlying technology and services architecture is powerful enough to build a fully distributed system on a network of workstations. And the Jini connection infrastructure is small enough that a community of devices enabled by Jini connection software can be built out of the simplest devices.
Events are the mechanism used for asynchronous communication in Jini systems, and as such are crucial to the effective use of the technology. It is both interesting and valuable to consider the nature of the distributed event mechanism, since such an investigation will reveal much of interest about both Jini technology and the appropriate use of RMI.
Perhaps the most useful approach is to consider why the existing delegation event model is not used directly and then examine the way in which these shortcomings are addressed.
There are several reasons why conventional events are not used:
The pre-existing listener interfaces currently defined (
ActionListener and similar) do not throw
RemoteException from their handler methods. This is because Java technology prohibits overriding or implementing a method such that the new method throws exceptions not declared for the original method.
The Event classes currently defined (
ActionEvent and similar) contain references to the source of the event and a significant amount of additional data that might be needed when processing the event. In some cases, the event source object is non-serializable, which would prevent the use of the whole Event object as an argument to a remote method call. In other cases, the volume of data that would be serialized when the event is passed into an RMI call would seriously degrade performance.
The normal delegation model assumes that delivery of events is synchronous, reliable, ordered, and quick. In a single Java virtual machine, this is generally true. Although it is possible to break this assumption if you write handler methods that take long periods of time to execute. (You should not do this!). By contrast, however, in a distributed environment, these features cannot be guaranteed. Messages might be duplicated, corrupted, reordered, or lost, and if TCP or other reliable mechanism is not used for the underlying transport, then these errors might be propagated to the user program. Similarly, delivery of event messages in a distributed environment can take a significant amount of time. None of these issues can be handled easily by the existing event handlers using the data carried by their events.
In the existing event model, registration of a listener wishing to receive events is controlled only by explicit calls, such as
removeWindowEventListener. This is inappropriate in a distributed environment, because temporary failure of the listener must not cause deregistration of the event. If event delivery failures are permitted, it then becomes difficult to recognize the permanent failure condition.
This is a remote interface, indicating that RMI will be used to call the
notify(RemoteEvent) method that the interface defines. Note that although it is possible for particular events to be defined as using their own specific listener interfaces, it is usual to adopt the standard listener for all events. This can mean that multiple event causes are handled in the same listener. The next paragraph discusses how this situation can be efficiently addressed.
The second and third problems, those of the potentially huge size of serialized event objects in the pre-existing events and the unreliable network scenario, have been handled by the elegant design of the
net.jini.core.event.RemoteEvent object has been defined with only four fields, one of which is optional. The first field is a handle on the source of the event. Generally this is a remote reference, and consequently, does not grow larger as the object to which it refers grows. The next two fields are primitive types (in fact, long values) which clearly occupy a small and constant size in the serialized form.
In fact, there is only one element in the
RemoteEvent object that might grow to unbounded size, and that is called the "handback" object. The handback object is a serialized object that the caller provides to the event source. This field may be left null, allowing the programmer to keep close control of the size of the serialized form of the event object. A later paragraph describes the significance of the handback object.
The second field is an identifier for the event. You have seen that it is common for multiple event causes to be handled in the same listener method. The
eventID field gives the handler method a convenient mechanism for determining the reason the event has been delivered.
The third field is a sequence number. This is used to give some indication of whether events have been delivered in the correct order and whether any have been missed or duplicated. In general, as events are issued, the sequence number they carry should be incremented monotonically (that is, counting 3, 4, 5, and so forth). Sometimes, if a server fails and recovers, it might not be possible to guarantee that the order is perfectly maintained. The minimum requirement is that an event is never issued with a sequence number less than the one last used. But, where possible, event-source implementations attempt to make more guarantees. The specification describes these various guarantee levels and their significance.
The fourth field is the handback, or registration, object. It is passed to both the event registration and back to the listener in the form of a
java.rmi.MarshalledObject. Because the handback object is just thatan objectit carries with it both state and behavior and can be used in a variety of ways. For example, it is possible to design an event filter that runs on a powerful system and uses code in the handback object to determine if the particular event should be forwarded to the "real" listener or not. Such an approach is valuable if the "real" listener runs with a low power CPU that cannot handle the rate of events or if it is far away over the network and excess traffic would cause a problem. The handback object, in this scheme, typically carries the remote reference of the real listener. Of course, this is just one example. Since the handback object carries both state and behavior, there are a great many ways that it can be used.
It is useful to note that, in a distributed environment, another benefit accrues from using a single event class rather than defining new classes for each type of event that might occur. In such a system, there is no need to load a new class definition over the network when the first event of a new type is delivered.
The final problem, how to abandon event registration when a listener fails, is handled using leasing. Leasing is one of the other core parts of the programming model of Jini technology. Briefly, a lease is a mechanism that provides API-level control over distributed garbage collection. In this context, providing a lease for the event registration provides, in a standard framework, a means of applying a timeout to that registration. If the lease holder (usually the event listener) keeps renewing the lease at suitable intervals, then the event source will maintain the registration. On the other hand, if the lease is allowed to time out or is cancelled explicitly by the lease holder, then the event source will recognize that a problem has occurred and will de-register the event listener automatically.
These are just a few considerations for Jini technology developers today. Over time, the literature on this topic and many others will grow into a substantial resource for Jini developers. Good luck, and thank you for your early interest.
A new technical training seminar from Sun will provide you with the background needed to use Jini technology in real-world applications. Visit SunEd's registration page for more information.
Simon Roberts, senior course developer, joined Sun Educational Services in the UK four years ago and since then has been working with the Java programming language. He has taught and written training courses, co-authored two books, and leads the technical team responsible for the Sun Certified Programmer for the Java Platform and Sun Certified Developer for the Java Platform certification exams. Perviously, Simon spent twelve years as a software engineer, trainer, and course developer, concentrating on real-time control systems.
Jon Byous is a freelance copywriter for high-tech markets, specializing in Java technology and the Internet.