59

OSGi allows for dependencies to be determined via Import-Package, which just wires up a single package (exported from any bundle), and Require-Bundle, which wires up to a specific named bundle's exports.

In building a greenfield OSGi application, which approach should I use to represent dependencies? Most of the bundles will be internal, but there will be some dependencies on external (open-source) bundles.

Lii
  • 11,553
  • 8
  • 64
  • 88
AlBlue
  • 23,254
  • 14
  • 71
  • 91
  • 4
    From http://eclipsesource.com/blogs/2009/07/14/why-i-cant-recommend-using-import-package/ : “Look, Require-Bundle is something that has been used in Eclipse for awhile, mostly for legacy reasons. We don’t recommend its use any more. Import-Package is better if you want looser coupling between bundles. However, be aware of the pain split packages can cause.” – Thomas Jung Dec 08 '09 at 09:47

6 Answers6

57

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.

Daniel Hiller
  • 3,415
  • 3
  • 23
  • 33
Thilo
  • 257,207
  • 101
  • 511
  • 656
  • 3
    Both Require-Bundle and Import-Package are defined in the OSGi spec; there's no "pure" variant of the two. – AlBlue Dec 08 '09 at 19:40
  • 2
    @AlBlue: updated my answer to make it more clear that while Require-Bundle is in the spec, it is only made it there for Eclipse compatibility. – Thilo Dec 09 '09 at 00:51
  • 7
    I think Thilo is right. As Peter Kriens mentioned in the article: "Require-Bundle has an intuitive appeal that is hard to deny." But it is unnecessarily tying the bundles together. In Java world I would compare it to IoC vs looking up dependencies directly. One example is depending on `commons-logging` bundle vs depending on `commons-logging` API package. In the latter case you can easily swap the `common-logging` bundle with appropriate SLF4J adapter bundle that also exports the `commons-logging` API package and thus seamlessly creates a bridge from `commons-logging` to SLF4J. – Pavol Juhos Dec 09 '09 at 06:21
  • 2
    +1 because this is a good discussion of this topic. Small addition: require-bundle could be used to express dependencies that are different from just packages, e.g. a Bundle requires a resource in the form of another bundle to be present. – Andreas Kraft Dec 09 '09 at 12:26
  • 3
    Just to make an observation - the 'Require bundle has made it to the OSGi spec to accommodate Eclipse' is factually incorrect. It was added in OSGi 4, but most of Eclipse Import-Package. Eclipse 3.0 switched over to using OSGi in June 2004; OSGi 4 (with Require-Bundle) was released in August 2005. – AlBlue Dec 23 '09 at 10:28
17

Favour Import-Package over Require-Bundle.

Require-Bundle:

  • specifies the explicit bundle (and version) to use. If a requirde bundle needs to be refactored and a package moved elsewhere, then dependents will need changes to their MANIFEST.MF
  • gives you accesss to ALL exports of the bundle, regardless of what they are, and regardless of whether you need them. If the parts you don't need have their own dependencies you will need those to
  • bundles can be re-exported
  • although discouraged, allows the use of split packages, ie: a package that is spread across multiple bundles
  • can be used for non-code dependencies, eg: resources, Help etc.

Import-Package:

  • looser coupling, only the package (and version) is specified and the run-time finds the required bundle
  • Actual implementations can be swaped out
  • Dependent packages can be moved to different bundles by the package owner
  • But requires more metadata to be maintained (i.e: each package name) at lower levels of granularity
wuerg
  • 1,022
  • 12
  • 12
tekumara
  • 8,357
  • 10
  • 57
  • 69
  • For Import-Package, what if you need a particular version of the package but the bundle actually has the version in it? AFAIK, java packages don't have versions. – Raffi Khatchadourian Aug 25 '15 at 14:39
5

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.

omerkudat
  • 9,371
  • 4
  • 33
  • 42
1

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).

Lii
  • 11,553
  • 8
  • 64
  • 88
1

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.

Basilevs
  • 22,440
  • 15
  • 57
  • 102
0

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.

kberg
  • 225
  • 1
  • 8
  • 6
    This statement makes no sense. Your justification is the reason you would use Import Package instead of Require-Bundle. Deal with the public API and do not worry about who provides it. You don't work with the bundle, you work with the API. – Robin Jan 18 '12 at 21:07