5.5. Cooperation with Asynchronous Events

BundleEvents and FrameworkEvents are useful for administrative bundles. For example, a management bundle may present a user interface that enumerates all bundles currently installed in the framework. By listening to BundleEvents, it can dynamically update the list—remove an entry when the bundle is uninstalled, add an entry when a new bundle is installed, or change the status when a bundle is activated.

As another example, some diagnostic bundle may listen to FrameworkEvent.ERROR events and may report error conditions raised that way.

Let us demonstrate, in the following example, how bundles can cooperate using BundleEvent, and what to look for when dealing with asynchronously delivered events. Recall the bundle that registers a parameter service factory from “Service Factory” on page 66 in the previous chapter. We explained that the parameter bundle maintains a property file as the persistent storage for each client bundle in its own data area. We also showed that when a client bundle is stopped, its parameters are saved, and when it is restarted its parameters are restored. However, we left one problem unsolved: When a client bundle is uninstalled, the parameter bundle still keeps its property file, which is never used again.

The parameter bundle can use BundleListener to find out that a client bundle is gone, and can then call ParameterStore's clear method to clean up accordingly:

...
public class Activator implements BundleActivator {

   public void start(final BundleContext ctxt) {
      final ParameterStore store = new ParameterStore(ctxt);
      // add a bundle listener listening to
					// uninstallation of client bundles
					ctxt.addBundleListener(new BundleListener() {
					public void bundleChanged(BundleEvent e) {
					// we are only interested in bundle uninstalled event
					if (e.getType() != BundleEvent.UNINSTALLED)
					return;
					store.clear(e.getBundle());
					}
					});
      ParameterServiceFactory factory =
         new ParameterServiceFactory(store);
      ctxt.registerService(
         "com.acme.service.param.ParameterService",
         factory, null);
   }

   public void stop(BundleContext ctxt) {
      // nothing needs to be done
   }
}

We add the bundle listener, which is defined as an anonymous inner class. ParameterStore's clear method does the following: It first obtains the ID of the given bundle. Because we use the bundle ID as the directory name for each client bundle in the parameter bundle's data area, we check whether the bundle ID of the uninstalled bundle appears as the name of one of the directories. If so, one of the client bundles has been uninstalled, and we proceed to remove its parameter files. Otherwise, the uninstalled bundle has never requested ParameterService and thus is of no interest to the cleanup task at hand.

Recall that events other than ServiceEvent are delivered asynchronously, meaning that the framework, which fires the events, does not wait for the event listener methods to finish. Imagine in the previous example that while BundleListener is handling the BundleEvent.UNINSTALLED event by removing the parameter files for the uninstalled bundle, the same bundle is getting installed and activated by the framework again, and in the process is asking ParameterService to recreate those parameter files. Our implementation works fine in this circumstance because the framework generates a unique ID for the reinstalled bundle. However, if instead of using the bundle ID we had used some other naming convention that has no uniqueness guarantee, our bundle event handler would potentially have clashed with the framework operations in this particular scenario.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.204.186