So what are these Service Hooks? Service hooks complement the OSGi service programming model. The current model is based on the following primitives:
- Register a service (Publish)
- Find services (Find)
- Get a service (Bind)
- Listen for service events
During the write up of the specification for the Listener Hook a huge discussion erupted about ordering. Should the events of the adding/removing Service Listeners be ordered or not? There are two sides to this debate. Ordering is much easier for the hook implementer but it turns out that this is quite difficult for the Framework because these events are originating deep down in the bowls of the service registry. The occurrence of the out of order delivery is also very rare, though the chance is finite. After long discussions we found the solution in an extra method on the event object that indicated the state of the event object. This allows the hook implementer to easily find out that a specific delivery is out of order inside a synchronized block and ignore the event. The most scary part was that we also discovered that the same out of order case was possible with service events. Something none of us had ever realized.
The second use case for the hooks was proxying. With proxying, you want to hide the original service and provide an alternative. However, in current OSGi you cannot hide a service for another bundle. Meet the Event and Find Hooks! The Event Hook is a service that receives a service event before it is delivered to the bundles. As a bonus, it can remove bundles from the delivery list, effectively hiding events from that bundle. Its counterpart is the Find Hook that gets a chance to look at, and reduce, the results of the getServiceReference and getServiceReferences methods. This hook can remove Service Reference objects from the result, also effectively hiding the service from the caller.
One of the issues we found was that these hooks need to be implemented very carefully because, depending on when they begin, they can partially hide events from a bundle, creating the wrong image for that bundle. For example, if a bundle already has a service before you hide future events, it is easy to hide the unregister event for that bundle. Fortunately, we found out that the service tracker could handle most of these partial events, but if you hide an unregister event for a service, the service tracker could hold on to that service forever.
Clearly, these hook services are not for the faint of heart. They are very close to the framework and require to be very well-behaved. That said, they definitely look like they will enable new software patterns for more symmetric service programming. It is likely that utilities like the Service Tracker, or extensions to the OSGi programming models, are created on top of these hooks.
Peter Kriens
Hi Peter, is there somewhere an example publicly available that shows the EventHook used for proxying? Thanks.
ReplyDeleteWe will publish a draft soon of the spec, which will contain examples.
ReplyDeletePeter Kriens
Hi peter, can you post the link where i can get an example as how these hooks are used.
DeleteI got half of it figured out myself. :-)
ReplyDeleteBut what I don't understand though, is how to handle previously bound services. I assume an EventHook/FindHook implementation is not supposed to reregister the original service to force consumers to reget the service? And startup ordering with the EventHook/FindHook be started early won't be the answer too?
Thanks
You raise an interesting question that has been heavily debated. The only solution is to stop the bundles to make sure they do not keep holding on to a proxied service. Obviously, use of start level can make sure that you do are not stopping important bundles.
ReplyDeletePeter Kriens