I have two OSGi bundles A and B. Both are created with the API/implementation model. Both the bundles are activated through Blueprint mechanism. Both the API bundles export the interfaces whereas the implementation bundles don't export anything. Only A has dependency on B.
My issue is, I want to pass a resource file name (xml file) that resides in bundle A to Bundle B (after I get hold of B using the BundleContext.getServiceReferences() method) and then load the resource in Bundle B and process it. How can I achieve the same and is it even doable?
I read the following post and Neil Bartlett's answer suggest it should work.
Access resources in another osgi bundle?
However, when I read about getEntry, findEntries, getEntrypath methods, they don't talk about other bundles (or I misunderstood it). They talk only about fragments.
My question is, can I achieve what I am looking for using any of the above three methods? If so, can you please point to some other thread that has the answers or some sample code?
If this is not possible, can I use fragment bundles(containing only resources)? Again Bundle B is more like a provider where it can take any resource file and process it and satisfy clients requests (Bundle A). So even if I want to use bundle fragment approach, I need B to load the fragment bundle (only on needed basis) specified by clients (say they give the fragment bundle symbolic name). Please provide suggestions or other posts related to similar issues or any samples.
The easiest way to access a resource in a bundle is to use the classLoader of the bundle. In bundle A you get service MyService and do:
InputStream is = this.getClass().getResourceAsStream("myresource.xml");
MyService service.doSomething(is);
or if you prefer a URL:
URL url = this.getClass().getResource("myresource.xml");
MyService service.doSomething(url);
This works as we already resolve the resource before making the call. If you want to give the service just a relative path then you additionally need to give it the classLoader to get the resource from.
ClassLoader bundleALoader = this.getClass().getClassLoader();
MyService service.doSomething(bundleALoader, "myresource.xml");
Keep in mind though that this.getResource() will lookup the resource relatively to the package of "this" while classLoder.getResource() will lookup from the top of the name space.
Btw. These concepts also work fine outside of OSGi. The difference is only that in OSGi you have to make sure to use the classLoader that has visibility of a resource while outside there is often only one classLoader that sees all resources.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With