Not sure how long ago I started using OSGi. Perhaps it was 12 months ago or then perhaps 18. And yet I still find it painful using OSGi especially every time I bring in a foreign set of jars into the ecosystem. And yet I continue to be a dogged proponent. Hereâs why.
First let us understand one of the many problems OSGi solves. Let us imagine your java application has exactly three classes. One is the class you wrote called âMy.javaâ bundled in a jar called âmy.jarâ. Another is a class called âUses.javaâ whose api and features are leveraged by âMy.javaâ and is in a jar called âuses.jarâ. Finally there is yet another class âTransitive.javaâ which is leveraged by âUses.javaâ and lies in a jar called âtransitive.jarâ.
Ideally when you run your application you should have all the three jars available in your classpath. Since you did not write âUses.javaâ, how would you know about its transitive dependency on âtransitive.jarâ ? If you are fortunate, the build tool used to create âuses.jarâ would have created a corresponding âuses.pomâ or similar file which would allow your build tool to discover the transitive dependencies and assemble them all together. But what if that wasnât true?
Turns out these situations are far more frequent than one would imagine. When I started using OSGi, I imagined such cases to be rather unlikely. And yet I have found a large number of situations. Sometimes the unrecorded transitive dependencies are in a profusion of xml libraries, sometimes on alternate logging tools, sometimes even on packages from a different jvm like bea and at least in one case even on dalvik.
So how do you know the libraries you are using have all their transitive dependencies recorded (and in any typical java application today there are literally tens of such jars)? Turns out you donât.
The OSGi way :
OSGi requires you to record the metadata for the jar within the jar itself. Thus in the case above, âmy.jarâ would document the fact that it depended upon packages from âuses.jarâ. In turn, the metadata on the âuses.jarâ would record the fact it exports a certain set of packages (which âmy.jarâ uses) and also requires (imports) other packages which incidentally also happens to be exported by âtransitive.jarâ. The OSGi runtime will make sure all the dependencies are appropriately resolved. Thus in this situation if you attempted to run the application without âtransitive.jarâ, OSGi would flag that off as an error since some of the package imports would not get satisified and your application will not start until you add the third jar into the classpath.
The JVM runtime by default is unsafe
Java is often considered safe given its static typing. But that is just half the story. As the example above shows, its runtime is unsafe. And if you are a library author, you are in turn contributing your share by carrying forward that unsafeness into your userâs domain. The compiler makes sure you have compiled the code correctly to the interface of a given type. But the runtime does not guarantee the presence of that type. At a code level even if you think youâve proved your code works to the extent you could, quite frankly the poor runtime makes such a proof quite illusionary. Since you have no guarantee your code will work even if it compiled successfully. And if you want to test such errors, how on earth will you even test such conditions ?
Library Vendors : Please make your jars OSGi compatible
For every hour you save by not making your jars OSGi compatible, you are requiring your ânâ users who are interested in ensuring a stronger safety of their system to spend ânâ hours ie. one each. Believe me, Iâve spent enormous amounts of time doing this as a user. Thats what gives OSGi a bad rap. Thats what makes people say it is complex.
OSGi is really trying to make your application and java runtimes in general safer (There are many other capabilities, but Iâve focused on only one). Do use it when you publish your jars. And do encourage others to do so.