Java Reference
In-Depth Information
Embedding JARs instead of converting them
The trick of embedding a plain Java library into an existing OSGi bundle, rather than
converting it into its own bundle, works for more than loggers—it can be an effective
workaround for all sorts of troublesome libraries. Because the embedded JAR shares
a classloader with the consuming bundle, almost all class visibility issues vanish. But
this convenience comes at the expense of reduced modularity and increased bloat.
We recommend embedding JARs as an absolute last resort.
An alternative approach, used, for example, by SLF4J , is to package the implementa-
tion bundles as fragments of the API bundle. This neatly solves the implementation vis-
ibility issues. But fragments have a number of idiosyncratic behaviors, and not
everyone likes using them, which is why this approach hasn't been universally adopted.
Repackaging the logging API and implementation is only one of the ways in which
the bundles can be altered to improve your situation. Another option is to try to make
sure that the thread context ClassLoader has the correct view.
CHANGING THE THREAD CONTEXT CLASSLOADER
We've talked about how the thread context ClassLoader is the source of many issues
for Java libraries in an OSG i framework. One of the more obvious things to do, there-
fore, is to set the context classloader to one that can load the resources you need it to.
Setting the thread context ClassLoader is an invasive thing to do. It absolutely
requires that you change your code and recompile; it's also not something that you
would ever normally come across when writing Java code. For those of you who run
with Java 2 Security enabled, you'll also find that changing the thread context Class-
Loader is a privileged operation.
Setting the thread context ClassLoader is as simple as in the following listing, but
it's also something that you must be careful about doing, particularly when it comes to
setting it back afterward.
Listing 12.9
Setting the thread context ClassLoader
Thread current = Thread.currentThread();
ClassLoader original = current.getContextClassLoader();
try {
current.setContextClassLoader(clToUse);
//Make a call out to your library here
} finally {
current.setContextClassLoader(original);
}
Given that setting the thread context ClassLoader is easy to do, it's a good way of
ensuring temporary visibility of classes and resources. But there are some significant
drawbacks. As we mentioned earlier, you have to change your code. This is invasive
and potentially risky. Not all libraries even use the thread context ClassLoader ,
instead assuming the resource will be on their classpath.
Search WWH ::




Custom Search