Version 4.6
Copyright © 2008, 2009, 2010, 2012, 2013 Lars Vogel
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 |
Table of Contents
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.
OSGi has several implementations, for example Equinox, Knopflerfish OSGi or Apache Felix.
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.
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.
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.
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.
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.
|
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.
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.

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 → → → → .

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"
For legacy reasons OSGi supports also a dynamic import of packages. See http://wiki.osgi.org/wiki/DynamicImport-Package for details.
You should not use this feature, it is a symptom of a non-modular design.
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.
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.
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.
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.
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.
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.
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.
Browse to the Eclipse download site and download the Eclipse Classic package.

Extract the downloaded file to your harddisk. Avoid having special characters or spaces in the path to your extract Eclipse.
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 → .
Install → → 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.

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.
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(); } }
Select your manifest.mf, right-click, select
→ . 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.

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
You can start then the bundle with start and the id.

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.
http://www.osgi.org OSGi Homepage
http://www.eclipse.org/equinox Equinox Homepage
http://www.eclipse.org/equinox/documents/quickstart.php Equinox Quickstart guide
http://www.ibm.com/developerworks/opensource/library/os-osgiblueprint/ OSGi Blueprint services
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