Home Tutorials Training Consulting Products Books Company Donate Contact us

Online training


Quick links


OSGi with Eclipse Equinox. This tutorial gives an overview of OSGi and its modularity layer.

1. Introduction into software modularity with OSGi

1.1. What is software modularity?

An application consists of different parts, these are typically called software components or software modules.

These components interact with each other via an Application Programming Interface (API). The API is defined as a set of classes and methods which can be used from other components. A component also has a set of classes and methods which are considered as internal to the software component.

If a component uses an API from another component, it has a dependency to the other component, i.e., it requires the other component exists and works correctly.

A component which is used by other components should try to keep its API stable. This avoids that a change affects other components. But it should be free to change its internal implementation.

Java 9 provides its own module system to describe software component dependencies. But the Java module system has not yet been adapted by the module system used by Eclipse. The OSGi specification defines its own module system, which is a bit more flexible than the Java module system.

1.2. The OSGi specification and OSGi implementations

OSGi is a set of specifications. Its core specification, defines a component and service model for Java. A practical advantage of OSGi is that every software component can define its API via a set of exported Java packages and that every component can specify its required dependencies.

The components and services can be dynamically installed, activated, de-activated, updated and de-installed.

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

Eclipse Equinox is the reference implementation of the base OSGi specification. It is also the runtime environment on which Eclipse applications are based.

1.3. Plug-in or bundles as software component

The OSGi specification defines a bundle as the smallest unit of modularization, i.e., in OSGi a software component is a bundle. The Eclipse programming model typically calls them plug-in but these terms are interchangeable. A valid plug-in is always a valid bundle and a valid bundle is always a valid plug-in. In this tutorial the usage of plug-in is preferred, to be consistent with the terminology of Eclipse plug-in development.

A plug-in is a cohesive, self-contained unit, which explicitly defines its dependencies to other components and services. It also defines its API via Java packages.

2. OSGi metadata

2.1. The manifest file (MANIFEST.MF)

Technically OSGi plug-ins are .jar files with additional meta information. This meta information is stored in the META-INF/MANIFEST.MF file. This file is called the manifest file. It is part of the standard Java specification and OSGi adds additional metadata to it. According to the Java specification, any Java runtime must ignore unknown metadata. Therefore, OSGi plug-ins can be used without restrictions in other Java environments.

The following listing is an example for a manifest 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,
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6

The following table gives an explanation of the identifiers in the manifest file. For information on the version schema which is typically used in OSGi see Semantic Versioning with OSGi.

Table 1. OSGi identifiers in the manifest file
Identifier Description


Short description of the plug-in.


The unique identifier of the plug-in. If this plug-in is using the extension point functionality of Eclipse, it must be marked as Singleton. You do this by adding the following statement after the Bundle-SymbolicName identifier: ; singleton:=true


Defines the plug-in version and must be incremented if a new version of the plug-in is published.


Defines an optional activator class which implements the BundleActivator interface. An instance of this class is created when the plug-in gets activated. Its start() and stop() methods are called whenever the plug-in is started or stopped. An OSGi activator can be used to configure the plug-in during startup. The execution of an activator increases the startup time of the application, therefore this functionality should be used carefully.

Bundle-RequiredExecutionEnvironment (BREE)

Specify which Java version is required to run the plug-in. If this requirement is not fulfilled, then the OSGi runtime does not load the plug-in.


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 plug-ins. If not set, the Equinox runtime does not activate the plug-in, i.e., services provided by this plug-in are not available.


The Bundle-ClassPath specifies where to load classes from the bundle. The default is '.' which allows classes to be loaded from the root of the bundle. You can also add JAR files to it, these are called nested JAR files.

2.2. Bundle-SymbolicName and Version

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

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

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

2.3. Semantic Versioning with OSGi

OSGi recommends to use a <major>.<minor>.<patch> schema for the version number which is defined via the Bundle-Version field identifier. If you change your plug-in code you increase the version according to the following rule set.

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

For more information on this version scheme see the Eclipse Version Numbering Wiki.

2.4. Specifying plug-in dependencies via the manifest file

A plug-in can define dependencies to other software components via its manifest file. OSGi prevents access to classes without a defined dependency and throws a ClassNotFoundException. The only exception are packages from the Java runtime environment (based on the Bundle-RequiredExecutionEnvironment definition of the plug-in). The JRE packages are always available to a plug-in without an explicitly defined dependency.

If you add a dependency to your manifest file, the Eclipse IDE automatically adds the corresponding JAR file to your project classpath.

You can define dependencies either as plug-in dependencies or package dependencies. If you define a plug-in dependency your plug-in can access all exported packages of this plug-in. If you specify a package dependency you can access this package. Using package dependencies allows you to exchange the plug-in which provides this package at a later point in time. If you require this flexibility prefer the usage of package dependencies.

Dependency management

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

The OSGi runtime ensures that all dependencies are present before it starts a plug-in. OSGi reads the manifest file of a plug-in during its installation. It ensures that all dependent plug-ins are also resolved and, if necessary, activates them before the plug-in starts.

2.5. Life cycle of plug-ins in OSGi

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

If all required dependencies are resolved, the plug-in is in the RESOLVED status otherwise it stays in the INSTALLED status.

In case several plug-ins exist which can satisfy the dependency, the plug-in with the highest valid version is used.

If the versions are the same, the plug-in with the lowest unique identifier (ID) is used. Every plug-in gets this ID assigned by the framework during the installation.

When the plug-in starts, its status is STARTING. After a successful start, it becomes ACTIVE.

This life cycle is depicted in the following graphic.

OSGi life cycle

For legacy reasons OSGi supports a dynamic import of packages. See OSGi Wiki for dynamic imports for details. You should not use this feature, it is a symptom of a non-modular design.

2.6. API definition of a plug-in

In the MANIFEST.MF file a plug-in also defines its API via the Export-Package identifier. This allows you to define internal API, provisional API and API.

Dependency management

All packages which are not explicitly exported are not visible to other plug-ins.

Dependency management

All these restrictions are enforced via a specific OSGi classloader. Each plug-in has its own classloader. Access to restricted classes is not possible without using reflection.

Unfortunately OSGi can not prevent you from using Java reflection to access these classes. This is because OSGi is based on the Java runtime which does not yet support a modularity layer.

Via the x-internal flag the OSGi runtime can mark an exported package as provisional. This allows other plug-ins to consume the corresponding classes, but indicates that these classes are not considered as official API.

The following screenshot shows how to set a package as x-internal in the manifest editor.

Setting the x-internal flag

This is how the corresponding manifest file looks like.

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-internal:=true

You can configure how the Eclipse Java editor shows the usage of provisional API. Such an access can be configured to be displayed as, error, warning or if such access should be result in no additional message.

The default is to display a warning message. You can adjust this in the Eclipse preferences via the Window  Preferences  Java  Compiler  Errors/Warnings preference setting.

Settings in Eclipse for warnings for deprecated API usage

You can define that a set of plug-ins can access provisional API without a warning or error message. This can be done 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 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:="another.bundle"

The x-friends setting has the same effect as x-internal but all plug-ins mentioned in the x-friends setting can access the package without receiving an error or warning message.

2.7. Eclipse API and internal API

An OSGi runtime allows the developer to mark Java packages as public, provisional or internal APIs. The internal API is private, therefore not visible. The provisional API are to test non-finalized APIs, therefore are visible but non-stable. The public API, or simply API, are the visible and stable API, that can be reused by other components.

API definition in Eclipse

The Eclipse platform project marks packages either as public API or as provisional API, to make all Java classes accessible to Eclipse developers. If the Eclipse platform project releases an API, the platform project plans to keep this API stable for as long as possible.

If API is internal but accessible, i.e., marked as provisional, the platform team can change this API in the future. If you use such API, you must be prepared that you might have to make some adjustments to your application in a future Eclipse release.

If you use unreleased API, you see a Discouraged access: The …​is not API (restriction on required project …​) warning in the Java editor.

You can turn off these warnings for your workspace via Window  Preferences  Java  Compiler  Errors/Warnings and by setting the Discouraged reference (access rules) flag to Ignore.

Alternatively you can turn off these warnings on a per project basis, via right-click on the project Properties  Java Compiler and afterwards use the same path as for accessing the global settings. You might have to activate the Enable project specific settings checkbox at the top of the Error/Warnings preference page.

3. Using the OSGi console

3.1. The OSGi console

The OSGi console is like a command-line shell. In this console you can type a command to perform an OSGi action. This can be useful to analyze problems on the OSGi layer of your application.

Use, for example, the command ss to get an overview of all bundles, their status and bundle-id. The following table is a reference of the most important OSGi commands.

Table 2. OSGi commands
Command Description


Lists the available commands.


Lists the installed bundles and their status.

ss vogella

Lists bundles and their status that have vogella within their name.

start <bundle-id>

Starts the bundle with the <bundle-id> ID.

stop <bundle-id>

Stops the bundle with the <bundle-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>

Shows information about the bundle with the <bundle-id> ID, including the registered and used services.

headers <bundle-id>

Shows the MANIFST.MF information for a bundle.

services filter

Shows all available services and their consumer. Filter is an optional LDAP filter, e.g., to see all services which provide a ManagedService implementation use the "services (objectclass=*ManagedService)" command.

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

3.3. 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 created with the Eclipse IDE contains this parameter by default. Via the following parameter you can open a port to which you can connect via the telnet protocol.

-console 5555

If you open a telnet session to the OSGi console, you can use tab completion and a history of the commands similar to the Bash shell under Linux.

3.4. Access to the Eclipse OSGi console

You can also access the OSGi console of your running Eclipse IDE. In the Console View 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.

If you want to access the OSGi host console in a runtime Eclipse IDE, you need to add the plug-ins from the org.eclipse.pde feature to your runtime.

4. Download the Eclipse SDK

If you plan to add functionalities to the Eclipse platform, you should download the latest Eclipse release. Official releases have stable APIs, therefore are a good foundation for adding your plug-ins and features.

The Eclipse IDE is provided in different flavors. While you can install the necessary tools in any Eclipse package, it is typically easier to download the Eclipse Standard distribution which contains all necessary tools for plug-in development. Other packages adds more tools which are not required for Eclipse plug-in development.

Browse to the Eclipse IDE download site and download the Eclipse IDE for Eclipse Committers package.

Download Eclipse Plug-in IDE

Eclipse provides also an Eclipse installer installer. The installer is useful, if you want to download several flavors of Eclipse. It uses a shared installation pool for common plug-ins, which reduces the required space.

5. Exercise: Data model plug-in

In this exercise you create a plug-in for the definition of your data model. You also make this data model available to other plug-ins.

5.1. Create the plug-in for the data model

Naming convention: simple plug-in

A plug-in can be generated by Eclipse via the File  New  Other…​  Plug-In Development  Plug-In Project menu entry. The corresponding wizard allows specifying several options. This tutorial calls plug-ins generated with the following options a simple plug-in or simple bundle.

  • No Activator

  • No contributions to the user interface

  • Not a rich client application

  • Generated without a template

Create a simple plug-in project called com.vogella.tasks.model.

Creating a simple plug-in

The following screenshot depicts the second page of the plug-in project wizard and its corresponding settings. Press the Finish button on this page to avoid the usage of templates.

Create a second page

5.2. Create the base class

Create the com.vogella.tasks.model package and the following model class.

package com.vogella.tasks.model;

import java.util.Date;

public class Todo {

    private final long id;
    private String summary = "";
    private String description = "";
    private boolean done = false;
    private Date dueDate = new Date();

You see an error for your final id field. This error is solved in the next section.

5.3. Generate constructors

Select Source  Generate Constructor using Fields…​ to generate a constructor using all fields. Use the same approach to create another constructor using only the id field.

Ensure that you have created both constructors, because they are required in the following exercises.

5.4. Generate getter and setter methods

Use the Source  Generate Getter and Setter…​ menu to create getters and setters for your fields.

Why is the id field marked as final?

The id is final and therefore Eclipse creates only a getter. This is correct and desired. We will use this field to generate the equals and hashCode() methods therefore it should not be mutable. Changing a field which is used in the equals and hashCode() methods can create bugs which are hard to identify, i.e., an object is contained in a HashMap but not found.

Getter and setter generation

5.5. Adjust the generated getter and setter methods

Adjust the generated getter and setter for the dueDate() field to make defensive copies. The Date class is not immutable and we want to avoid that an instance of Todo can be changed from outside without the corresponding setter.

public Date getDueDate() {
    return new Date(dueDate.getTime());

public void setDueDate(Date dueDate) {
    this.dueDate = new Date(dueDate.getTime());

The resulting class should look like the following listing.

package com.vogella.tasks.model;

import java.util.Date;

public class Todo {

    private final long id;
    private String summary = "";
    private String description = "";
    private boolean done = false;
    private Date dueDate = new Date();

    public Todo(long id) {
        this.id = id;

    public Todo(long id, String summary, String description, boolean done, Date dueDate) {
        this.id = id;
        this.summary = summary;
        this.description = description;
        this.done = done;


    public long getId() {
        return id;

    public String getSummary() {
        return summary;

    public void setSummary(String summary) {
        this.summary = summary;

    public String getDescription() {
        return description;

    public void setDescription(String description) {
        this.description = description;

    public boolean isDone() {
        return done;

    public void setDone(boolean done) {
        this.done = done;

    public Date getDueDate() {
        return new Date(dueDate.getTime());

    public void setDueDate(Date dueDate) {
        this.dueDate = new Date(dueDate.getTime());

5.6. Generate toString(), hashCode() and equals() methods

Use Eclipse to generate a toString() method for the Todo class based on the id and summary field. This can be done via the Eclipse menu Source  Generate toString()…​.

Also, use Eclipse to generate a hashCode() and equals() method based on the id field. This can be done via the Eclipse menu Source  Generate hashCode() and equals()…​.

5.7. Write a copy() method

Add the following copy() method to the class.

public Todo copy() {
    return new Todo(this.id, this.summary,
            this.description, this.done,

5.8. Create the interface for the todo service

Create the following ITodoService interface.

package com.vogella.tasks.model;

import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;

public interface ITodoService {

    void getTodos(Consumer<List<Todo>> todosConsumer);

    boolean saveTodo(Todo todo);

    Optional<Todo> getTodo(long id);

    boolean deleteTodo(long id);


5.9. Define the API of the model plug-in

Export the com.vogella.tasks.model package to define it as API.

For this, open the MANIFEST.MF file and select the Runtime tab. Add com.vogella.tasks.model to the exported packages.

Exported API

6. Exercise: Provide an OSGi service

In this exercise you create a plug-in for a service implementation. This implementation provides access to the task data.

This service implementation uses transient data storage, i.e., the data is not persisted between application restarts. To persist the data you could extend this class to store the data for example in a database or the file system. As this storage is not special for Eclipse plug-ins and applications, it is not covered in this tutorial.

6.1. Create a data model provider plug-in (service plug-in)

Create a new simple plug-in project called com.vogella.tasks.services. This plug-in is called service plug-in in the following description.

The MacOS operating system treads folders ending with .service special, therefore we use the .services ending.

6.2. Define the dependencies in the service plug-in

Add the com.vogella.tasks.model plug-in as dependency to your service plug-in. To achieve this, open the MANIFEST.MF file. Afterwards select the Dependencies tab and add the com.vogella.tasks.model package to the Imported Packages.

Also add a plug-in dependency in MANIFEST.MF file to:

  • org.eclipse.osgi.services

6.3. Provide an implementation of the ITodoService interface

Create the com.vogella.tasks.services.internal package in your service plug-in and create the following class.

package com.vogella.tasks.services.internal;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import com.vogella.tasks.model.ITodoService;
import com.vogella.tasks.model.Todo;

public class MyTodoServiceImpl implements ITodoService {

    private static AtomicInteger current = new AtomicInteger(1);
    private List<Todo> todos;

    public MyTodoServiceImpl() {
        todos = createInitialModel();

    public void getTodos(Consumer<List<Todo>> todosConsumer) {
        // always pass a new copy of the data
        todosConsumer.accept(todos.stream().map(t -> t.copy()).collect(Collectors.toList()));

    protected List<Todo> getTodosInternal() {
        return todos;

    // create or update an existing instance of Todo
    public synchronized boolean saveTodo(Todo newTodo) {
        // hold the Optional object as reference to determine, if the Todo is
        // newly created or not
        Optional<Todo> todoOptional = findById(newTodo.getId());

        // get the actual todo or create a new one
        Todo todo = todoOptional.orElse(new Todo(current.getAndIncrement()));

        if (!todoOptional.isPresent()) {
        return true;

    public Optional<Todo> getTodo(long id) {
        return findById(id).map(todo -> todo.copy());

    public boolean deleteTodo(long id) {
        Optional<Todo> deleteTodo = findById(id);

        deleteTodo.ifPresent(todo -> {

        return deleteTodo.isPresent();

    // Example data, change if you like
    private List<Todo> createInitialModel() {
        List<Todo> list = new ArrayList<>();
        list.add(createTodo("Application model", "Flexible and extensible"));
        list.add(createTodo("DI", "@Inject as programming mode"));
        list.add(createTodo("OSGi", "Services"));
        list.add(createTodo("SWT", "Widgets"));
        list.add(createTodo("JFace", "Especially Viewers!"));
        list.add(createTodo("CSS Styling", "Style your application"));
        list.add(createTodo("Eclipse services", "Selection, model, Part"));
        list.add(createTodo("Renderer", "Different UI toolkit"));
        list.add(createTodo("Compatibility Layer", "Run Eclipse 3.x"));
        return list;

    private Todo createTodo(String summary, String description) {
        return new Todo(current.getAndIncrement(), summary, description, false, new Date());

    private Optional<Todo> findById(long id) {
        return getTodosInternal().stream().filter(t -> t.getId() == id).findAny();


6.4. Enable annotation processing and plug-in activation

Ensure that OSGi services can be defined via annotations in the class via Window  Preferences  Plug-in Development  DS annotations.

Activate DS annotation processing

6.5. Define OSGi service

Add the @Component annotation to your MyTodoServiceImpl class. Eclipse uses this annotation to generate the necessary files to make the MyTodoServiceImpl class available as OSGi services for the ITodoService interface.

import org.osgi.service.component.annotations.Component;
// more stuff

public class MyTodoServiceImpl implements ITodoService {
    // as before ...

6.6. Update the product configuration (via your feature)

Add your new model and services plug-ins to your feature. Ensure that you use the Plug-ins tab on the feature.xml file.

Every time you create a new plug-in and refer to it in your MANIFEST.MF file you have to add it to your product configuration file (via your feature project).

7. Tutorial: Using the Activator and exporting your bundle

In this exercise you create another bundle which uses an Activator. You also 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.

7.1. Create a new Bundle

Create a new simple plug-in project "com.vogella.osgi.firstbundle.internal" via File  New  Other…​  Plug-in Development  Plug-in Project.

7.2. Coding

Create the following thread class.

package com.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 {
            } catch (Exception e) {
                System.out.println("Thread interrupted " + e.getMessage());

    public void stopThread() {
        active = false;

Change the class Activator.java to the following.

package com.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 com.vogella.osgi.firstbundle");
        myThread = new MyThread();

    public void stop(BundleContext context) throws Exception {
        System.out.println("Stopping com.vogella.osgi.firstbundle");


7.3. Run

Select your MANIFEST.MF file, right-click it and select Run As  Run Configuration. Create an OSGi Framework launch configuration. deselect all bundles except your de.vogella.osgi.firstbundle. Afterwards press the Add Required bundles. This adds the org.eclipse.osgi bundle to your run configuration.


Run this configuration. Every 5 seconds a new message is written to the console.

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.

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


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

But running the osgi jar solely is usually not desired.

Therefore the org.eclipse.osgi bundle needs to be configured by a config.ini file located in an configuration folder.

In order to pass commands to the OSGi runtime from the command line additional bundles are required.

  • org.eclipse.equinox.console

  • org.apache.felix.gogo.command

  • org.apache.felix.gogo.runtime

  • org.apache.felix.gogo.shell

To start these bundles with the org.eclipse.osgi bundle the config.ini file has to look like this:

osgi.bundles=org.eclipse.equinox.console@start, org.apache.felix.gogo.command@start, org.apache.felix.gogo.shell@start, org.apache.felix.gogo.runtime@start

With this configuration the other bundles have to be located right besides the org.eclipse.osgi bundle.

osgi standalone dir structure

With this setup the OSGi runtime can be started similar to this with the additional -console parameter:

java -jar org.eclipse.osgi_3.11.2.v20161107-1947.jar -console

Once started like this the OSGi console can be used, e.g., by using commands like ss to see the available bundles.

osgi standalone show bundles command

You can also 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 probably need to correct the path and the bundle name on your system.

You can start the bundle with start and the id.


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

9. OSGi Resources

10. vogella training and consulting support

Copyright © 2012-2018 vogella GmbH. Free use of the software examples is granted under the terms of the Eclipse Public License 2.0. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.