This usually happens when you use a pre-bundled .jar file that calls "Class.forName(bar.Foo)". Calling Class.forName() isn't a good practice inside of OSGi, because it requires your bundle to be able to perform "wiring" after it has been active and started. But, seriously, you can't change over a decade of programming practices overnight, so folks still do this. Seeing that this would be an issue, the good folks at OSGi created a neat way of fixing it, the bundle fragment! (applause, Woo HOO!)
What a bundle fragment does is add functionality to an existing bundle. In the OSGi reference the purpose is usually listed as providing localization support. However, it is also a very power mechanism for adding and changing the contents of a bundle's MANIFEST.MF file. For those of you unaware of what this file does, it includes a set of directions for the OSGi environment on how to treat a bundle.
In the above example, you would create a fragment adding the foo package to the Import-Package section of the MANIFEST.MF file.
Most bloggers would stop there. I identified an issue and then told you how to fix it. But not me, nope, I want to show you how a real-life example of this using Hibernate and Antlr.
Hibernate uses a parsing service called AST. This, in turn uses Antlr to help with its parsing. Unfortunately, Antlr needs to use a hibernate class called "org.hibernate.hql.ast.HqlToken". And, of course, Antlr does a Class.forName() at runtime to get an instance of it. This kind of makes sense, Antlr wasn't written just for use with Hibernate. As such, it needs to be told at runtime what token it should use for parsing.
To fix this issue, you create a fragment that adds an Import-Package entry for the package HqlToken is in, "org.hibernate.hql.ast". Doing this is pretty simple. First, you create a normal java project. It doesn't matter what tool you use, as long as you have the following basic structure.
Because we're only adding something to the MANIFEST.MF file, the only file in this project that will have anything in it will be the Maven pom.xml. There are a ton of places folks can go to get smart on Maven, so I'm not going to review how the pom.xml file should look other than the maven-bundle-plugin.
In your build section of your pom.xml, add the following
Then, run the following from your console, or compile it with your IDE.
mvn clean install
This will create a bundle fragment ready for use with OSGi. In Karaf, after you deploy your original antlr bundle and the fragment, you can run the following console command to see the new import package directive added to the rest of antlr's import-package section. The bundleId referred to in this code is the bundleId of the original antrl bundle, not the new fragment.
I added the new antlr fragment to my hibernate features.xml document (from a previous blog entry) right after my antlr bundle and then deployed it as part of my Hibernate feature.
Please let me know if that helps!