views:

63

answers:

3

Hey guys. We're using OSGi services in an Eclipse RCP application. To track them, we're using the org.osgi.util.tracker.ServiceTracker class. A sample code from the application looks like

mailServiceTracker = new ServiceTracker(context, MailService.class.getName(), null);
mailServiceTracker.open();
MailService service = (MailService) mailServiceTracker.getService();

Now my problem is that the getService() method frequently returns null when I created a new service. The code works very well for services that are existing for a long time in the application, but each time I create a new service, I have to do many things until the service is finally found and tracked. I regularly try for example

  • 'Clean...' in Eclipse
  • 'Refresh' all projects in Eclipse
  • Rebuild the project on the command line

Sometimes those things help, and sometimes they don't. Does anyone have experiences with those trackers and can tell me how to avoid this behavior and how to get the services tracked immediately upon creation?

Thanks

A: 

Not being flippant at all, don't use service trackers. They appear to make your life simple, but there are all sort of issues with them. I'd recommend that you look into using Declarative Services instead. The support for DS in Eclipse has been very good from 3.5 onward.

You might want to check out this book and the associated presentations for more information on why using Service Trackers is a bad idea.

http://equinoxosgi.org/

James Branigan
Could you be a bit more specific what you mean with "there are all sorts of issue with them"? I wouldn't just dismiss them because there are scenarios where they are much easier to use than DS.
akr
In the book I referenced, look at section 6.2.3 "Service Tracker Summary". The book shows an example using Service Trackers, then moves the example to Service Activator Toolkit(from the Eclipse RT project), and then to Declarative Services. The authors do a much better job explaining the problems then is possible in a Stackoverflow question.
James Branigan
+1  A: 

There is nothing wrong with using ServiceTrackers other than the fact that it's a fairly low-level way of tracking services. Whilst I agree that declarative services are a nice mechanism, simply dismissing ServiceTrackers because of "all sorts of issues" sounds like bad advice.

Back to the question.

As soon as a service tracker is created and opened, it gives you access to all services that match the filter condition you specified upon creation. There is no delay there. The only thing I can think about is that somehow your bundles are not correctly resolved, so services that are registered from a bundle A are simply not visible to a bundle B using a ServiceTracker. To check this, first locate the bundle that exports the package containing the service interface, and then make sure both A and B are actually wired to it.

Explaining the update/refresh mechanism in OSGi a bit more:

Whenever you update something in OSGi, it's a two step process.

Let's assume you update a bundle that contains a new version of an exported package. Let's also assume there is some consumer that imports it. As long as you only update the bundle but not explicitly refresh the wiring (of which import links to which export) the consumer will still be wired to the old version of the package. As soon as you do a package refresh (something you can do in OSGi via the PackageAdmin service) your consumer will be resolved again and will be wired to the new version.

The reason this is decoupled is that you might want to do updates of several bundles and not "refresh" after each one but instead defer such a refresh until all of them are updated.

It's quite possible that this is the effect you're seeing. Initially you only do an update, and only after the refresh will the tracker actually see the new version of the service.

Marcel Offermans
Hey Marcel, thanks for the answer. I haven't checked whether the problem only occurs when referencing services across bundles, but the problem always disappears after a while, so I think it's not something related to bundles not being resolved correctly. I takes some refreshing and recompiling, but after a while the trackers seem to work. My question is, what exactly do I have to do to make them work and why don't they work from the beginning?
David Sauter
Maybe you should keep in mind that ST are synchronous. As soon as you call ST.open(), you will receive all the services you are tracking.
akr
David, there is nothing wrong with ServiceTrackers -- they work perfectly fine. If a ServiceTracker does not see a service, it can only be because that service does not exist.I suggest you look closely at the code where you actually create and register the services. Also try using the commands supplied by your OSGi shell to diagnose why the services aren't being registered.
Neil Bartlett
+1  A: 

The problem is that the services you want may not have been created yet (especially in an bundle activator, as some bundles may not yet have started). If you still want to use the service tracker, you will need to provide a ServiceTrackerCustomizer, and keep track (sorry, no pun intended) of the services as they come and go.

Or, you could just switch over to Declarative Services that handle this for you.

Tassos Bassoukos
Ah, interesting...I'll have a look at this `ServiceTrackerCustomizer` class. Thanks for the answer!
David Sauter