views:

119

answers:

2

How can I add packages to a bundle's import from within code? I need it since I use libraries which rely on reflection and require other packages and I don't want to need to manually add those packages to MANIFEST.MF for each bundle I develop

+1  A: 

You cannot. Import-Packages are evaluated in the Resolution phase. (Phases are Installed -> Resolved -> Active ).

Your code is executed when the bundle is Active, therefore too late to add Import-Packages.

You can do 2 things:

  • Import-Package the packages you're going to use
  • Use the Dynamic-ImportPackage property to specify packages whose resolution can be deferred to execution time
Filippo Diotalevi
Dynamic-ImportPackage use is discouraged as it's little better than the flat classpath problem that OSGi is trying to fix.
hbunny
A: 

In addition to Filippo's solution, you can try to invert the dependency. F.i. instead of calling and inspecting the other bundles, you can let the bundles do that. Another way would be using a bundle tracker and obtaining the ClassLoader of the Bundle tracked. With this class loader you can act "as the bundle", so you don't need the Import-Package clause anymore.

When I started using OSGi, this was one of the first requirements I came up. Over time, I realized that in almost all cases, there is a cleaner and more consistent solution. So, think about it, if you really need this dependency. Is there no way to invert or abstract it to create a generic solution?

If nothing helps (as a last resort), you can also create (in Memory) a fragment with your core bundle as host, providing the required imports. The BundleContext offers you a method to load a bundle from a stream. You then have to update and call refreshpackages(via PackageAdmin service) on your host bundle in order to get the updated ClassLoader (implies a restart of your bundle). However, at the end, you'll have access to all your packages.

As a side note, I would not recommend to manipulate your host bundle by tweaking the import statement and then update... This renders your bundle indeterministic and won't work with signed bundles. Also, this is against everything one expects from OSGi (imagine a growing bundle over time... you need to shrink the imports at some point as well!!!)

Cheers, Mirko

Mirko Jahn
Some of the 3rd party libraries I use use my bundle's class loader to find their own classes. This works well in a WAR environment, not OSGi. What I end up with is needing to add those packages to my bundle. As I develop more and more bundles, this becomes tedious.
IttayD
Ok, so it is something like:bundle(3rdP) -> bundle(me) -> bundle(3rdP)So it is something like logging. 3rdP is some bundle offering HelloWorld and a specific LogFormatter, where "me" provides the logging API. HelloWorld calls the Logging API, which in return needs the formatter to print the log output.There are several ways to solve this:- providing a parameter for the required class loader (in "me")- offering a lookup service with ext. contributers- a ClassTracker(trackers all bundles and checks where to find a specific class to load - tough one to implement,versioning is an issue here)
Mirko Jahn