Wednesday, March 2, 2011

OSGi's Role

With the increased adoption of OSGi the issue of when to use the OSGi API pops up more and more often. One misconception, popularized with Dependency Injection, is that NO code should touch the OSGi API.

The reason code should not touch a specific API is cohesion. If you write a program to control the brakes of a car you'd likely not want to include code to optimize fuel consumption. Cohesion is about keeping focus in your module; the more concerns get mixed, the less cohesive the module gets. Low cohesion modules are bad because they are more complicated to maintain, which translates to extra cost, and they are less usable in another model because now the module requires both the brake semantics as well as the fuel semantics to be applicable for any new model. The less cohesive, the smaller the chance all the domains match the new usage area for the module.

So it is very true that you do not want to mix OSGi API with your shopping cart code for an ecommerce site, these are different domains. The quest for high cohesion forbids mixing these domains.

However (you knew this was coming), there are many cases where the application infrastructure is the domain. Looking at open source you find that (often too) large swaths of code are not related to some application domain but they are about the infrastructure of the application, or said differently, the plumbing. Application plumbing can be very beneficial; it is all about reducing application domain code. Dynamic class loading, annotation processing, reflection, and many other techniques are all used to reduce the amount of application code with plumbing code. Clever plumbing code is reusable so over several systems the total complexity will be much less.

Application plumbing is exactly the domain of OSGi.

So once you start using class loaders or play with Class.forName realize that you are acting as an application plumber. Whatever you're doing, once your code uses a class loader your no longer in Kansas. If you have to use Class.forName and class loaders you're like a plumber in the medieval ages. You might be a craftsman but the environment gives you very little support so you're largely on your own, devising your own tricks. There might be some common patterns you picked up from your local guild but there are no standards in the Java VM.

Once you realize you're into application plumbing you should realize that you're right at the heart of OSGi's application domain. In all those cases the OSGi API is perfectly suitable to use and gives you much cleaner and reusable solutions than continuing to abuse the Java APIs in this areas that were never intended to be used for application plumbing.

So to conclude that one should never use OSGi APIs is misunderstanding the cohesion issue; once you do application plumbing it is much more advantageous to use the OSGi API than any alternative route. The OSGi gives you a comprehensive framework for application plumbing that is unmatched in the software world.

Peter Kriens

6 comments:

  1. Hi Peter,
    I work as a framework developer (Apache CXF and Apache Camel). The problem is that our domain is not so much the plumbing but we still do it and to some extend have to do it.

    The problem is that CXF and Camel have to work with or without spring and inside or outside osgi. Doe you have an idea what a good strategy is to separate the real framework from the plumbing? I think it is clear that we can´t simply use osgi apis.

    ReplyDelete
  2. Well, not using the OSGi API because you want to run outside OSGi just means you're gone have to reinvent the wheel.

    I actually never understood the argument to not couple to OSGi when you're in its domain: application plumbing.

    Felix is around 400k, which is a minute dependency nowadays. Using non-OSGi code with OSGi code is a breeze with the launching API, and last but not least, you can run OSGi inside OSGi, JEE server, plain class path, in any combination and recursive depth. OSGi is incredibly non-intrusive because we avoided statics like the plague. Stop looking at OSGi as framework you run inside but start seeing it as a part of your application where you can do certain things really easy and powerful.

    So I think the fear for the OSGi is heavily exaggerated. If you use BCEL or ASM , do you create your own abstraction? If you do application plumbing then not using OSGi is pretty dumb imho ...

    ReplyDelete
  3. The problem is that we create frameworks that people use for many different things. As there are many people that do not use OSGi we can not fully concentrate on it. If you are writing an application then it is easier. You simply decide for one plumbing and go with it. In a framework that needs plumbing but wants to fit in the environment of an application it is not that easy.

    ReplyDelete
  4. @Christian: Not sure you understood me. What I am advising is just include a framework in your code. If you're running inside OSGi, use that framework. If you're deployed in a WAR or on the classpath, just start your own Felix ...

    OSGi is not like a big bloated app server ... it is just a (small) dependency that can make your life a lot better.

    ReplyDelete
  5. That sounds interesting as we could remove abstractions or "di framework" classes that are necessary to run in several environments. The problem for us is that for example CXF is only a small part in a bigger application. So your suggestion could work for the inner plumbing of cxf and camel as long as it not visible on the outside. There we have to be flexible to fit into what the application architects have defined as their plumbing.

    ReplyDelete
  6. It will require some redesign but it is oh so nice if you can always rely on OSGi to be there ...

    And it is not that hard to make many of the support libraries work on OSGi as well as on the dreaded classpath.

    ReplyDelete