Module Lifecycle

This section describes the dynamic aspects of bundles. It starts with the explanation of the lifecycle states. After that it is described how to write code to install, start, stop, and uninstall bundles.

Bundle Lifecycle

Bundles follow a dedicated lifecycle. The following diagram illustrates a bundle’s states and their transitions:

bundle lifecycle

State Description


This is the initial state of a bundle after the installation into the runtime


This state is reached during the first start of the bundle. It means that the bundle layer is loaded successfully


The bundle is in the start process


The bundle is successfully started and ready to operate


The bundle is shutting down


The bundle is fully uninstalled from the runtime and can not be restarted again

Reacting on the Start/Stop of a bundle

One way to perform logic after a bundle is started, and until a bundle is stopped, is to a add a BundleActivator to the bundle. A BundleActivator is informed by the JS OSGi runtime about the start and stop of the bundle in which it is declared. The BundleActivator can use a BundleContext to interact with the JS OSGi runtime.

A BundleActivator is added to a bundle by declaring the following in the manifest.json file:

BundleActivator in manifest.json
  "activator" : "AClassName"

A base template of a BundleActivator file looks like this:

BundleActivator Template
export default class{
      // do something
      // clean up

Since version 2.0.1, a BundleActivator can return a Promise in the start method. The JS OSGi runtime waits until the Promise is resolved before setting the state of the bundle to ACTIVE.

BundleActivator returning a Deferred
import Promise from "apprt-core/Promise";
export default class{
     return new Promise((resolve)=>{

The main class for interacting with the JS OSGi runtime is the BundleContext, which provides all methods to manipulate bundle states, register for framework events or use the service layer (see next section).

Listening to Bundle Events

Following bundle and framework events are fired by the OSGi runtime. These are also transported via the EventService, so the topics are listed, too.

Type Topic Description



Fired when a bundle is installed.



Fired when a bundle was started.



Fired when a bundle was stopped.



Fired when a bundle is uninstalled.



Fired when a bundle enters the resolve phase.



Fired when all classes (JavaScript sources) have been resolved.



Fired during the uninstallation of a bundle.



Fired at the beginning of a bundle start.



Fired at the beginning of a bundle stop.



Fired after the framework and all preinstalled bundles are started.



Fired when an error occurs within the framework.



Fired during startup of the framework.



Fired if the framework considers a state as warning and not as error. One situatution where it is fired is if a bundle has defined an optional dependency to another bundle and this bundle is not installed.



Fired when the framework was stopped

The BundleContext can be used to listen to bundle events using the addBundleListener method.

Listening for bundle events
import BundleEvent from "apprt/BundleEvent";
export default class {
      this._bundleEventListenerHandle = bundleContext.addBundleListener(this._onBundleEvent,this);

      this._bundleEventListenerHandle = null;

      let types = BundleEvent.types;
      if (types.STARTED === evt.getType()){
          let bundle = evt.getBundle();

The same approach can be used to register to framework events, by applying the addFrameworkListener method.

Listening for framework events
import FrameworkEvent from "apprt/launch/FrameworkEvent";
export default class {
      this._frameworkEventListenerHandle = bundleContext.addFrameworkListener(this._onFrameworkEvent,this);
      this._frameworkEventListenerHandle = null;

      let types = FrameworkEvent.types;
      if (types.STARTED === evt.getType()){


Access manifest properties

If a BundleActivator needs to access manifest properties, it can use the getProperty method of the BundleContext.

export default class {
      //NOTE: getProperty first looks in the manifest of the bundle but
      // if the key is not defined, it looks in the manifest of the system bundle, too!
      let vendor = bundleContext.getProperty("vendor");

As an alternative it can obtain the bundle object from the BundleContext and use the getHeaders. This method ignores system bundle properties and only returns values specified in the bundle.

export default class{
      let bundle = bundleContext.getBundle();
      let manifest = bundle.getHeaders();
      let vendor = manifest.get("vendor");

      // for some properties exist methods in the apprt/Bundle class
      // the state as integer
      let state = bundle.getState();
      // the state as string
      let stateName = bundle.getStateTitle();
      // a unique number of the bundle (internal number identifier, not stable between framework starts)
      let id = bundle.getBundleId();
      // value of "Bundle-SymbolicName"
      let symName = bundle.getSymbolicName();
      // apprt/Version instance of the bundle
      let version = bundle.getVersion();
      // value of "Bundle-Namespace"
      let ns = bundle.getNamespace();

Retrieve Internationalization (i18n) values

If a BundleActivator needs to access i18n values, it can use the bundle object.

export default class{
      let bundle = bundleContext.getBundle();
      // gets a ct/I18N object
      let i18n = bundle.getI18n();
      // gets value of key 'i18nkey' from the nls/bundle.js files
      let i18nvalue = i18n.get().i18nkey;

Search for bundles

The BundleContext also provides methods to search for bundles installed in the JS OSGi runtime using the getBundles method.

export default class {
      // returns array of all bundles
      let allbundles = bundleContext.getBundles();
      // search bundles with symbolic name "test"
      let bundles = bundleContext.getBundles("(name=test)");
      // expect one test bundle
      let testBundle = bundles[0];

getBundles accepts a filter string that can define complex filter expressions. This expression is used to filter bundles based on their manifest properties.

Filter expressions are specified by the RFC-1960 and known as LDAP filter syntax. It is adopted by the OSGi specification and used in different places to express search queries for bundles or services.

Here are some examples of possible filter expressions, which should help to understand the syntax.

Sample Description


Property name must have the value test (case sensitive)


Property name must have a value (must exist).


Property keywords must have the value wizard. keywords is of type array. This means that one value of the array must match the condition.


Property name must start with test

(startLevel <= 10)

Property startLevel must be less or equal to 10

(startLevel >= 10)

Property startLevel must be greater or equal to 10

(! (startLevel = 10))

Property startLevel must not be equal to 10, This is the Not Operator

(& (startLevel < 10) (startLevel > 8))

Property startLevel must be lower 10 and greater 8. This is the And Operator

(| (startLevel < 10) (startLevel > 10))

Property startLevel lower 10 or greater 10. This is the Or Operator


Property name must be equal to test (case insensitive), so it matches test, TEST, TesT for example.


Property name must start with test but (case insensitive), so it matches testab, TESTab, TesTaB for example.

Manually trigger the start of a bundle

If a BundleActivator needs to start a bundle manually, it can use the start method of a bundle object.

export default class {
      // seach bundles with symbolic name "test"
      let bundles = bundleContext.getBundles("(name=test)");
      // expect one test bundle
      let testBundle = bundles[0];
      // start the test bundle
        console.debug("test bundle started");

Manually trigger the stop of a bundle

If a BundleActivator needs to stop a bundle, it can use the stop method of a bundle object.

A bundle should not stop itself.

export default class {
      // search bundles with symbolic name "test"
      let bundles = bundleContext.getBundles("(name=test)");
      // expect one test bundle
      let testBundle = bundles[0];
      // stop the test bundle
        console.debug("test bundle stopped");

Install a bundle

If a BundleActivator needs to install new bundles into the system, it can use the installBundle method of the BundleContext. This is a very powerful feature, because it allows lazy adding of features to a running application.

This method expects three parameters and can be used in different ways.

installBundle interface
  location, // URL pointing to the bundle directory
  manifest, // manifest.json object (optional)
  name  // the name of the bundle (optional), overwrites the name provided in the manifest.json

The following example shows the most simple way to install a new bundle:

export default class {
      // install a test bundle
      let promise = bundleContext.installBundle("http://localhost:8080/js/externalBundles/test");
      // The installBundle method, now fetches the manifest.json provided
      // at http://localhost:8080/js/externalBundles/test/manifest.json
      // interprets it and constructs a bundle instance
      promise.then((testBundle) => {
        // after successfull installation start the bundle

Uninstall a bundle

If a BundleActivator needs to uninstall a bundle, it can use the uninstall method of a bundle object.

export default class {
      // search bundles with symbolic name "test"
      let bundles = bundleContext.getBundles("(name=test)");
      // expect one test bundle
      let testBundle = bundles[0];
      // uninstall the test bundle
        console.debug("test bundle uninstalled");