Humanizing OSGi I: Yet another layer? Really? But why?
I’m the kind of developer that abhors Eclipse and adores IntelliJ. Eclipse gives me the impression – or rather it climbs up a mountain and shouts down at me – that noone is really interested in me getting my job done. Life is hard, so stop whining. Did you think writing code was going to be easy? Gee, wuss much? You realise what people got by with before? Well, do you, punk? Of course, this is subjective.
IntelliJ, by contrast, is near intoxicating at times. It is like a drinking buddy that understands me a little better with each sip. Again, this is my subjective feeling and rest assured the metaphor shall remain unexplored.
Eclipse, on the other hand, runs on OSGi, in the shape and form of its Equinox plug-in engine. I’ve come to value OSGi over the last couple of years, so I’m all for it. I think OSGi contributes something of value. But OSGi, like Eclipse, has an ugly interface – its programmatic API. OSGi is a bit like IBM itself – old and rickety, but solidly built.
The central BundleContext interface has stuff like:
ServiceRegistration registerService(String clazzes, Object service, Dictionary properties)
This has been accurately described as old-skool. A Dictionary? Eep. Fortunately, as programmers we can use it and not have to like it. We wrap stuff, like this:
<T> Registration<T> register(T service, ServiceProperties<T> serviceProperties)
Right? Right? Generics. Higher-level abstractions of central concepts. A new layer between OSGi and your logic! Sure, call it vanity, but I like building abstractions and modelling stuff. Some have emphasized the importance of making forward progress over building beautiful models, but in this case I believe these concerns go hand-in-hand.
A forward-progress-maker, not to say a forward-progress-maker fundamentalist (not that I know of any) would ask: What’s the point of wrapping it? After all, invoking the BundleContext works, you wuss.
The model-builder (and his/her fundamentalist counterpart), who incidentally are speaking from experience, then point out that we are dealing with a very low-level API that is very flexible. It also leads to usage of some less-common types, like Dictionary. The higher-level wrapper may serve you well in heading off some undesirable developments:
You might start to see a lot of methods doing Map/Dictionary conversions. You will see casting of Object references with varying degrees of type checking. In general, people will start to establish various usage patterns around the OSGi API. As I said, OSGi is low-level and flexible, and the Dictionary is just a case in point: When the code base starts to grow, your services will be registered with various properties, all with more or less well-defined semantics. This is your low-level architecture emerging, and you will want a handle on it before it turns into a copy-and-paste-fest.
That vanity-item of a method signature is part of that handle. This handle is the layer where you will express certain rules about how your application is using OSGi. You may have an architecture specification saying this, but it is basically worthless unless there is well-tested code enforcing it. It is also important that this layer simplifies and facilitates OSGi usage for the layers above, since developers by nature don’t take to using something that doesn’t make their life easier.
So about that forward progress: I found that once this layer is established and accepted as a thing of sufficient value, forward progress and maintaining existing code becomes easier. If you don’t have it, be prepared to find similar-looking util methods and Dictionary lookups on string literals scattered about your code base.
Hmm. Once I got this down, it strikes me what trivial advice it is. Don’t, like, duplicate code. However, in the face of OSGi, and with no well-known place to put the common code, you’ll be surprised at what can appear. Condensed advice, then: OSGi is super, but it’s a bit unwieldy code-wise, so don’t be a slacker. Sorry if you expected the world to be on fire by this point.
And service filters. Don’t get me started on service filters. That’s for my next post.