Anshul Bindlish Anshul Bindlish -4 years ago 54
Java Question

Why the dependent bundles are not notified/refreshed if another bundle providing service is updated Java?

I have 2 OSGI bundles TestCommons that is the service provider bundle and TestMyBundle that consumes that Service.
Now I have used Declarative services in testMyBundle and based on that I have setter and unsetter in the Activator class of TestMyBundle. So, setter method is called whenever TestCommons service is found and unsetter is called if TestCommons service is unregistered from OSGI.

Now I want to update TestCommons bundle programatically, I used update() method of org.osgi.framework.Bundle interface to update an existing bundle.
Now if I update the bundle, setter and unsetter methods of Bundle TestMyBundle is not called and the bundle is not notified. How can I notify the dependent bundle of the update programatically?
One way is refreshing but I am not able to manually refresh the bundles.

Here is the code that I have written

Bundle[] bundle = context.getBundles();
String symbolicName = "TestCommons";
try {
FrameworkWiring frameworkWiring = null;
for (Bundle b : bundle) {
if (b.getSymbolicName().equalsIgnoreCase(symbolicName)) {
b.update(new FileInputStream(new File("/home/temp/TestCommons-0.0.1-SNAPSHOT.jar")));
frameworkWiring = context.getBundle().adapt(FrameworkWiring.class);
break;
}

}
frameworkWiring.refreshBundles(null);
} catch (Exception e) {
System.out.println("Exception occured while starting...");
e.printStackTrace();
}


}

Now, adapt() method is returning me null. So refresh cannot be called. Please update me as what is the issue here and what other approach could be taken to achieve bundle updation.

Any leads would be appreciated. Thanks...

Answer Source

Your TestMyBundle is not updated as the interface package of the service is updated. So you are already on the right track that you need a refresh of your TestMyBundle to pick up the change.

In practice you can often avoid this by using a separate bundle for the api. As long as you do not update the service interface - and it should be rare - you can then simply update the service bundle and your declarative services component in the client will pick up the new service.

Now about refreshing bundles. You are already right that you need FrameworkWiring for this but only the system bundle can be adapted to FrameworkWiring. So this should do the trick:

Bundle systemBundle = context.getBundle(0);
systemBundle.adapt(FrameworkWiring.class).refresh(null);

This will refresh all bundles.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download