OSGi 4.2: Extender Pattern and BundleTracker

Today a updated my dynamic OSGi demo (see screenshot below),  in particular: the extender bundle. The extender pattern is a frequently used pattern in the OSGi world. The idea is to extend the semantics of bundles by adding custom manifest headers and react, if bundles with these headers come and go dynamically. Prominent examples for using the extender pattern are service component models like OSGi Declarative Services (DS) or Spring Dynamic Modules (Spring DM). In my demo I wanted to create a simple extender that tracks bundles with the custom manifest header “Action-Contribution” and provide a class that should be registered as a service. Here an example for such a custom manifest header (you find it in the manifest of bundle com.siemens.ct.pm.ui.actions.vcard in the demo):

Action-Contribution: com.siemens.ct.pm.ui.actions.vcard.Actions

Before OSGi 4.2 I used Heiko Seeberger’s custom bundle tracker to deal with all workflow and threading issues. But since OSGi 4.2 comes with a convenient BundleTracker now, it is no longer necessary to implement all the plumbing. Here is the complete source code of my little extender:

public class ExtenderBundleTracker extends BundleTracker {

  private final Logger logger = LoggerFactory
      .getLogger(ExtenderBundleTracker.class);

  public ExtenderBundleTracker(BundleContext context) {
    super(context, Bundle.ACTIVE, null);
  }

  @Override
  public Object addingBundle(Bundle bundle, BundleEvent event) {
    String className = (String) bundle.getHeaders().get(
        "Action-Contribution");
    if (className != null) {
      Class<?> clazz;
      try {
        clazz = bundle.loadClass(className);
        try {
          bundle.getBundleContext()
              .registerService(
                  "com.siemens.ct.pm.application.service.IActionContribution",
                  clazz.newInstance(), null);
          logger.info("Extender Action Contribution Service registered for: "
              + clazz.getName());

        } catch (InstantiationException e) {
          logger.error("Could not instantiate " + className, e);
        } catch (IllegalAccessException e) {
          logger.error("Illegal access during instatiation of class "
              + className, e);
        }
      } catch (ClassNotFoundException e) {
        logger.error("Could not find class " + className, e);
      }
    }
    return bundle;
  }
}

You might wonder, why I did not overload

public void removedBundle(Bundle bundle, BundleEvent event, Object object) {}

to unregister the services. Since I used the context of the active bundle that comes in to register the service, this service is automatically unregisterd when the bundle goes away.

Have Fun

Kai
Follow me on Twitter

Leave a Reply

I accept the Privacy Policy