OSGi – Simple Hello World with services

OSGi Logo

In this post, we’ll develop a simple Hello World application with OSGi. We will use Felix as OSGi container. In the next post, we’ll continue with this application and use Spring Dynamic Modules to improve it.

To make the development interesting, we will create two bundles :

  • A bundle providing a service of HelloWorld
  • A bundle consuming the service to print hello at regular interval time.

So let’s start with the first bundle. What we need first is a very simple service providing a simple print in the console :

package com.bw.osgi.provider.able;
 
public interface HelloWorldService {
    void hello();
}
package com.bw.osgi.provider.impl;
 
import com.bw.osgi.provider.able.HelloWorldService;
 
public class HelloWorldServiceImpl implements HelloWorldService {
    @Override
    public void hello(){
        System.out.println("Hello World !");
    }
}

We cannot make easier. Then, we need to export the Service using an activator :

package com.bw.osgi.provider;
 
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
 
import com.bw.osgi.provider.able.HelloWorldService;
import com.bw.osgi.provider.impl.HelloWorldServiceImpl;
 
public class ProviderActivator implements BundleActivator {
    private ServiceRegistration registration;
 
    @Override
    public void start(BundleContext bundleContext) throws Exception {
        registration = bundleContext.registerService(
                HelloWorldService.class.getName(),
                new HelloWorldServiceImpl(),
                null);
    }
 
    @Override
    public void stop(BundleContext bundleContext) throws Exception {
        registration.unregister();
    }
}

A lot more code here. For those who aren’t confident with OSGi, some explanations. The start method will be called when the module is started and the stop when it’s stopped. In the start method, we register our service in the bundle context using the name of the interface as the name of the exported service. The third parameter, null, indicate that we doesn’t give any configuration for this service. In the stop method, we just unregister the service.

Now, our first bundle is ready. We can build it. For that we’ll use Maven and the maven-bundle-plugin to build the OSGi Bundle directly. Here is the pom.xml file for the project.

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>OSGiDmHelloWorldProvider</groupId>
    <artifactId>OSGiDmHelloWorldProvider</artifactId>
    <version>1.0</version>
 
    <dependencies>
        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.osgi.core</artifactId>
            <version>1.4.0</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
 
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>OSGiDmHelloWorldProvider</Bundle-SymbolicName>
                        <Export-Package>com.bw.osgi.provider.able</Export-Package>
                        <Bundle-Activator>com.bw.osgi.provider.ProviderActivator</Bundle-Activator>
                        <Bundle-Vendor>Baptiste Wicht</Bundle-Vendor>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build> 
</project>

And then, use mvn install to build it.

We’ll work in a folder called osgi, so we’ll copy this new bundle in the osgi folder.

We can already test it in the OSGi container. If you dont’ have already Felix, let’s download it here. You have to choose the “Felix Distribution”.

Then extract it to the osgi folder we created before. You must now have this folder structure :

osgi
  - felix
  - OSGiDmHelloWorldProvider-1.0.jar

So we can go in the felix folder and launch Felix :

wichtounet@Linux-Desktop:~/Desktop/osgi/felix$ java -jar bin/felix.jar
_______________
Welcome to Apache Felix Gogo

g! 

And install our bundle :

g! install file:../OSGiDmHelloWorldProvider-1.0.jar
Bundle ID: 5

The install is good installed, we can try to start it and see its status :

g! start 5
g! bundle 5
Location             file:../OSGiDmHelloWorldProvider-1.0.jar
State                32
Version              1.0.0
LastModified         1279124741320
Headers              [Tool=Bnd-0.0.357, Bundle-Activator=com.bw.osgi.provider.ProviderActivator, Export-Package=com.bw.osgi.provider.able, Build-Jdk=1.6.0_20, Bundle-Version=1.0.0, Created-By=Apache Maven Bundle Plugin, Bundle-ManifestVersion=2, Manifest-Version=1.0, Bundle-Vendor=Baptiste Wicht, Bnd-LastModified=1279124686551, Bundle-Name=Unnamed - OSGiDmHelloWorldProvider:OSGiDmHelloWorldProvider:bundle:1.0, Built-By=wichtounet, Bundle-SymbolicName=OSGiDmHelloWorldProvider, Import-Package=com.bw.osgi.provider.able,org.osgi.framework;version="1.5"]
BundleContext        org.apache.felix.framework.BundleContextImpl@2353f67e
BundleId             5
SymbolicName         OSGiDmHelloWorldProvider
RegisteredServices   [HelloWorldService]
ServicesInUse        null

All is fine. Our service is good registered :)

Now we’ll try to consume this service in our second bundle. Our consumer class will be very simple :

package com.bw.osgi.consumer;
 
import javax.swing.Timer;
 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import com.bw.osgi.provider.able.HelloWorldService;
 
public class HelloWorldConsumer implements ActionListener {
    private final HelloWorldService service;
    private final Timer timer;
 
    public HelloWorldConsumer(HelloWorldService service) {
        super();
 
        this.service = service;
 
        timer = new Timer(1000, this);
    }
 
    public void startTimer(){
        timer.start();
    }
 
    public void stopTimer() {
        timer.stop();
    }
 
    @Override
    public void actionPerformed(ActionEvent e) {
        service.hello();
    }
}

And now, we must create the activator to get the service and then give it to the consumer. That will give use something like this :

package com.bw.osgi.consumer;
 
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
 
import com.bw.osgi.provider.able.HelloWorldService;
 
public class HelloWorldActivator implements BundleActivator {
    private HelloWorldConsumer consumer;
 
    @Override
    public void start(BundleContext bundleContext) throws Exception {
        ServiceReference reference = bundleContext.getServiceReference(HelloWorldService.class.getName());
 
        consumer = new HelloWorldConsumer((HelloWorldService) bundleContext.getService(reference));
        consumer.startTimer();
    }
 
    @Override
    public void stop(BundleContext bundleContext) throws Exception {
        consumer.stopTimer();
    }
}

We get a service reference from the bundle context using the name of the class. After that, we get the service instance from the bundle context.

We create also a little pom.xml file to build the bundle :

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <modelVersion>4.0.0</modelVersion>
    <groupId>OSGiDmHelloWorldConsumer</groupId>
    <artifactId>OSGiDmHelloWorldConsumer</artifactId>
    <version>1.0</version>
    <packaging>bundle</packaging>
 
    <dependencies>
        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.osgi.core</artifactId>
            <version>1.0.0</version>
        </dependency>
 
        <dependency>
            <groupId>OSGiDmHelloWorldProvider</groupId>
            <artifactId>OSGiDmHelloWorldProvider</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
 
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>OSGiDmHelloWorldConsumer</Bundle-SymbolicName>
                        <Bundle-Activator>com.bw.osgi.consumer.HelloWorldActivator</Bundle-Activator>
                        <Bundle-Vendor>Baptiste Wicht</Bundle-Vendor>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Then, we use mvn install to create the bundle and we install it in the container :

g! start 6
g! Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
g! stop 6

And here we are :) We’ve created our first application using OSGi. With that technology you can build modules really independant.

In the next post about OSGi, we’ll see how to use Spring to make the OSGi development easier and to concentrate our effort on the application not OSGi.

The sources of the two bundles are available here :

Related posts:

  1. OSGI and Spring Dynamic Modules – Simple Hello World
  2. OSGi 4.2 Entreprise Release is available !
  3. Bundle non-OSGi dependencies with Maven
  4. JTheque Core 2.1.0 released !
  5. Modular Java – Book Review
  • http://hello-world-123.blogspot.com Hello World

    Cute. I wonder if I could use it on my site?

    • Baptiste Wicht

      Thanks.

      Yes, you can use it if you cite me as the author, there is no problem.

  • http://hello-world-123.blogspot.com Hello World

    Cute. I wonder if I could use it on my site?

    • Baptiste Wicht

      Thanks.

      Yes, you can use it if you cite me as the author, there is no problem.

  • http://www.moldremoval.net Mold Removal Miami

    Wow! great site.Thanks.

  • http://www.terrazzorestoration.net Terrazzo Polish Ft.Lauderdale

    OSGi – Simple Hello World with services!

  • http://www.terrazzofloorcleaning.net Restore Terrazzo Ft.Lauderdale

    Good stuff in here!

  • http://www.terrazzocleaning.net Terrazzo Repair

    To make the development interesting, we will create two bundles.

  • http://www.terrazzofloorpolishing.net Terrazzo Repair

    To make the development interesting, two bundles were created!

  • http://www.moldtesting.org Mold Testing Hialeah

    I wonder if I could use it on my site?

    • Anonymous

      Of course you can, just add a little note to indicate me as the author.

  • http://www.terrazzocleaning.net/ Terrazzo Care West Palm Beach

    OSGi – Simple Hello World with services

  • http://www.terrazzofloorpolishing.net/ Terrazzo Floor Care Boca Raton

    In the next post, we’ll continue with this application

  • http://www.terrazzofloorrestoration.net/ Polish TerrazzoFloor BocaRaton

    We use mvn install to create the bundle and we install it in the container

  • http://www.terrazzofloorpolishing.net/ Maintaining Terrazzo BocaRaton

    What we need first is a very simple service providing a simple print in the console