开发者

Prioritizing OSGi service selection within a container when more than one implementation exist

I am playing with OSGi and have a few bundles. Bundle A and B both contain a registered service which implements a single interface. The third bundle C includes code to lookup a service implementing the previously mentioned interface. The A and B bundles have different version numbers, however it appears that C picks up the service from the first started bundle. I have changed the start level to do the right thing, but version is only used to accept rather than order which service is returned.

   A version 1.0 start level 1
   B version 1.1 start level 2
   C requires both bundles, start level 3

In the above example C always gets the service from A even though B has a higher bundle version. However, if I switch the start level, so B starts before A, C sees the B service.

I have searched the OSGi website and there is no clear explaination of whether versioning of a bundle is used to prioritise a service over another. My understanding seems to indicate that start level is supposed to be used to order bundle startup so开发者_运维问答 that dependencies can be satisified correctly. However it appears to be overloaded so that it also prioritises service priority. Given all the above, I guess it makes sense not to use the bundle version in selection because the version number is just a number relative to nothing.

What is the best way to prioritise one service over another, besides start level?


The best way of prioritizing OSGi services to use SERVICE_RANKING service property. This property may be supplied in the properties object passed to the BundleContext.registerService() method.

According to the documentation of the BundleContext.getServiceReference() method:

If multiple such services exist, the service with the highest ranking (as specified in its Constants.SERVICE_RANKING property) is returned.

If there is a tie in ranking, the service with the lowest service ID (as specified in its Constants.SERVICE_ID property); that is, the service that was registered first is returned.


If the service is registered by a third-party library you may not have control over it's ranking or registered properties. Using ServiceTracker gives you more control. For example, you can do something like this :

ServiceTracker tracker = new ServiceTracker (bundleContext, serviceClass ,new ServiceTrackerCustomizer () {

            @Override
            public Object addingService(ServiceReference srvRef) {

                boolean criteria =  // whatever your criteria is for prioritizing
                        if(criteria)
                            return bundleContext.getService(srvRef);
                        else
                            return null;
            }

            @Override
            public void modifiedService(ServiceReference srvRef, Object arg1) {


            }

            @Override
            public void removedService(ServiceReference srvRef, Object arg1) {

            }

        });
tracker.open();
Object service = tracker.getService();


In org.osgi.framework.BundleContext.registerService(String[], Object, Dictionary) you can specify arbitrary properties in the Dictionary. To find a service, you can specify a filter in org.osgi.framework.BundleContext.getServiceReferences(String, String). And if that's not enough, you can check org.osgi.framework.ServiceReference.getProperty(String), for example for a priority value.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜