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

江枫思渺然 提交于 2019-12-04 16:20:28

问题


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?


回答1:


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.




回答2:


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();



回答3:


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.



来源:https://stackoverflow.com/questions/1850974/prioritizing-osgi-service-selection-within-a-container-when-more-than-one-implem

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!