OSGi Import Package and Split Package Woes

OSGi Import Package and Split Package Woes

Since OSGi developers gained influence in the Eclipse development and trainings discussion… many words have been said in favour of declaring dependencies via Import-Package instead of Require-Bundle.

The concept of Import-Package is quite appealing. In today’s world, Java itself doesn’t have a concept for modules so we depend on OSGi for modularity. Actual dependencies on the Java side are specified on the class and package level. So it feels more natural to specify what you need via Import-Package instead of where you want something from via Require-Bundle.

As an experienced Eclipse developer dealing with many large projects… I’ve lost some enthusiasm for Import-Package. All those different bundles and their dependencies are difficult enough to grasp for newcomers. Require-Bundle has better tooling support in Eclipse and less complexity in general… so I recommend to use Require-Bundle unless someone needs the improved flexibility of Import-Package.

What’s the reason for my attitude?

Recently I spent some time with a single-sourcing a RAP/RCP project. Having different target platforms for the same bundles is a perfect example where you need the flexibility of Import-Package. Flexibility is good, right? So I went ahead and declared all dependencies as Import-Package.

Now imagine you have declared an Import-Package to the org.eclipse.ui bundle, being sure that org.eclipse.ui is exported in your target.

Everything is fine, right? So far so good in the typical Eclipse RCP case.

However, it’s not so fine if you try it with RAP although you’ll find that bundle org.eclipse.rap.ui.workbench exports the org.eclipse.ui package.

So the situation is:

my.bundle imports org.eclipse.ui
org.eclipse.rap.ui.workbench exports org.eclipse.ui

However, your bundle just won’t be resolved due to a missing Import-Package constraint on org.eclipse.ui.

The diagnostics in Equinox don’t help much either… it just tells you exactly the above imports and exports. I don’t know if there are better tools out there to diagnose issues.

The reason for this behavior is a concept in Java called split packages. It allows the same package to be declared across several bundles… giving each split a special name. So it’s something like a sub-package concept for packages. Although it is discouraged in the OSGi specification… it is used by the Eclipse workbench and other areas where there has been a lot of refactoring and Require-Bundle usage.

The correct import declaration in my.bundle would be

Import-Package: org.eclipse.ui; ui.workbench="split"

Why does it work in the RCP target case?

It wouldn’t if your target platform contains RCP only. However, most RCP applications have the bundle org.eclipse.ui.ide in their target platform which exports another split of the org.eclipse.ui package. OSGi only resolves split packages if at least two exported split packages can be found.

Knowing this… I now can safely use Import-Package for my single-sourced applications. However, I don’t see a way how I possibly could recommend this to students in my training courses or new people to OSGi in general. I’d need to tell them “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.”

I guess my gripe is that split packages make things complicated and we need better tooling to support them.

How are other people handling split packages in the wild?