Reputation: 115
I'm considering to modify my existing java framework to work with OSGi. I have several components that rely on reflection and work with any type of class (like a bean and persistence service). I'm not very experienced with OSGi yet but as far as I understand an OSGi bundle can only see the classes in packages it explicitly imports. If I build a bundle with the maven-bundle-plugin and specify a wildcard as the import-package it resolves the packages that are referrenced by the code at build time. I would need the code to work with classes in packages not known at build-time.
What I want to achieve is that bundle-A can use the persistence-framework in bundle-B to persist classes belonging to bundle-C. While bundle-B does not know bundle-C at build time.
What manifest entries would I need and how do I set them using the maven-bundle-plugin?
Also since there can be multiple versions of the same class used by different bundles would this even make sense in an OSGi environment? If I understand correctly Bundle-A and Bundle-B might see different vesions of Bundle-C. If Bundle-A now passes an object of a class located in Bundle-C to Bundle-B which then uses reflection on the class, will Bundle-B see the class as it is defined in it's Bundle-C or as it is defined in Bundle-A's Bundle-C. For instance if I have the following classes in Bundle-C:
class Y {
[...]
}
class X {
Y y;
[...]
}
Bundle-C is different for Bundle-A and B. B passes an object of class X to A. If B now discovers the field y and resolves it's class will it resolve Y as it is in it's version of Bundle-C or the version known to A?
In short even if I have a bundle that imports all classes from all bundles would this even be usefull to, for instance, create a service to persist objects into a database?
Upvotes: 0
Views: 294
Reputation: 19626
The whole issue of classloading is only relevant when you load a class. Reflection works in OSGi in the same way as outside OSGi.
So if you have a method in bundle b that takes an Object as a parameter. Then you can call this method from bundle A with an instance of a Class defined in bundle c. Even if bundle b has no import for the package of the object it can still use reflection to work on the object.
If you want load classes by name in a bundle that does not import the package the safe way is to give it the classloader of the bundle that contains the classes.
So for example you can have this method in bundle b:
public Object loadTest(ClassLoader loader, String name) {
return loader.loadClass(name);
}
Now the question is of course how to get the classloader of bundle b in bundle a. The easiest way is to create a class from b using MyClass myObject = new MyClass(). Bundle a can do this as it imports the package. You can then use myObject.getClass().getClassLoader()
to get the classloader of bundle b.
In OSGi the classloader of each object is the classloader of the bundle it is defined in (if you do not do anything weird).
If that is not possible you can get the classloader of a bundle by using
ClassLoader loader = bundle.adapt(BundleWiring.class).getClassLoader();
Upvotes: 1
Reputation: 12085
You have multiple questions in a single article :)
For setting up the JPA in the OSGi environment you may check my blog.
JPA implementation in OSGi environment works another way. It hooks to a bundle listener and if a bundle is started with persistent (@Entity) classes, it will load them.
About the class versions:
Generally - if you want some service bundle to recognize your classes, you can 'inject' it using the bundle fragments. In your case - you have a direct dependency (X depends on Y), therefore any bundle loading the class X will load the class Y (with the specific version).
In the OSGi environment you may use different class versions, but you may not mix them. Practically a bundle depends on a specific class version (declared or first found). In fact - each class is identified by its name and the classloader identification. Therefore forcing a bundle to use the same class from different classloaders (versions) will lead to the 'classloader poisoning' and a lot of difficult-to-trace exceptions.
Have fun
Upvotes: 0