Create an OSGi Bundle and Deploy in Equinox

In this tutorial, we will learn how to build a simple OSGi bundle and deploy it in an OSGi framework (Eclipse Equinox).

Technologies used –

  • Eclipse IDE for Java EE developer 4.5.0.20150621-1200 (Mars)
  • Preinstalled Maven with Eclipse Mars
  • Java 1.8

Create Bundle:

Using eclipse-

1.  Open eclipse and go to New > Maven Project > Next > Add Archetype …

2.  Fill in the following values:

Archetype Group Id=org.apache.karaf.archetypes
Archetype Artifact Id=karaf-bundle-archetype
Archetype Version=2.4.0

Please note that this step is needed only if you don’t have the archetype already available in your workspace.

KarafBundleArchetypeCreate

 

3.  Close the maven project window. Again, try creating a maven project and you should see karaf bundle archetype in catalogs list. Please select it.

 

karafbundlearchtype

 

4. Click Next and fill the details.

 

Karaf Bundle Project Artifact Id

 

5. Click Finish. You should get your maven bundle project.

 

Karaf Maven Bundle Project

Using command line (In Mac):

1. Download maven from Maven 3.3.3
2. Unzip the folder in your favorite directory.
3. In your Home directory, open the file .bash_profile. If you don’t have the file, please create one.
4. Update the file with the following entry :

export M2_HOME=~/Development/apache-maven-3.3.3
export PATH=$PATH:$M2_HOME/bin
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home

Note: Please note that ~(tilde) used is my home directory since I downloaded maven in my home directory. Also, version of java used may be different for you and so is your java installation directory. Please make changes accordingly.

5.  Open command line and type the below command.

mvn archetype:generate \
    -DarchetypeGroupId=org.apache.karaf.archetypes \
    -DarchetypeArtifactId=karaf-bundle-archetype \
    -DarchetypeVersion=2.4.0 \
    -DgroupId=com.javanbeyond \
    -DartifactId=MyFirstBundle \
    -Dversion=0.0.1-SNAPSHOT \
    -Dpackage=com.javanbeyond.bundle \
    -DinteractiveMode=false

6. Once the command execution completes, you should get the following folder structure inside  MyFirstBundle folder.

.
./pom.xml
./src
./src/main
./src/main/java
./src/main/java/com
./src/main/java/com/javanbeyond
./src/main/java/com/javanbeyond/bundle
./src/main/java/com/javanbeyond/bundle/Activator.java

Project artifacts:

1. Maven dependencies and bundle plugin
file:pom.xml. It uses maven bundle plugin to create bundles and make appropriate entries in the bundle MANIFEST.MF file.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -->
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.javanbeyond</groupId>
    <artifactId>MyFirstBundle</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>bundle</packaging>
    <name>MyFirstBundle Bundle</name>
    <description>MyFirstBundle OSGi bundle project.</description>
    <dependencies>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.core</artifactId>
            <version>5.0.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>2.5.0</version>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                        <Bundle-Version>${project.version}</Bundle-Version>
                        <Bundle-Activator>com.javanbeyond.bundle.Activator</Bundle-Activator>
                        <!-- The package exposed and can be used by other bundles. -->
                        <Export-Package>com.javanbeyond.bundle*;version=${project.version}</Export-Package>
                        <!-- wildcard dynamic import. if there is any dependency on other bundles, it will be loaded automatically, if deployed in the container -->
                        <Import-Package>*</Import-Package>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2. OSGi Life cycle methods

file: Activator.java. Lifecycle class whose methods are called before a bundle is started and after it is stopped.

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.javanbeyond.bundle;

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

// This is a life cycle class of a bundle
public class Activator implements BundleActivator {

    // this life cycle method is called when the bundle starts
    // it get Bundle Context parameter which can used to register a class, get
    // other bundles etc.
    public void start(BundleContext context) {
        System.out.println("Starting the bundle");
    }

    // this method is called when the bundle stops. Can be used for resource
    // cleaning etc.
    public void stop(BundleContext context) {
        System.out.println("Stopping the bundle");
    }

}

 

Start OSGi framework (Eclipse Equinox):

Eclipse Mars comes preinstalled with Equinox OSGi framework.

  1. Right click on the project and go to  Run As  > Run Configurations…> OSGi Framework.
  2. Double click on OSGi Framework and name the configuration of your choice.
  3. Uncheck all the boxes of Target Platform in Bundles column.
  4. Select only the below bundles:
  • org.apache.felix.gogo.command
  • org.apache.felix.gogo.runtime
  • org.apache.felix.gogo.shell
  • org.eclipse.osgi
  • org.eclipse.equinox.console

Eclipse OSGi Equinox

5. Go to Settings tab above and check “Clear the configuration area before launching” and click on Apply and then  Run.

Start OSGi Framework Console

Deploy the created OSGi Bundle:

1. Run maven clean and install on the newly created project. A jar named “MyFirstBundle-0.0.1-SNAPSHOT.jar” should get created in the target folder.

2. On the OSGi console, type “install file:<PATH TO JAR>/MyFirstBundle-0.0.1-SNAPSHOT.jar” where <PATH TO JAR> is location of jar.

Please note that in case of Windows, you might need to provide double slash for path to jar.

3. The jar should get deployed with a snapshot of it’s MANIFEST.MF file.

Install OSGi Bundle initiative

MANIFEST.MF

The MANIFEST.MF file, which resides in META-INF folder of jar is to Bundle as web.xml is to War (Web archive) file. The MANIFEST.MF file acts as a deployment descriptor of the bundle. Here’s a brief description of the headers of MANIFEST.MF file.

Bnd-LastModified
This header is set by Bnd API to give information on the last modified time of the bundle.

Build-Jdk
The Jdk version used to build this bundle.

Bundle-Activator
It names our optional listener Activator class to be notified of bundle start and stop events. Please note that the class should be public and contain a public constructor without any arguments.

Bundle-Description
A brief description of the bundle. This is set to some default value if no value is mentioned in pom.xml. In practice, it can be a description of the role the bundle plays in the application.

Bundle-ManifestVersion
It indicates the OSGi specification to use for reading this bundle. 1 indicates OSGi release 3 while 2 OSGi release 4 and later.

Bundle-Name
It defines a short, human-readable name for the bundle.

Bundle-SymbolicName
It specifies a unique identifier for the bundle. This name will be used while referring a given bundle from other bundles. In our case, the project name is given to the value of this header.

Created-By
The API name that created it.

Bundle-Version
The version of the bundle.In our case, project version is given to the value of this header.

Export-Package
It indicates what packages (available in the bundle) are exported so they can be imported by other bundles. Only the packages specified by this header will be exported, the rest will be private and will not be seen outside the containing bundle.

Import-Package
It indicates the packages that are imported by a bundle. Only the packages specified by this header will be imported. By default, imported packages are mandatory – the importing bundle will fail to start, if the imported package is not available. In our case, we have given wildcard expression to the value of this header. It means that the Maven Bnd api would traverse though all the import statements of bundle to get the name of the dependent packages for this bundle and accordingly, set its value. Please note that if you are using declarative configuration where you define dependencies in xml files, it may not be reported here. In such case, please set the values specifically.

4. Type “start <BUNDLE ID>”. In this case, <BUNDLE ID> is 5. So the command is “start 5”.

5. The bundle should start with the output of Activator’s start method. Similarly, if it is stopped, it will output the print of stop method.

6. Stop the bundle with command “stop <BUNDLE ID>”.

7. If you want to uninstall the bundle, type “uninstall <BUNDLE ID>”.

osgi> start 5
Starting the bundle
osgi> stop 5
Stopping the bundle
osgi> uninstall 5
osgi>

 

Back to Top