Recently I wanted to use the good old ServiceTracker to get access to OSGi services registered under a specific interface and matching a given filter. I was surprised to discover that there is no constructor for the
ServiceTracker that allows the specification of a class name and a filter.
A quick look into the OSGi specification revealed: the list of the service interfaces is made available by the OSGi framework as the service property objectClass. Using this property, the interface can be part of the filter:
BundleContext bundleContext = ... String filterString = "(objectClass=com.eclipsesource.MyInterface)"; Filter filter = bundleContext.createFilter(filterString); ServiceTracker tracker = new ServiceTracker(bundleContext, filter, null);
Here is a cleaner alternative for specifying the filter string above:
String filterString = "(" + Constants.OBJECTCLASS + "=" + MyInterface.class.getName() + ")";
There is actually a bunch of service properties that are set by the framework or at least have predefined semantics. See the OSGi specification for a complete table of standard service properties defined by the framework, or have a look at the interface org.osgi.framework.Constants for the properties’ keys.
Another interesting side note about the objectClass property is the fact that its value is actually a String array of the interfaces the service is registered for. This even allows you to find matches for several interfaces at once, using only one filter string:
String filterString = "(&(" + Constants.OBJECTCLASS + "=" + MyInterface.class.getName() + ")" + "(" + Constants.OBJECTCLASS + "=" + MyOtherInterface.class.getName() + "))";
The objectClass service property allows you to formulate complex filters for your services that go beyond what the standard OSGi API can offer.