Java Reference
In-Depth Information
added and automatically cleans up any remaining listeners when the bundle stops.
You saw something similar in section 4.2.1 when the framework removed any leftover
service registrations.
The test method is now simple, because you're caching the service instance:
while (Thread.currentThread() == m_logTestThread) {
if (m_logService != null) {
m_logService.log(LogService.LOG_INFO, "ping");
} else {
alternativeLog("LogService has gone");
}
pauseTestThread();
}
This looks much better, doesn't it? You don't have to do as much checking or polling
of the service registry. Instead, you wait for the registry to tell you whenever a Log Ser-
vice appears or disappears. Unfortunately, this code sample has a number of prob-
lems. First, there are some minor issues with the test method; you don't catch runtime
exceptions when using the service; and because of the caching, you don't unget the
service when you're not using it. The cached Log Service could also change between
the non-null test and when you use it.
More importantly, there's a significant error in the listener code, because it doesn't
check that the UNREGISTERING service is the same as the Log Service currently being
used. Imagine that two Log Services (A and B) are available at the same time, where
the test method uses Log Service A. If Log Service B is unregistered, the listener will
clear the cached instance even though Log Service A is still available. Similarly, as new
Log Services are registered, the listener will always choose the newest service regard-
less of whether it has a better service ranking. To make sure you use the highest-
ranked service and to be able to switch to alternative implementations whenever a ser-
vice is removed, you must keep track of the current set of active service references—
not just a single instance.
The bundle activator in listing 4.9 has another subtle error, which you may not
have noticed at first. This error may never show up in practice, depending on how you
start your application. Think back to how listeners work: the event source sends events
to the listener as they occur. What about events that happened in the past? What
about already-published services? In this case, the service listener doesn't receive
events that happened in the dim and distant past and remains oblivious to existing
Log Service implementations.
FIXING THE SERVICE LISTENER
You have two problems to fix: you must keep track of the active set of Log Services and
take into account already-registered Log Services. The first problem requires the use
of a sorted set and relies on the natural ordering of service references, as defined in
the specification of the compareTo() method. You'll also add a helper method to
decide which Log Service to pass to the client, based on the cached set of active ser-
vice references; see the following listing.
Search WWH ::




Custom Search