Over the last 2 weeks I had a chance to teach the 2-day dm Server course 3 consecutive times. One of the topics that inevitably generates a lot of interest is the “uses” directive in OSGi, which is neither easy to grasp nor to explain.
My own first encounter with the “uses” directive was in the form of the mysterious “uses conflict” messages when trying to deploy bundles into an OSGi environment. I say mysterious because they mean nothing to the uninitiated and also because they require a fair amount of research. At the end I provide some links for a more complete understanding. In the mean time I’ll offer my own plain word explanation.
The ability to run multiple versions of the same bundle (or jar) in OSGi is well-known. For example I am a bundle and I need Hibernate 3.2.6.ga. You’re a bundle and you need Hibernate 3.5. We can run side by side in OSGi because the OSGi runtime creates separate classloaders for your bundle and for my bundle, which makes it possible to use different versions of Hibernate.
The problems starts if I decide to use packages exported by you. Why is that a problem? If a class exported by you returns a Hibernate type, I may try to use it, in which case I’ll probably run into problems like LinkageError because you’re essentially using a different version of Hibernate.
That’s the problem. The solution involves the OSGi “uses” directive, which lists packages used in an exported package. The OSGi resolver takes that information and works out if problems like the one above are likely to occur. If so it produces the “uses conflict” message well ahead of runtime exceptions such as LinkageError, ClassCastException, and others.
To understand the solution consider the fact that the descibed issue occurs only if I come into “contact” with a Hibernate type passed to me through one of your exported classes. If you use Hibernate internally and never expose it in your exported packages then the issue would never occur.
If you accept the above problem and solution one more thing that leads to questions is how the uses directive is maintanted. Clearly it’s a fair amount of work figuring out everything your exported packages use. That’s a job for tools like bundlor and bnd.
For more details I highly recommend looking at:
- The OSGi specification, which has very readable definitions and examples in sections 3.5.5 (Export Package) and 3.6.4 (Package Constraints).
- This blog by Glyn Normington that explains the basic problem (note the comments section where he suggests that either bundles should use matching versions or that a bundle is refactored not to export any of the types causing the conflict).
- This follow-up blog by Rob Harrop that provides a realistic example involving Spring ORM and two versions of EclipseLink. It also provides a step by step approach to debugging such issues in the OSGi console, which is key to understanding the messages then produced in dm Server. Lastly there is an interesting variation on how this problem can occur based on deployment order.