Search code examples
javaosgiapache-felixdeclarative-services

Why is it a bad idea to manually wire OSGi services?


In order to favor certain service implementations over others, I wrote a customizable version of java.util.ServiceLoader (adds priority and enabled/disabled flag to implementations via preference files for non-OSGi code).

The client was pleased and wanted the same customization for OSGi service implementations. The devised solution is based on calling getServiceReferences(Class<S> clazz, String filter) on BundleContext and uses a null filter to retrieve all implementations.

Nevertheless, fiddling around with OSGi on such a low level leaves a bad taste. There's much boilerplate code (e.g. mandatory subtypes of BundleActivator) and the used approach will also hinder an smooth upgrade to declarative services and some point in time.

I also read about the SERVICE_RANKING property, but compared to the preference files from the approach above, it has the drawback that each implementation sets its own ranking property and it's not possible to change the ranking afterwards.


So my question is: What are good arguments against this low-level approach? Why should declarative services be used instead?


Solution

  • At the core OSGi is a dynamic environment. Bundles and services can come and go at every moment (theoretically). So the only way to cope with this environment is to react on changes compared to waiting for something to happen.

    For example a declarative services component will come up once all its mandatory services are present and will vanish if one goes away. A solution based on service loader or similar will actively get the services that are available if such a service is mandatory then you will have to block until it is available. This can easily lead to deadlocks in the application.

    Of course in practice the application is normally not so dynamic. In most cases this only affects the startup of the application. So in many cases the blocking behaviour can work but it will produce an application that is inherently fragile.

    On the other hand if you have the problem that your application needs to run inside and outside of OSGi then DS is problematic as it relies on OSGi to be present. Typical examples are Aapache CXF and Apache Camel. Both do not use DS and instead invented different abstractions for usage in OSGi and both sometimes have problems in OSGi exactly because of this. Still it would be difficult to improve this as they need to work outside of OSGi too.