A lot of people are following the buzz about OSGi now and are excited about all the things it can do for you. A great world of new opportunities. Now, after the first draft of OSGi 4.2 it very much looks like we’re getting even more as an official OSGi standard (with RFC 124). The formally called Spring Dynamic Modules (in short SpringDM) is going to be OSGi-efied. Today, I want to take a short peak into what this can actually mean and how it could affect the software/ component reuse in your software stack even today.
First things first, when I talk to people about OSGi the most common complain is nothing OSGi specific at all. Basically it is the problem of every API out there. If you implement against an open or proprietary API you’re bound to it to some extend. Ok, this is besides the issue of being to complex. When done right, which includes using all the versioning features OSGi offers it is unfortunately kinda true. We’re still lacking the right tooling support here. Anyway, let’s stick to the first one first (I’ll cover the tooling problem in a later post). Speaking of proprietary, it is true you have to add custom headers to your jar files, but this alone doesn’t hurt you. You can still just use the jar as – yeah well – a simple jar in your web container or any other Java application without any problems at all. This was simple, but there is more of course – the OSGi doesn’t only specify manifest headers. There is also an API you use and program against. Activators for instance can be used to do something like setting up or shutting down your bundle and opening or closing connection pools to databases, registering services signaling that you’re bundle is there and ready to get its work done. Assuming you are not using any of the compendium APIs the imposed layer is rather small and can be encapsulated in a single package per bundle and more often just one single class.
However, as soon as you start using those few classes they become part of your jar and thus you’re bound to them. So, we’re still stuck right? Well, not really. First of all, every OSGi expert (and probably any other sane software engineer) will tell you not to intermingle your domain logic with middleware APIs of any kind. As already mentioned, with OSGi, you can usually keep this layer pretty thin. With Spring DM we can make it now even thinner and separate domain concerns from the container entirely. So, how can we achieve this. Of course, Spring is not doing any magic, although it does a pretty good job. All it does is actually providing an IoC framework, which declaratively wires beans together. Plain simple speaking, that’s about it. You could also use other IoC frameworks like Google Guice or pico container if like, but the integration in OSGi with Spring is pretty unique. The big question remaining is how we can best separate these two concerns.
To start with, you design your domain logic in a bean driven way. By that you not only achieve a well testable domain code, you also remove hard wired dependencies not relevant for your core needs – a very common practice in Domain Driven Design, to throw in some buzz words Package all that code in one or more bundles depending on your needs. What you got is the code base you can reuse in any environment. Now, we need the glue code to actually make it work in OSGi – the package with the few OSGi specific classes. Those you now have to put into a different bundle or fragment (more on this later). By this separation you no longer deliver container specific code, if you don’t need to. Even more, depending on your deployment scenario, you can change and adjust the configuration to your specific needs, all separated in different bundles/fragments. Removing configurations from your domain bundles has the advantage of independent versioning of you actual code and configuration. The domain code, if used f.i. in a Software Product Line is now no longer related to the configuration of your products based on this code and can be versioned independently – enabling you to see what really changes in your application.
This approach is shown in figure 1. You have two applications using the same library with different configurations. You can fix bugs or add features in the library without touching the configurations and vice versa. Interesting now is the difference between fragments and bundles. When should I use what? The advantage of a bundle is that it is the way OSGi intends to deploy code. You can use Activators and define your dependencies. The fragment in contrast was actually intended to only carry optional data like i18n information and alike. The advantage however is that the fragment and its host are sharing the same class loader(, which is also the biggest disadvantage and should be considered really carefully!). This distinction basically sets when to use what. When ever the configuration is loaded by the library and can’t be injected by another bundle, you need to have access to the bundles class path in order to provide the required resource. But wait a minute, you can’t use Activators in fragments. How could we now do the initialization? Here Spring DM comes in. You can just provide a Spring configuration in your fragment and as soon as the fragment is attached, Spring will recognize it and just initializes your beans defined in the descriptor and you have your Activator again. You even have access to the BundleContext if required. However, this approach is only intended for code that otherwise wouldn’t work or can’t be changed for some reasons. The best way to do it is for sure using bundles for that kinda thing.
The main point, I was trying to make here is that with the help of Spring and the up coming manifestation in OSGi R4.2 (if accepted), we have even more opportunities to build reusable and coherent artifacts, perfect suitable for software product lines. However, all the presented possibilities also impose potential for misuse and you should be careful by choosing your way. In many cases the simplest way on first sight eventually becomes a dead end, so be careful and farsighted when making your decisions.