Back to top

vogella training Training Books

OSGi Modularity - Tutorial

Lars Vogel

Version 4.6

10.02.2013

Revision History
Revision 0.1 03.09.2007 Lars
Vogel
Created
Revision 0.2 - 4.6 25.10.2008 - 10.02.2013 Lars
Vogel
bugfixes and enhancements

OSGi with Eclipse Equinox

This tutorial gives an overview of OSGi and its modularity layer. For this tutorial Eclipse 4.2 (Juno) is used.


Table of Contents

1. OSGi Overview
1.1. What is OSGi
1.2. Implementations
1.3. Eclipse Equinox
2. OSGi Bundles and Dependencies
2.1. OSGi bundles
2.2. Bundle-SymbolicName and Version
2.3. Semantic Versioning with OSGi
2.4. MANIFEST.MF
2.5. Bundle dependencies and public API
2.6. Provisional API and Friends
2.7. Dynamic imports of packages
2.8. OSGi dependency management
2.9. Bundle Lifecycle
3. OSGi console
3.1. OSGi error analysis
3.2. OSGi console
3.3. Required bundles
3.4. Telnet
3.5. Access to the Eclipse OSGi console
4. Installation
4.1. Downloading or upgrading
4.2. Download the Eclipse plug-in package
4.3. Update an Eclipse Java IDE
5. Tutorial: Your first OSGi bundle
5.1. Create a new Bundle
5.2. Coding
5.3. Run
5.4. Export your bundle
6. Running a stand-alone OSGi server
7. Thank you
8. Questions and Discussion
9. Links and Literature
9.1. Source Code
9.2. OSGi Resources
9.3. vogella Resources

1. OSGi Overview

1.1. What is OSGi

OSGi is a specification. The core of the OSGi specification defines a component and service model for Java. The components and services can be dynamically activated, de-activated, updated and de-installed.

A very practical advantage of OSGi is that every bundle must define its exported Java packages and its required dependencies. This way you can effectively control the provided API and the dependencies of your plug-ins.

1.2. Implementations

OSGi has several implementations, for example Equinox, Knopflerfish OSGi or Apache Felix.

1.3. Eclipse Equinox

Eclipse Equinox is the reference implementation of the base OSGi specification.

Eclipse Equinox is the runtime environment on which Eclipse application are based.

In Eclipse the smallest unit of modularization is a plug-in. The terms plug-in and bundle are (almost) interchangeable. An Eclipse plug-in is also an OSGi bundle and vice versa.

Eclipse Equinox extends the concept of bundles with the concept of extension points.

2. OSGi Bundles and Dependencies

2.1. OSGi bundles

The OSGi specification defines the OSGi bundle as the unit of modularization.

A bundle is a cohesive, self-contained unit, which explicitly defines its dependencies to other modules and services. It also explicitly defines its external API.

Technically OSGi bundles are .jar files with additional meta information. This meta information is stored in the META-INF folder in the MANIFEST.MF file.

The MANIFEST.MF file is part of a standard jar specification to which OSGi adds additional metadata. Any non-OSGi runtime will ignore the OSGi metadata. Therefore OSGi bundles can be used without restrictions in non-OSGi Java environments.

2.2. Bundle-SymbolicName and Version

Each bundle has a symbolic name which is defined via the Bundle-SymbolicName property. The name starts by convention with the reverse domain name of the author of the bundle, e.g. if you owned the domain example.com the name of your symbolic name would start with "com.example".

Each bundle has also a version number in the Bundle-Version property.

The Bundle-Version and the Bundle-SymbolicName uniquely identifies a bundle in OSGi.

Both properties are defined in the MANIFEST.MF file.

2.3. Semantic Versioning with OSGi

OSGi recommends to use a <major>.<minor>.<patch> schema for the version number.

  • <patch> is increased if all changes are backwards compatible.

  • <minor> is increased if public API has changed but all changes are backwards compatible.

  • <major> is increased if changes are not backwards compatible.

2.4. MANIFEST.MF

The following is an example of a MANIFEST.MF file.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Popup Plug-in
Bundle-SymbolicName: com.example.myosgi; singleton:=true
Bundle-Version: 1.0.0
Bundle-Activator: com.example.myosgi.Activator
Require-Bundle: org.eclipse.ui,
 org.eclipse.core.runtime
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6 

The following table gives an explanation of the identifiers.

Table 1. OSGi Manifest Identifier

Identifier Description
Bundle-Name Short descriptive text of the bundle.
Bundle-SymbolicName The unique identifier for this bundle.
Bundle-Version Defines the bundle version and must be incremented if a new version of the bundle is published.
Bundle-Activator Optional, defines an Activator. This class will be notified whenever the bundle is started or stopped.
Bundle-RequiredExecutionEnvironment Specify which Java version is required to run the bundle. If this requirement is not fulfilled then the OSGi runtime does not load the bundle.
Bundle-ActivationPolicy Setting this to lazy will tell the OSGi runtime that this plug-in should only be activated if one of its components, i.e. classes and interfaces are used by other bundles. If not set, the OSGi runtime will activate this bundle by default.

2.5. Bundle dependencies and public API

Via the MANIFEST.MF file a bundle can define its dependency to other bundles or packages. OSGi will throw a ClassNotFoundException, if a class from a bundle tries to access a class without a defined dependency to it. The only exception are packages in the java.* namespace from the standard Java virtual machine; these packages are always available.

In the MANIFEST.MF file a bundle also defines its API, i.e. via the exported packages. All packages which are not explicitly exported are not visible to other bundles.

All these restrictions are enforced via a specific OSGi classloader. Each bundle has its own classloader. Access to restricted classes is not possible, also not via reflection.

A bundle can define that it depends on a certain version (or a range) of another bundle, e.g. bundle A can define that it depends on bundle C in version 2.0, while bundle B defines that it depends on version 1.0 of bundle C.

2.6. Provisional API and Friends

Equinox supports that an exported package is declared as provisional via the x-internal flag. The following screenshot shows how to set a package as x-internal in the MANIFEST.MF editor.

Setting the x-internal flag

This results in the following MANIFEST.MF file.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Example
Bundle-SymbolicName: osgi.example
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: osgi.example.Activator
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: org.osgi.framework;version="1.3.0"
Export-Package: osgi.example;x-internal:=true 

Eclipse will show the usage of this API as an error, warning or ignore this, depending on the setting in WindowPreferencesJavaCompilerError.

Settings in Eclipse for warnings for deprecated API usage

You can also release a package only for a specific plug-in via the x-friends directive. This flag is added if you add a plug-in to the Package Visibility section on the Runtime tab of the MANIFEST.MF editor.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Provider
Bundle-SymbolicName: de.vogella.osgi.xinternal.provider
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Export-Package: de.vogella.osgi.xinternal.provider;x-friends:="bundle" 

2.7. Dynamic imports of packages

For legacy reasons OSGi supports also a dynamic import of packages. See http://wiki.osgi.org/wiki/DynamicImport-Package for details.

Warning

You should not use this feature, it is a symptom of a non-modular design.

2.8. OSGi dependency management

OSGi is responsible for the dependency management between the bundles.

OSGi reads the MANIFEST.MF file of a bundle during its installation. It ensures that all dependent bundles are also loaded, if the bundle is activated.

If the dependencies are not met, then the bundle is not loaded.

2.9. Bundle Lifecycle

With the installation of a bundle in the OSGi runtime this bundle is persisted in a local bundle cache. The OSGi runtime then tries to resolve all dependencies of the bundle.

If all required dependencies are resolved the bundle is in the status RESOLVED otherwise it is in the status INSTALLED.

If several bundles exist which would satisfy the dependency, then the bundle with the highest version is used. If the versions are the same, then the bundle with the lowest install ID will be used (the bundle is assigned a unique identifier by the framework when it was installed in the OSGi environment). If the bundle is started, its status is STARTING. Afterwards it gets the ACTIVE status.

3. OSGi console

3.1. OSGi error analysis

3.2. OSGi console

The OSGi console is like an MS-DOS prompt. In this console you can type a command to perform certain OSGi actions. The following is a reference of the most important OSGi commands.

Use for example the command ss to get an overview of all bundles and their status.

Table 2. OSGi commands

Command Description
help Lists the available commands.
ss Lists the installed bundles and their status.
ss vogella Lists bundles and their status that have vogella within their name.
start id Starts the bundle with the id ID
stop id Stops the bundle with the id ID
diag <bundle-id> Diagnoses a particular bundle. It lists all missing dependencies.
install URL Installs a bundle from a URL
uninstall <bundle-id> Uninstalls the bundle with the <bundle-id> ID
bundle <bundle-id> Show information about the bundle with the <bundle-id> ID, including the registered and used services.
headers <bundle-id> Show the MANIFST.MF information for a bundle.
services filter Show all available services and their consumer. Filter is an optional LDAP filter, e.g. to see all services use "services (objectclass=*ManagedService)".


Bundles can be identified via their id which is displayed by the command ss.

3.3. Required bundles

You have to add the following bundles to your runtime configuration to use the OSGi console.

  • org.eclipse.equinox.console

  • org.apache.felix.gogo.command

  • org.apache.felix.gogo.runtime

  • org.apache.felix.gogo.shell

Equinox contains also a simple built-in console which can be activated with the -Dosgi.console.enable.builtin=true parameter.

3.4. Telnet

If you specify the -console parameter in your launch configuration Eclipse will allow you to interact with the OSGi console. An OSGi launch configuration contains this parameter as default. Via -console 5555 you can open a port to which you can telnet. If you telnet to the OSGi console the new console included in Eclipse 4.2 supports tab completion and a history of the commands.

3.5. Access to the Eclipse OSGi console

You can also access the OSGi console of your running Eclipse IDE. In the Console View of your running Eclipse you find a menu entry with the tooltip Open Console. If you select Host OSGi Console, you will have access to your running OSGi instance.

Please note that interfering with your running Eclipse IDE via the OSGi console, may put the Eclipse IDE into a bad state.

4. Installation

4.1. Downloading or upgrading

To get the required Eclipse tooling for plug-in development you have two options. You can download a special version of Eclipse to develop plug-ins or your can upgrade an existing Eclipse Java IDE.

Both approaches require that you have Java already installed.

4.2. Download the Eclipse plug-in package

Browse to the Eclipse download site and download the Eclipse Classic package.

Download Eclipse Plug-in IDE

Extract the downloaded file to your harddisk. Avoid having special characters or spaces in the path to your extract Eclipse.

4.3. Update an Eclipse Java IDE

In case you have downloaded the Eclipse Java IDE (or any other non RCP flavor) distribution you can use the Eclipse update manager to install the plug-ins required for RCP development.

To open the update manager select HelpInstall new Software....

Install General Purpose Tools Eclipse Plug-in Development Environment Eclipse RCP Plug-in Developer Resources from the Eclipse update site for your release. This would be for example http://download.eclipse.org/releases/kepler for the Eclipse 4.3. release. You may have to remove the Group items by category flag to see all available features.

Update dialog showing how the group by flag can be removed

5. Tutorial: Your first OSGi bundle

The following will create a simple OSGi bundle and run it within Eclipse. At the end of this chapter you will also export your bundle to use it later in a stand-alone OSGi server.

5.1. Create a new Bundle

Create a new plug-in project "de.vogella.osgi.firstbundle" via FileNewOther...Plug-in DevelopmentPlug-in Project

5.2. Coding

Create the following thread class.

package de.vogella.osgi.firstbundle.internal;

public class MyThread extends Thread {
  private volatile boolean active = true;

  public void run() {
    while (active) {
      System.out.println("Hello OSGi console");
      try {
        Thread.sleep(5000);
      } catch (Exception e) {
        System.out.println("Thread interrupted " + e.getMessage());
      }
    }
  }

  public void stopThread() {
    active = false;
  }
} 

Change the class Activator.java to the following.

package de.vogella.osgi.firstbundle;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

import de.vogella.osgi.firstbundle.internal.MyThread;

public class Activator implements BundleActivator {
  private MyThread myThread;

  public void start(BundleContext context) throws Exception {
    System.out.println("Starting de.vogella.osgi.firstbundle");
    myThread = new MyThread();
    myThread.start();
  }

  
  public void stop(BundleContext context) throws Exception {
    System.out.println("Stopping de.vogella.osgi.firstbundle");
    myThread.stopThread();
    myThread.join();
  }

} 

5.3. Run

Select your manifest.mf, right-click, select Run AsRun Configuration . Create a OSGi Framework launch configuration. Deselect all bundles except your de.vogella.osgi.firstbundle. Press then "Add Required bundles". This should select the org.eclipse.osgi bundle.

Run this configuration. This should give you the following output. Every 5 second a new message should be written to the console.

Tip

In case you are wondering in which folder OSGi starts you find it in ${workspace_loc}/.metadata/plugins/org.eclipse.pde.core/ <runconfig> . This folder list the installed bundles via the file "dev.properties" and set the Eclipse workspace as reference in the config.ini file via the osgi.bundles=reference\:file\ statement. This way you can update your bundles in the running OSGi environment directly without any deployment.

5.4. Export your bundle

Export your bundle. This will allow you to install it into a OSGi runtime. Select your bundle and choose File -> Export -> Plug-in Development -> "Deployable plug-ins and fragment".

Unflag the option to export the source.

6. Running a stand-alone OSGi server

This chapter will show how to run Equinox as a OSGi stand-alone runtime.

In your Eclipse installation directory identify the file org.eclipse.osgi*.jar. This file should be in the "plugin" folder. Copy this jar file to a new place, e.g. c:\temp\osgi-server. Rename the file to "org.eclipse.osgi.jar".

Start your OSGi server via the following command.

java -jar org.eclipse.osgi.jar -console 

You can use "install URL" to install a bundle from a certain URL. For example to install your bundle from "c:\temp\bundles" use:

install file:c:\temp\bundles\plugins\de.vogella.osgi.firstbundle_1.0.0.jar 

Tip

You properly need to correct the path and the bundle name on your system.

You can start then the bundle with start and the id.

Tip

You can remove all installed bundles with the -clean parameter.

7. Thank you

Please help me to support this article:

Flattr this

8. Questions and Discussion

Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.com Google Group. I have created a short list how to create good questions which might also help you.

9. Links and Literature

9.1. Source Code

Source Code of Examples

9.3. vogella Resources

vogella Training Android and Eclipse Training from the vogella team

Android Tutorial Introduction to Android Programming

GWT Tutorial Program in Java and compile to JavaScript and HTML

Eclipse RCP Tutorial Create native applications in Java

JUnit Tutorial Test your application

Git Tutorial Put everything you have under distributed version control system