OSGi allows for dependencies to be determined via Import-Package
, which just wires up a single package (exported from any bundle), and Require-Bundle
Avoid Import-Package. As packages provide many-to-many relationships between bundles, they are prone to dependency cycles that are hard to detect and avoid.
Require-Bundle on the other hand, references a single bundle, making dependency graph protected from cycles by a trivial build-time check. With Require-Bundle it is much easier to build layered architecture with isolated lower level of abstraction.
Import-Package
should be better because, as previously said, you can move a package from one bundle to another without changing existing client's MANIFEST.MF
But...
There is a practical reason to use Require-Bundle
if you are using Eclipse to develop your bundles:
Eclipse don't use packages as units of resolution. It uses bundles. That is, if you use one package of a bundle, Eclipse compiles your bundle without reporting any problem with the use of the rest of packages not imported from that bundle.
You could (you are human) think that everything is OK and upload your bundle for deployment but ... your bundle will break at runtime.
I'm sure about it because this problem has happened (to me!) today.
The good solution would be to change the Eclipse classpath container but... if this is not going to be done... you could decide to avoid this kind of problems requiring bundles, instead of packages, paying the mentioned price (no backward compatible code movement between bundles).
I believe Require-Bundle
is an Eclipse thing (that has now made it in the OSGi spec to accommodate Eclipse). The "pure" OSGi way is to use Import-Package
, as it specifically decouples the package from the bundle that provides it. You should be declaring dependencies on functionality that you need (the Java API provided by a certain version of a certain package) instead of where that functionality is coming from (which should not matter to you). This keeps the composition of bundles more flexible.
JavaScript analogy: This is like detecting whether a web browser supports a certain API versus inferring from what the user-agent string says what kind of browser it is.
Peter Kriens of the OSGi Alliance has more to say about this on the OSGi blog.
Probably the only case where you need to use Require-Bundle
is if you have split packages, that is a package that is spread across multiple bundles. Split packages are of course highly discouraged.
I believe Import-Package gives you looser coupling and should be preferred. I use it when declaring dependencies on packages that I don't own, such as slf4j, and I can swap implementations as I wish. I use Require-Bundle when the dependency is something I have control over, such as my own bundles, because any important change would have gone through myself anyway.
I'm not convinced that using Import-Package is better, because my default expectation when working with a bundle is to work with the associated public API. For that reason, Require-Bundle makes more sense.
Favour Import-Package over Require-Bundle.
Require-Bundle:
Import-Package: