views:

59

answers:

1

I'm trying to understand what guarantees are provided for service events.

The OSGi spec says that ServiceEvents are synchronous, I've taken this to imply that a ServiceListener will not receive a serviceChanged() call with an UNREGISTERING ServiceEvent until the serviceChanged() call with a REGISTERED ServiceEvent has completed. Is this correct?

I've also had a look at the source for ServiceTracker. It seems to try to cope with the situation where those two serviceChanged() calls overlap. Is this possible?

Are there any similar guarantees on calls to a ServiceTrackerCustomizer?

+1  A: 

This is a very tricky issue. When a service is registered in OSGi, the event is handled and all interesting parties are notified (service listeners, service trackers and declarative service runtime). Each interested party has a chance to handle the event. Handling the event can include registering or unregistering additional services. Due to the synchronous behavior of ServiceEvent notification, these events are then dispatched to the interested parties. In a long dependency chain you end up with a tree of notification, where you go to register a single service and it causes a whole bunch of new guys to get registered. I know this because it can make performance tuning OSGi startup a very challenging exercise, since your simple register service call got charged for the service activation of an unknown number of services.

To specifically answer your question, its not a multi-threaded concern with the events, its a re-entrant one. That is the guy processing your register event could get back around to you with another event notification before the full tree gets processed. This is one of the reasons that they strongly recommend that you never register or unregister services while holding locks, or else you can deadlock the event dispatcher thread. Another good way to stay safe is to have a bundle dependency tree, not a graph. The circular dependencies between bundles, even if the classes compile can cause real problems.

I hope this helps. If you want to read more on this sort of thing, there is a new book coming out on OSGi and Equinox. Its available on rough cuts now and should be available in print very soon. http://my.safaribooksonline.com/9780321561510

James Branigan
To avoid these event storms during startup and to keep a bit of order you can use startlevels.
akr
If service A is registered then each interested ServiceListener would get a serviceChanged() call with a REGISTERED event for that service. Is it possible to get a re-entrant serviceChanged() call with an UNREGISTERING event for that *same service A* whilst the REGISTERED event is being processed?I can't see that being possible as you need a ServiceRegistration to unregister the service and that isn't available until after registration completes, but...
Chris Greenaway