I'm trying to develop a web application that is going to be launched from a HTTP OSGi service, this application needs to use other OSGi service (db4o OSGi), for what I need a reference to a BundleContext
. I have tried two different approaches to get the OSGi context in the web application:
BundleContext
of the Activator
in a static field of a class that the web service can import and use.FrameworkUtil.getBundle(this.getClass()).getBundleContext()
(being this
an instance of MainPage
, a class of the web application).I think that first option is completely wrong, but anyway I'm having problems with the class loaders in both options. In the second one it raises a LinkageError
:
java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/felix/framework/ModuleImpl$ModuleClassLoader) previously initiated loading for a different type with name "com/db4o/ObjectContainer"
Also tried with Equinox and I have a similar error:
java.lang.LinkageError: loader constraint violation: loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) previously initiated loading for a different type with name "com/db4o/ObjectContainer"
The code that provokes the exception is:
ServiceReference reference = context.getServiceReference(Db4oService.class.getName());
Db4oService service = (Db4oService)context.getService(reference);
database = service.openFile("foo.db");
The exception is raised in the last line, database
class is ObjectContainer
, if I change the type of this variable to Object
the exception is not raised, but it's not useful as an Object
:)
Update: I have tried to use other services instead of db4o and they worked as expected. Maybe db4o OSGi bundle does something strange when loading its own classes, or maybe I'm not using it correctly. It also works if I use it from a non-web bundle.
Why not passing the BundleContext in the constructor of the servlet class? That class can safely store the context since the service is stopped when the bundle is stopped (and the BundleContext becomes invalid).
I recommend to avoid using classloaders in OSGi at all, since a) the OSGi framework does a lot of classloader magic in order to separate the bundles from each others, and b) you might run in a lot of problems when OSGi and Java 2 security is enabled. This will most probably reduce the reusability of your bundle.