Wednesday, February 18, 2009

OSGi Service Hooks

I made sure not to have any conferences or meetings in February so I could focus on the writing of the specifications. It is now half way through the month and it has been a crazy month, even worse than usual. Though I have not been able to devote nearly 25% of the time to the specifications as I intended, it looks like the Service Hooks specifications are basically finished.

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
The service registry acts as a mediator between the publishing and finding/binding party. Due to RFC 119 Distributed OSGi, we discovered that we were missing primitives in the service registry. One of the key requirements in RFC 119 was to be able to provide services on demand. However, you can only provide services on demand when you know what bundles are waiting for. The beauty of the OSGi service registry is that this information is available through the internal registry of Service Listeners. Service Listeners are registered with a filter that contains the information about their interest. The Listener Hook provides this information. Registering a Listener Hook service will provide the caller with an initial list of all registered Service Listeners and is then kept informed of additions and removals.

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

4 comments:

  1. Hi Peter, is there somewhere an example publicly available that shows the EventHook used for proxying? Thanks.

    ReplyDelete
  2. We will publish a draft soon of the spec, which will contain examples.

    Peter Kriens

    ReplyDelete
  3. I got half of it figured out myself. :-)

    But 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

    ReplyDelete
  4. 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.

    Peter Kriens

    ReplyDelete

Blog Archive