In order for the code change to be effective, you have to get hold of a class-
loader that can load the resources you need it to. If you can identify a class with visi-
bility of the resources, then the classloader of the owning bundle is a good bet.
Bundles don't directly expose their classloader, but a call like ClassThatCanSee-
Resources.class.getClassLoader() will return a suitable classloader. If you have
a bundle but no class, you can write a facade classloader that delegates to the
bundle.loadClass() and bundle.loadResource() methods. As long as the bundle
contains some classes, you can instead use bundle.getEntries() to introspect
the bundle contents and find an arbitrary class name, and then use bundle
.loadClass().getClassLoader() to get the classloader. Both of these methods are
fragile and require caution.
The biggest problem with setting the thread context ClassLoader is that you can't
always be sure it will stay set. When you call out to third-party code, it's entirely possi-
ble that the first thing it does is to change, or unset, the thread context ClassLoader .
If it does, then you're a little stuck! All we can suggest is that if you're having thread
context ClassLoader issues, then this is something to try.
If setting the thread context ClassLoader is too invasive for your taste, you don't
have the source, aren't allowed to change the source by its license, or it doesn't work,
then all isn't lost. Another, somewhat specialized, manifest header can come to the
rescue. Given that this is the case, you may wonder why we haven't been extolling its
virtues throughout this chapter. The answer is simple: this header comes with a price.
DynamicImport-Package—a saving grace?
We've spent a lot of time throughout this topic discussing the use of package imports
to achieve modularity. By correctly describing your dependencies, you gain a powerful
understanding of your application and a lot of flexibility. There has been one consis-
tent message, which is that until all of your dependencies are available, your bundle
can't be used. This statement is weakened somewhat when using the optional direc-
tive, which allows your bundle to start in the absence of some packages. Importantly,
the optional directive is an all-or-nothing deal: either your package will be wired
when your bundle resolves, or it never will (unless the bundle is reresolved).
DynamicImport-Package operates like an optional import in that it won't stop your
bundle from resolving. If that was all DynamicImport-Package did it would be useless,
but there's an important difference. Whereas an optional import is either wired or not
wired , you can think of DynamicImport-Package as imports that aren't wired yet .
Dynamic package imports indicate to the OSG i framework that it should attempt to
wire the package when the bundle first attempts to load something from it. If the wir-
ing fails, then so does the attempt to load the resource. Critically, when a dynamic
import has been successfully wired, it's wired for good. At this point, a dynamic import
is no different from a normal one.
Another key difference between dynamic imports and normal imports is that
dynamic imports can be defined using wildcards, as follows. This allows a bundle to
Search WWH ::