A few months ago, we started researching new platforms, frameworks, and tools for the next generation of our flagship product at my day job. OSGi was one of several Java technologies that came up during our initial discussions. I had heard of OSGi in its context as the underlying runtime for the Eclipse IDE plugin architecture, but otherwise I knew very little about it. A quick Google search revealed that it’s been rather ubiquitous in the embedded software world for quite some time now as a way to implement service gateways. More recently, forward-looking developers have also started to consider it as a platform for increased modularity in enterprise web applications. This idea piqued my interest, and I decided to do a little research. While we ultimately chose not to use OSGi for reasons which I’ll outline below, I still had a lot of fun putting together a presentation for my colleagues and building a small prototype. I’m definitely going to keep an eye on progress in the OSGi world over the coming months in the hope that someday it will become a standard in the web world too.
As I started to research OSGi in a little more depth, I quickly realized that I was going to need to purchase a book to learn the basics before I would be able to really get my head around its complexity. I ended up buying a copy of Modular Java by Craig Walls, author of the excellent Spring in Action (I’m about half way through the latest 3rd edition). The first chapter includes a very good introduction to OSGi and its potential for increasing modularity in Java Web applications. After a brief introduction to the many benefits of modularity — improved changeability, comprehensibility, testability, flexibility, etc — the author describes how OSGi takes modularity one step further than the current set of best practices for overcoming the rather weak support for modularity in Java itself.
Programmers have lots of existing options for increasing modularity in their code. Some traditional methods for creating modular Java designs include:
- Organizing packages by function
- Employing design patterns to create functional layers
- Abstracting functionality behind interfaces to promote low coupling
- Using dependency injection frameworks like Spring
- Breaking large applications up into sets of smaller projects
While all of these techniques are helpful, OSGi takes things one step further by enabling the development of well-defined, loosely-coupled modules called bundles which extend modularity to the Java runtime. As opposed to JAR and WAR files which include everything in the same class space at runtime, the OSGi container runs each bundle in its own separate class space. This separation makes it possible for the container to be running more than one version of a particular bundle at the same time, hence dependent bundles can be configured to use the one that best meets their needs. And because all of the mutable design and implementation details of these bundles are abstracted behind stable APIs, applications built using OSGi are ultimately more maintainable, testable, and understandable. OSGi also provides a service registry for bundles to publish and/or consume services, thus enabling an “out-of-the-box” Service Oriented Architecture (SOA) running on a single JVM. By the end of the first chapter, I was definitely hooked and wanted to learn more.
How OSGi Works
The OSGi specification defines a lifecycle for modules, as well as providing a service registry and a whole host of services for various tasks. These modules, or bundles as they’re referred to in the OSGi specification, are simply JARs with some extra OSGi metadata in their META-INF/MANIFEST.MF file. Once a bundle has been installed into an OSGi container, it can be started, stopped, and uninstalled via the framework. The container’s service registry allows bundles to publish and/or consume other services, as well as trigger tasks when a bundle is started or stopped. Additional OSGi services include a logging service, an HTTP service, and a configuration service. There’s also an optional security layer that spans the other layers to ensure that bundles are authenticated (via digital signatures or verification of install location). I’ve created a diagram similar to one in the book to illustrate the multiple layers of an OSGi application below.
OSGI Containers
There are many open source containers available for running OSGi bundles, but the two most popular implementations are Eclipse’s Equinox and Apache’s Felix. Craig Walls recommends Equinox, and after trying both out a little bit, I’d have to say that I agree. Equinox is more fully-featured and the commands just seem a bit more intuitive. Still, the open source licenses are slightly different, so you may want to review them to see if they meet your business needs before settling on a particular implementation.
What Is Spring DM?
Spring Dynamic Modules (now called Gemini Blueprint since being donated to the Eclipse project last year) is a collection of bundles specifically designed to help manage the deployment of OSGi web applications. While the OSGi container can manage the life cycle of WAR files in exactly the same manner as it manages JAR files, the framework itself doesn’t know anything about deploying to a servlet container. Spring DM monitors the service registry for other web bundles, and then deploys them to either Tomcat or Jetty. The core of Spring DM is the “extender,” the bundle that watches for other bundles to be started. If the web bundles that it finds happen to be Spring-enabled, the extender automatically creates a Spring application context for each one found before deploying to the configured servlet container.
Dude, Where’s My Jar?
All of the examples in Modular Java are given in the context of a sample application, a search engine called “Dude, Where’s my Jar?” which allows a programmer to search Maven repositories for matching JAR files based on their class, interface, enum, or annotation name. While I appreciate that the author put some thought into the concept for this program and came up with something a little more useful and interesting than the typical “pet store” app, I have to say that I’ve rarely found myself using it since I started using Sonatype’s excellent Nexus repository manager for Maven. More on that in a future post. Still, this app provides a good starting point for learning more about OSGI, as well as the Apache Lucene and Compass libraries it uses for indexing and searching files. I’ll include some screenshots of this app in action here soon.
Final Analysis
A couple of months ago, I delivered my presentation on OSGi and Spring DM at one of our long range engineering meetings, after which I demoed a prototype of one of our existing applications using an OSGi service layer. While OSGi captured our engineering team’s interest for a time, upon closer inspection we’ve found OSGi to be a bit too complex and unwieldy to use in its current state. The biggest problem is that we still rely on too many non-OSGi-compliant JARs. While it’s fairly easy to “wrap” a JAR to make it work with OSGi, this quickly becomes cumbersome when you’re using dozens of libraries, many of which have their own non-compliant dependencies. This has also been a problem for the Spring Roo project. They started out with the laudable goal of 100% OSGi compatibility, but then decided to back off until the industry push for OSGi-compliant JARs has progressed a little farther.
The second problem we’ve identified with OSGi is that the tooling just isn’t quite there yet compared to other solutions. While the Pax Construct project includes some really nice scaffolding tools (similar to Ruby on Rails and Spring Roo), I wouldn’t yet consider it to be a complete toolset for something as complex as OSGi. Sonatype’s Jason Van Zeil has stated that he thinks it will still be another year or two before the tooling is ready for web application prime time. Bottom line: We’re not going to be using OSGi at my day job for now, but I’m definitely going to keep playing around with it. Hopefully I’ll be able to incorporate it into a side project sometime soon. And if I do, I’ll be sure to post my further adventures here.