Let’s write and run your first OSGi service on WSO2 platform

As I promised last time, this post focuses on building OSGi services and their interaction. We are going to run over OSGi services in WSO2 carbon platform which is an OSGi based platform. Before heading to the implementation, make sure you have the basic idea of OSGi. You can get the background knowledge from here.

Let’s start with a very basic scenario.

Imagine there are two members; a producer (who produces a service) and a consumer (who consumes a service). For example, a greeting card maker(producer) to create greeting cards and a customer to buy a greeting card(consumer).

Let’s map this example to OSGi domain.

There is a module interaction in OSGi. Therefore, the producer and consumer are two different modules. Each module in a system defines a logical boundary. Also, a module itself is in a control of the classes which are fully encapsulated(hidden) and which are exposed to external use.

So, producer module should have a set of exposed services to the outside such as confirming order requests, sending orders, listing available cards, and etc. to use by consumers.

The consumer module can order a card, retrieve an ordered card, view available cards, and etc.

Hope now you have a good understanding of this practical example.

Module interaction of the above scenario

Let’s make our hands dirty.🤗

However, I hope you have the basic knowledge to make a maven project, add dependencies and plugins. If not, please have a quick glance at them, but I will explain in the lower level.

First, we will create the project structure to implement the modules(using Intellij IDEA editor in Ubuntu).

Create a maven project with the name greeting-card-manager. This is the main project and it contains both the producer and consumer component. (but it is not a must you can have a consumer and producer in separate two places)

groupId — org.wso2.carbon

artifactId — greeting-card-manager

version — 1.0-SNAPSHOT

packaging — pom

name — WSO2 Carbon-Greeting Card Manager

Note: <properties> and <modules> tags will add to this pom file later. Final pom is as follows.

pom.xml of Greeting-card-manager project

Now let’s create 2 sub maven projects (producer and consumer).

(1) org.wso2.carbon.greeting.card.producer

artifactId — org.wso2.carbon.greeting.card.producer

packaging — bundle

name — WSO2 Carbon-Greeting Card Producer

plugin — maven-bundle-plugin

plugin — maven-scr-plugin

dependency — org.apache.felix.scr.ds-annotations

dependency — org.eclipse.osgi.services

dependency — org.eclipse.osgi

Note: When adding this project, the parent project should be updated accordingly with <modules> and the current project with <parent> tag. If you are using an IDE, it auto generates them.

org.wso2.carbon.greeting.card.producer — pom.xml

Here is a brief explanation about the above pom file.

A OSGi bundle

Writing the manifest.mf file is a most important task when building an OSGi bundle. However, writing that file correctly is not an easy task. Therefore, you need to use a tool to generate it. Maven bundle plugin an example to use for it.

Maven bundle plugin decides the classes and resources which need be copied to your bundle and the manifest headers and their values which should be placed in the bundle’s manifest.mf file. Let’s see the manifest file of this component after building it.

You can see,

<packaging>bundle</packaging>

Setting “bundle” as the packaging element is the place where you configure maven to build an OSGi bundle

Bundle-SymbolicName, Bundle-Name, Export-Package, Import-Package, Private-Package and some other values sets for OSGi manifest header under configuration instructions of the maven-bundle plugin.

Note: Export-Packages instruction has taken precedence.

If you use the following order, all classes in org.wso2.carbon.greeting.card.producer package will be exported except classes inside org.wso2.carbon.greeting.card.producer.internal.

<Export-Package>
!org.wso2.carbon.greeting.card.producer.internal,
org.wso2.carbon.greeting.card.producer.*
</
Export-Package>

If the above order is changed, we can’t stop internal folder’s export.

Internal package contains the class which is used to register the OSGi service. We don’t expose it to outside. That’s why the above order is given in the Export-package. Further, we define that internal package is a private package.

<Private-Package>

org.wso2.carbon.greeting.card.producer.internal

</Private-Package>

Let’s write the greeting card service.

Create the following folder structure in org.wso2.carbon.greeting.card.producer project,and an interface named as GreetingCardProducer , a class named as GreetingCardProducerImpl (in src/main/java/org/wso2/carbon/greeting/card/producer/) , a java class named as GreetingCardProducerServiceComponent (in src/main/java/org/wso2/carbon/greeting/card/producer/internal) and a java class named as GreetingCard (in src/main/java/org/wso2/carbon/greeting/card/producer/model).

project structure of greeting card producer

Let’s write the service as follows and create the data model.

GreetingCardProducer.java
GreetingCardProducerImpl.java
GreetingCard.java

Then register the created service of greeting card producer in a registry in order to use it from other components.

That registering is done in the GreetingCardProducerServiceComponent class.

GreetingCardProducerServiceComponent.java
bundleContext.registerService(GreetingCardProducer.class,
GreetingCardProducerImpl.getInstance(), null);

Service registration is done in this line under activate method. The above added dependencies are used in this class.

(2) org.wso2.carbon.greeting.card.consumer

artifactId — org.wso2.carbon.greeting.card.consumer

packaging — bundle

name — WSO2 Carbon-Greeting Card Consumer

plugin — maven-bundle-plugin

plugin — maven-scr-plugin

dependency — org.wso2.carbon.greeting.card.producer

dependency — org.apache.felix.scr.ds-annotations

dependency — org.eclipse.osgi.services

dependency — org.eclipse.osgi

Note: When adding this project, the parent project should be updated accordingly with <modules> and the current project with <parent> tag. If you are using an IDE, it auto generates them.

org.wso2.carbon.greeting.card.consumer-pom.xml

An important thing in this pom file is import-packages. Since we are going to use the greeting card producer in this consumer module, that producer need to be imported here.

<Import-Package>
org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}",
org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}",
org.wso2.carbon.greeting.card.producer.*; version="${project.version}"
</Import-Package>

Create the following folder structure in org.wso2.carbon.greeting.card.consumer project, and a class named as GreetingCardConsumer (in src/main/java/org/wso2/carbon/greeting/card/consumer/), a class named as GreetingCardConsumerComponent (in src/main/java/org/wso2/carbon/greeting/card/consumer/internal/),and a class named as GreetingCardConsumerDataHolder (in src/main/java/org/wso2/carbon/greeting/card/consumer/internal/).

final project structure

Now we are going to write the consumer, in such a way that the consumer requests to create a greeting card at its activation.

GreetingCardConsumer.java
GreetingCardConsumerComponent.java
GreetingCardConsumerDataHolder.java

Now build your projects using mvn clean install command. Navigate to the greeting-card-manager folder. Then open a terminal and print mvn clean install .

If the build is succeeded, you could find

org.wso2.carbon.greeting.card.consumer-1.0-SNAPSHOT.jar inside greeting-card-manager/org.wso2.carbon.greeting.card.consumer/target

org.wso2.carbon.greeting.card.producer-1.0-SNAPSHOT.jar inside greeting-card-manager/org.wso2.carbon.greeting.card.producer/target

Open the jar files and check MANIFEST.MF file inside it, in order to understand how maven-bundle-plugin is made it.

Now we are done with creating OSGi bundles. Let’s deploy and test.

Deploy and Test

As I mentioned above, we are going to run these OSGi services in WSO2 platform.

  1. In your Web browser, go to http://wso2.com/products/carbon/.
  2. Click the Download button in the upper right-hand corner of the page to download the latest version. To download an older version, click the Previous Releases link and then select the version that you want.
  3. Enter the required details in the form, and click Download.
  4. Extract the downloaded zip file. Hereafter I’ll use <PRODUCT_HOME> for that extracted folder.
  5. Navigate to <PRODUCT_HOME>/repository/components/dropins .
  6. Copy org.wso2.carbon.greeting.card.consumer-1.0-SNAPSHOT.jar and org.wso2.carbon.greeting.card.producer-1.0-SNAPSHOT.jar to there.
  7. Then, go to <PRODUCT-HOME>/bin folder and start the product as follows.

In Linux Environment

sh wso2server.sh -DosgiConsole

In Windows Environment

wso2server.bat -DosgiConsole

Since we have used the producer inside consumer when the consumer activates, That requested greeting card needs to be created before starts the server.

The below highlighted logs could be seen if your bundles are activated and working properly.

Okay we are done. 😎

If you got any issue when activating the bundles let’s do a quick debug.

Useful OSGi commands to debug

After the server starts up, enter few lines. Then you can get the OSGi console.

Then type osgi> ss greeting .

ss → List down all bundles in the server with their bundle id, life cycle state and the name

ss <name> → Search the given name in the bundles name and list out only relevant bundles.

In order to perform the bundles activities, they should in ACTIVE state. If it is not ACTIVE debug further.

Note : The bundle life cycle is explained in here.

Then type osgi> b<bundle id> .

That command lists down the details of the selected bundle. Id, status, data root, registered services, services in use, exported packages, imported packages, and etc. So, you can check whether the services are registered and relevant packages are imported and exported.

Then type osgi>diag <bundle id> .

It shows any unsatisfied constraints of the bundle. So you can realize what are the reasons for not activating the bundle.

If it says No unresolved constraints. , it is good to proceed.

Here you can find the full code.

Happy Coding 😊

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Anuradha Karunarathna

Senior Software Engineer@ WSO2 | Computer Science and Engineering graduate@ University of Moratuwa, SriLanka