Snippets / Stop aQute - Software Consultancy
Search
*

A Bundle That Stops Itself

In certain cases it is necessary for a bundle to stop itself. This should be done with care because the stop method will then return to a bundle that has just be stopped. The issue is more extensively explained in Best Practice with Depressed Bundles.

Purpose

Bundles that want to stop themselves without causing havoc.

Prerequisites

  • osgi interfaces, provides all service interfaces for the OSGi specifications.

Instructions

The demonstration program is quite simple. The activator creates a thread. The thread does some work and at the end of the work it calls the @@safeStop()@ method. This method runs the stop method in another thread. This thread waits until the main thread has finished and then calls stop. This guarantees that the main thread is done and the amount of code executed in the bundle after it is stopped is absolutely minimal.

The source code looks as follows:

 package aQute.stop;
 import org.osgi.framework.*;

 public class DepressedActivator extends Thread implements
    BundleActivator {
  BundleContext context;
  boolean       quit;

  public void start(BundleContext context) throws Exception {
    System.out.println("start {");
    this.context = context;
    start();
    System.out.println("start }");
  }

  public synchronized void stop(BundleContext context)
      throws Exception {
    System.out.println("stop {");
    quit = true;
    interrupt();
    System.out.println("stop }");
  }

  public void run() {
    System.out.println("run {");
    // Do something really interesting
    safeStop();
    System.out.println("run }");
  }

  public synchronized void safeStop() {
    System.out.println("safeStop {");
    if (quit) {
      System.out
          .println(" safeStop } (after early return)");
      return;
    }

    final Thread activator = this;
    new Thread() {
      public void run() {
        System.out
            .println("safeStop.run {");
        try {
          try {
            activator.join(10000);
            System.out
                .println("joined");
          } catch (InterruptedException e) {
            // Ignore this silly exception
          }
          context.getBundle().stop();
        } catch (BundleException e) {
          e.printStackTrace();
        }
        System.out
            .println("safeStop.run }");
      }
    }.start();
    System.out.println("safeStop }");
  }
 }

The code is heavily sprinkled with print statements to follow the actions. What will happen when you run this code?

 start {
 start }

 run {
   safeStop {
   safeStop }
 run }

 safeStop.run {
   joined

   stop {
   stop }

 safeStop.run }

Links

Copyright 2006 aQute SARL, All Rights Reserved