Writing your first OSGI Service in Liferay 7

writing-your-first-osgi-service-in-liferay-7


aimIn this article we will try to understand about OSI Service and its usage. In Liferay 7, OSGI plays a vital role. So its very important to understand the basics of OSGI Service. In this article we will create a basic OSGI service and in the next article we will create a portlet to consume this service.


Note

Whats OSGI Service???

1. An OSGI Service is simply a instance of Java Object registered in OSGI Framework with some properties. At the time of registering OSGI Service we can set properties to it. However setting properties is optional.

2. OSGI Service class must have to implement interface.

3. In OSGI everything is deployed as bundle. So when we create an OSGI Service, the final artifact is simply an OSGI Bundle.

4. An OSGI Bundle can register zero or multiple services in the OSGI Framework. Its not mandatory that an OSGI Bundle should register service. Its fully optional.

 5. The way an OSGI Bundle can Register services (or expose service ), similarly it can also consume one or many services.

 6. We can unregister a service at any point of time.   


Creating OSGI Service:

 Use the bellow maven command to create OSGI Service

 mvn archetype:generate
-DarchetypeGroupId=com.liferay
-DarchetypeArtifactId=com.liferay.project.templates.service
-DgroupId=com.proliferay
-DartifactId=com.proliferay.sample.osgi.service
-DserviceClass=SampleService
-DclassName=SampleServiceImpl
-DinteractiveMode=false 

Service Interface:

package com.proliferay.service;

public interface SampleService {

	public int add(int number1, int number2);
}

Service Implementation:

package com.proliferay.service.impl;

import com.proliferay.service.SampleService;

import org.osgi.service.component.annotations.Component;

@Component(
	immediate = true,
	property = {
		// TODO enter required service properties
	},
	service = SampleService.class
)
public class SampleServiceImpl implements SampleService {

	@Override
	public int add(int number1, int number2) {
		System.err.println("###########Calling add() method##################");
		return number1 + number2;
	}
}

Bundle Activator: 

Now we have service implementation in place. The OSGI framework has to understand that its a service. To make OSGI to understand that its a service, we have to register the service in the framework. We can use bundle activator to register our service. Remember that an activator class must implement BundleActivator interface. Below is the code for registering the service.

package com.proliferay.activator;

import com.proliferay.service.SampleService;
import com.proliferay.service.impl.SampleServiceImpl;

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

public class ServiceActivator implements BundleActivator {

	private ServiceRegistration registration;
	
	@Override
	public void start(BundleContext context) throws Exception {

		registration = context.registerService(SampleService.class.getName(), new SampleServiceImpl(), null);
		System.out.println("###########Service Registered Successfully##############");
	}

	@Override
	public void stop(BundleContext context) throws Exception {
		registration.unregister();
		System.out.println("###########Service Unregistered##############");
		
	}

}


NoteBundleActivator???

A bundle activator is simply a class which is notified when a bundle starts and stops. Therefore to register our service BundleActivator is the right choice. Just write the registration code inside the start method so that when the bundle start the service is also registered as well.


Very Important!!!!

The final artifact of the project is OSGI bundle and its not same as traditional JAR file. The MANIFEST file must have BundleActivator entry so that when the bundle is deployed in OSGI container, it reads the MANIFEST file at first. Look into bnd.bnd file in the source code. Give attention to the Export-Package entry also. We need to expose our service so that from other bundle it can be discovered.

Bundle-Name: com.proliferay.sample.osgi.service
Bundle-SymbolicName: com.proliferay
Bundle-Version: 1.0-SNAPSHOT
Bundle-Activator: com.proliferay.activator.ServiceActivator
Export-Package: com.proliferay.service

When the bundle is packaged at the end, look inside the JAR(which is nothing but bundle) and open the MANIFEST file. It should look like

Manifest-Version: 1.0
Bundle-SymbolicName: com.proliferay
Archiver-Version: Plexus Archiver
Built-By: hamidul.islam
Bnd-LastModified: 1479719348003
Bundle-ManifestVersion: 2
Import-Package: com.proliferay.service,org.osgi.framework;version="[1.
 8,2)"
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
Service-Component: OSGI-INF/com.proliferay.service.impl.SampleServiceI
 mpl.xml
Tool: Bnd-3.2.0.201605172007
Provide-Capability: osgi.service;objectClass:List<String>="com.prolife
 ray.service.SampleService"
Export-Package: com.proliferay.service;version="1.0.0"
Bundle-Name: com.proliferay.sample.osgi.service
Bundle-Version: 1.0.0.201611210909
Bundle-Activator: com.proliferay.activator.ServiceActivator
Private-Package: com.proliferay.activator,com.proliferay.service.impl
Created-By: 1.8.0_111 (Oracle Corporation)
Build-Jdk: 1.8.0_111

Packaging and deploying the Bundle:

Navigate to the project directory and execute mvn clean install. The generated bundle will be available in the target folder of the project directory. Now copy the bundle and deploy in the deploy folder of Liferay. After few seconds the service will be registered in the OSGI Container.

Checkpoint:

We have deployed the service. How would we know whether the service is registered or not. For a quick check open the Gogo Shell. We will find the bundle id of deployed bundle. The Active status of a bundle indicates that the bundle is active inside the container. 

g! lb proliferay 
START LEVEL 20
   ID|State      |Level|Name
  513|Active     |    1|com.proliferay.demo (1.0.0.201611210957)
  514|Active     |   10|com.proliferay.sample.osgi.service (1.0.0.201611210909)
g! 

As displayed in the above 514 is the ID of the bundle. Now we can check the service associated with the bundle ID

g! inspect cap service 514
com.proliferay_1.0.0.201611210909 [514] provides:
-------------------------------------------------
service; com.proliferay.service.SampleService with properties:
   service.id = 6749
   service.bundleid = 514
   service.scope = singleton
   Used by:
      com.proliferay_1.0.0.201611210957 [513]
service; com.proliferay.service.SampleService with properties:
   component.name = com.proliferay.service.impl.SampleServiceImpl
   component.id = 2414
   service.id = 6763
   service.bundleid = 514
   service.scope = bundle
g! 

Summery:
In this article we have shown how to create a sample service. In the next article we will explain how to use this service inside another bundle/portlet.

Download Source Code:

com-proliferay-sample-osgi-service

About The Author

3 thoughts on “Writing your first OSGI Service in Liferay 7”

  1. Pingback: Consume OSGI Service in Liferay Portlet - Pro Liferay

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top