OSGi has been around for a while, and it has been moving rapidly towards the enterprise java development. There are still some miles to be covered before the mainstream enterprise development will move to OSGi, but the first steps have been made.
I don’t believe any developer will be prepared to package the entire code base as OSGi bundles and deploy it in some OSGi container. The chance of running into class loading problems is too big for that. There is, however, a road in the middle, that will allow you to adopt OSGi in your project in a reasonable, controlled, but truthful way.
Instead of running your entire application in an OSGi container, it is also possible to run the OSGi container inside your application. That way, you can run certain relatively isolated parts in the OSGi container, while the complicated business logic is still loaded with your regular trusted class loader.
It doesn’t take much to start up an OSGi container within your application. In fact, Jettro has already written a blog item on how to start the Felix context. When the context is started, you obtain a BundleContext instance. This instance gives you access to the entire OSGi context. You can use it to find services, register services, register listeners, etc. In fact, your entire application is now registered as the System Bundle (bundle 0), making it one big virtual OSGi bundle. As far as the OSGi container is concerned, your application really is a bundle. The only difference is that you don’t import any packages. That wouldn’t make a lot of sense since all you need should be inside the application. Exporting packages, however, is a must, since most likely your bundles will require some classes inside your application.
Your application will need two components in order for this plugin-infrastructure to work. The first is the collection of extension points, or plugin API. This component contains the classes that your OSGi bundles will use in order to do something with your application. The second component is the bridge, which is responsible for passing your application requests into your OSGi container.
Suppose you have an application that can send messages. This message sending system should detect the type of message and select an appropriate plugin to actually send it. A typical extension point in this case would be an interface called “MessageSender”. The plugins will then have to provide a service for this interface. The bridge component will listen for these services inside the OSGi container and decide which message should be handles by which MessageSender.
Your application should export all packages needed for the extension points to the OSGi container. Do this using the Constants.FRAMEWORK_SYSTEMPACKAGES entry in the Felix configuration. If your bundles should interact directly with classes in your application, make sure to export the packages containing these classes too. Of course, you could decide to offer instances of these classes as services, instead of hard-wiring the Bundles to a specific implementation. Remember, OSGi services help you to achieve loose coupling, since you only rely on a certain interface. OSGi does the binding and wiring of an implementation (either based on certain properties or not) for you.
The services provided by the plugins/bundles may come and go during runtime as bundles are installed and removed, making your application extremely flexible. But of course, your main application will have to make sure it doesn’t rely on services being available all the time. That is why the container bridge should always keep track of the availability of services. The ServiceTracker is provided by the OSGi container for this purpose. However, there are other possibilities, such as the the list of services provided by Spring DM, which is automatically maintained for you by the Spring container.
With these components, the bridge and the plugin API, your application is technically ready for plugins. But, before you rush off with your OSGi implementation, remember that you’ll be needing a way to interact with your OSGi container in order to install and start bundles. Felix has a shell bundle which allows you to interact with your OSGi container from your console. See http://felix.apache.org/site/apache-felix-shell-tui.html for more information about this bundle. You can auto-start your bundle by adding it to the class path of your application, and specifying it in you Felix configuration.
An important note when you’re planning to use Spring DM for your bundles: make sure Spring DM is *not* included as part of your application. The Spring Dynamic Modules Extender bundle heavily relies on the OSGi class loader, meaning that it must run inside an OSGi container to make it work. The rest of the Spring Framework jars may be part of your main application and run outside the OSGi container.
Happy OSGi coding!