Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Tagged as

OSGI for Beginners Using Maven with Equinox(HowTo)

, 2 Jun 2011 Apache
Rate this:
Please Sign up or sign in to vote.
I have struggled to understand what OSGI really means for a long time. It has been around since a very long time but not many people are aware of it. It has been hyped as a very complex technology to understand. Here is my attempt to make it simple for any Java Developer. In my [...]

I have struggled to understand what OSGI really means for a long time. It has been around since a very long time but not many people are aware of it. It has been hyped as a very complex technology to understand. Here is my attempt to make it simple for any Java Developer. In my view if you understand concept of Interface , JNDI or EJB( Or registering some service in some form)  you will understand OSGI. In short OSGI is a Container where you can register your services through interfaces and those can be accessed any time. Another benefit of OSGI is that all these services can be Installed/Uninstalled/Started/Stopped at runtime (i.e Code can be hot deployed at runtime ) rather than normal requirement we have where we have restart J2EE server. Similar to J2ee containers (Tomcat, WebSphere, Jboss , Weblogic ) OSGI also has container like Equinox( Which is base for Eclipse), Apache Felix …etc

In this article i’m going to explain OSGI with Eclipse Equinox container. Anyone who has Eclipse IDE installed on their machine has OSGI container also installed in Eclipse plugin’s folder.

Name of OSGI container jar file looks like   org.eclipse.osgi_<version>.jar

You can start OSGI like this

java -jar org.eclipse.osgi_3.5.2.R35x_v20100126.jar -console

Attached is sample screenshot of how i started my OSGI container ( Its analogous to starting tomcat)

Now that we started OSGI , let me start creation a HelloWorld OSGI Application using Maven. Lemme show you my project structure first and then display my pom.xml


Now i’ll display my pom.xml. My pom.xml has 2 more profiles added to create 2 more new modules(MathService and MathServiceClient) which will be later explained in this article

<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>com.linkwithweb.osgi</groupId>
	<artifactId>HelloWorld</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>HelloWorld</name>
	<dependencies>
		<dependency>
			<groupId>org.osgi</groupId>
			<artifactId>org.osgi.core</artifactId>
			<version>4.2.0</version>
		</dependency>
	</dependencies>

	<build>
		<finalName>HelloWorld-${version}</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.1</version>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<archive>
						<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
					</archive>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<profiles>
		<profile>
			<id>MathService</id>
			<build>
				<finalName>MathService-${version}</finalName>
				<plugins>
					<plugin>
						<groupId>org.apache.maven.plugins</groupId>
						<artifactId>maven-compiler-plugin</artifactId>
						<version>2.3.1</version>
						<configuration>
							<source>1.5</source>
							<target>1.5</target>
						</configuration>
					</plugin>

					<plugin>
						<groupId>org.apache.maven.plugins</groupId>
						<artifactId>maven-jar-plugin</artifactId>
						<configuration>

							<excludes>
								<exclude>**/*.xml</exclude>
								<exclude>**/*.bsh</exclude>
								<exclude>**/*.properties</exclude>
							</excludes>
							<archive>
								<manifestFile>src/main/resources/MathService/META-INF/MANIFEST.MF</manifestFile>
							</archive>
						</configuration>
					</plugin>

				</plugins>
			</build>
		</profile>
		<profile>
			<id>MathServiceClient</id>
			<build>
				<finalName>MathServiceClient-${version}</finalName>
				<plugins>
					<plugin>
						<groupId>org.apache.maven.plugins</groupId>
						<artifactId>maven-compiler-plugin</artifactId>
						<version>2.3.1</version>
						<configuration>
							<source>1.5</source>
							<target>1.5</target>
						</configuration>
					</plugin>

					<plugin>
						<groupId>org.apache.maven.plugins</groupId>
						<artifactId>maven-jar-plugin</artifactId>
						<configuration>

							<excludes>
								<exclude>**/*.xml</exclude>
								<exclude>**/*.bsh</exclude>
								<exclude>**/*.properties</exclude>
							</excludes>
							<archive>
								<manifestFile>src/main/resources/MathServiceClient/META-INF/MANIFEST.MF</manifestFile>
							</archive>
						</configuration>
					</plugin>

				</plugins>
			</build>
		</profile>
	</profiles>

</project>

Now if you observe pom.xml there are 3 different MANIFEST.MF defined for 3 different OSGI bundle’s we create.  Saying so lemme explain you that OSGI bundles are same as Java jar file with its configuration defined in Manifest file of standard jar. OSGI defined few entries in manifest file which are related to OSGi which are read by container to activate the bundle, thus avoiding learning of any new metadata format we generally have for other frameworks

Here is sample Manifest.MF i have defined for MathServiceClient

Manifest-Version: 1.0
Bundle-Name: MathServiceClient
Bundle-Activator: com.linkwithweb.osgi.service.client.MathServiceClientActivator
Bundle-SymbolicName: MathServiceClient
Bundle-Version: 1.0.0
Import-Package: org.osgi.framework,com.linkwithweb.osgi.service

If you observe above manifest file you can observer that all the entries except Manifest-Version are OSGI specific entries. These are the entries which define how to deploy a bundles what all it is dependent on and what are extension points it exposes for other services to consume.. etc

Having explained this lemme first explain a HelloWorld bundle with its MANIFEST.MF and Activator class and its installation into Equinox OSGI Container

/**
 *
 */
package com.linkwithweb.osgi;

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

/**
 * @author Ashwin Kumar
 *
 */
public class HelloActivator implements BundleActivator {
	public void start(BundleContext context) {
		System.out.println("Hello World");
	}

	public void stop(BundleContext context) {
		System.out.println("Goodbye All");
	}
}
Manifest-Version: 1.0
Bundle-Name: HelloWorld
Bundle-Activator: com.linkwithweb.osgi.HelloActivator
Bundle-SymbolicName: HelloWorld
Bundle-Version: 1.0.0
Import-Package: org.osgi.framework

Now run “mvn clean package” to build our bundle

It will create HelloWorld-0.0.1-SNAPSHOT.jar in target folder and we can install that into Equinox to test. Here is the image which shows how to install and start our HelloWorld into Equinox

install file:K:\Ashwin\OSGI\MavenProject\target\HelloWorld-0.0.1-SNAPSHOT.jar

If you observe above screenshot you can use install command to install the bundle and use the start command on bundle id to start the bundle

On start of Bundle start method of Activator class is called and while stopping bundle stop method of Activator is called and so you are seeing HelloWorld

Congratulations you have learned basics of OSGI and you have just deployed your first bundle.

Now lemme explain my second part of article which explains how to Expose and Consume services of modules

Exposing and Consuming Services

To explain this i’ll take a very simple example where i’ll publish a service which can add 2 numbers

Here is the code which does that

First we need to define an Interface which we are thinking of exposing to external bundles

/**
 *
 */
package com.linkwithweb.osgi.service;

/**
 * @author Ashwin Kumar
 *
 */
public interface MathService {

	/**
	 * @param a
	 * @param b
	 * @return
	 */
	public int add(int a, int b);
}

Now the implementation Class

/**
 *
 */
package com.linkwithweb.osgi.service;

/**
 * @author Ashwin Kumar
 *
 */
public class MathServiceImpl implements MathService {

	/* (non-Javadoc)
	 * @see com.linkwithweb.osgi.service.MathService#add(int, int)
	 */
	public int add(int a, int b) {
		// TODO Auto-generated method stub
		return a+b;
	}

}

Now Activator class which register’s this service with OSGI container

/**
 *
 */
package com.linkwithweb.osgi.service;

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

/**
 * @author Ashwin Kumar
 *
 */
public class MathServiceActivator implements BundleActivator {
	/*
	 * (non-Javadoc)
	 *
	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
	 */
	public void start(BundleContext context) {
		MathService service = new MathServiceImpl();
		// Third parameter is a hashmap which allows to configure the service
		// Not required in this example
		context.registerService(MathService.class.getName(), service, null);
		System.out.println("Math Service Registered");
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) {
		System.out.println("Goodbye From math service");
	}
}

Here is the manifest file which exposes service

Manifest-Version: 1.0
Bundle-Name: MathService
Bundle-Activator: com.linkwithweb.osgi.service.MathServiceActivator
Bundle-SymbolicName: MathService
Bundle-Version: 1.0.0
Import-Package: org.osgi.framework
Export-Package: com.linkwithweb.osgi.service

If you observe this we are Exporting some packages so that they can be consumed later. Also all the package that we are thinking of importign have to be defined here

Use the following command to build the jar file

mvn -PMathService package

and Here is image which displays how to Install and Run the service

Now lemme explain how to implement consumer

/**
 *
 */
package com.linkwithweb.osgi.service.client;

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

import com.linkwithweb.osgi.service.MathService;

/**
 * @author Ashwin Kumar
 *
 */
public class MathServiceClientActivator implements BundleActivator {
	MathService service;
	private BundleContext context;

	/*
	 * (non-Javadoc)
	 *
	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
	 */
	public void start(BundleContext context) {
		this.context = context;
		// Register directly with the service
		ServiceReference reference = context
				.getServiceReference(MathService.class.getName());
		service = (MathService) context.getService(reference);
		System.out.println(service.add(1, 2));
	}	/*
	 * (non-Javadoc)
	 *
	 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) {
		System.out.println(service.add(5, 6));
	}
}

And now manifest file

Manifest-Version: 1.0
Bundle-Name: MathServiceClient
Bundle-Activator: com.linkwithweb.osgi.service.client.MathServiceClientActivator
Bundle-SymbolicName: MathServiceClient
Bundle-Version: 1.0.0
Import-Package: org.osgi.framework,com.linkwithweb.osgi.service

Now here is how we create package and install

mvn -PMathServiceClient package

Source code have been checkedin to following location

https://linkwithweb.googlecode.com/svn/trunk/osgi-tutorials/MavenProject

 

Njoy creating OSGI bundles . Main benefit is you can redeploy your bundles/services at runtime.

Mail me incase you have any doubts


License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0

Share

About the Author

AshwinRayaprolu
Chief Technology Officer Northalley
United States United States
A Technology evangelist with no technical language barriers. A strong believer that Simple Sofware Is Perfect Software. A staunch proponent of software / documentation automation in all domain's. And finally a true diciple of Google Search.

Comments and Discussions

 
GeneralFeedback PinmemberMember 1024344430-Aug-13 14:28 
GeneralMy vote of 5 PinmemberAta Amini13-Mar-12 12:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 2 Jun 2011
Article Copyright 2011 by AshwinRayaprolu
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid