Liferay Development

Liferay Consulting

Liferay Training

Your Trusted Liferay Solutions Partner

Friday, September 29, 2017

OSGi Declarative Services Detailed Information

OSGI Declarative Services is a mechanism to create components and manage dependencies among the components. DS we can also called Service Component Runtime and DS and SCR convey same thing in the OSGi Development.

DS will use the XML configuration to define components and its references.  XML files available in the OSGi bundle. When we are talking about DS/SCR, we have following terminology such as Component, Services and Lifecycle.

The following article will gives idea of OSGI Declarative Services.


Components

OSGi primary artifact is Components. Declarative Services created the Component and managed by the OSGi Service Component Runtime.

The following terminology required when we are talking about OSGi components.

Service Component

Service Component is java class declared by Component Description and managed by OSGi Component Service Runtime. This configuration is defined in the XML file with in the bundle.

Usually Service Components are providing set of services and these services perform certain tasks. These components services will be used in the other bundles.

We can declare every java class as OSGi components and not every component have services.  Sometimes component may not provide any service.

Once we declared java class as Service Component then services available to all the bundles, which deployed in the OSGi container.

Component Description

Component Description is XML configuration to Declare Service Component in the bundle. Usually this configuration is available in XML file in the bundle.

Component Configuration

Component Configuration consist of set of properties and it will be used to track the dependencies and manage the Component instance.

Component Instance

The instance of the component implementation class. It is created when a Component Configuration is activated and discarded if the Component Configuration is deactivated.

Note:

Usually XML configuration file should be available in OSGI-INF folder in the bundle.
We have to use following header in the bundle MANIFEST file to identify the XML file by OSGi SCR


Service-Component: OSGI-INF/com.liferaysavvy.example.HelloComponent.xml


Service References

Service reference manage the dependencies among the components. Usually OSGi Application development composed of one or more components. Most of the time there will be dependencies between components, it means one component services will be used in other component. Services Reference is the way to identity the other components services and consume in the dependency components.

Usually when we declare components then the service available to all other bundles and it will be automatically managed by Service Component Runtime.

Service reference will help us to identify the exact services in dependency bundles by using some filers and properties.

When we talking about Service Reference we have following terminology comes into picture

Reference:

Reference is definition of dependency to other service. It is key point which explain the component service depends on other component service.

Target Services

Target services is used to identify the exact reference implementation for the given interface configured in the configuration. Target reference will use some properties to filter service and find exact match.

Usually one interface have multiple implementations so to find required implementation from multiple implementation we will use target services to identify and hook the exact match.

 Bound Services

The services that are bound to a Component Configuration. The binding is done on activating a Component Configuration.

Component Lifecycle

We have different types of components available. The following are deferent component types

Delayed Components

Delayed component will not activated until its get first request to service from other component. This we will defined in the component description based on configuration component will ready and services are available to other components.

Immediate Components

Immediate Components will be ready as soon as deployed in the OSGi container. These services immediately available to other components.

Factory Component

Creates and activates new Component Configurations on request. The created Component Configurations are not re-used if they become unsatisfied or unregistered.
The following Lifecycle state possible for each component

ENABLED/DISABLED

Component initial enable state manage by component description. These component state controlled dynamically by using Component Context.

UNSATISFIED

Component will be unsatisfied if the dependency services not resolved. Sometimes dependency services might not be ready component will be in unsatisfied state.

SATISFIED

If component resolved by all dependency services then it will be in satisfied state and it will be ready to use.

RIGISTERED

If the component is satisfied then it will be registered in SCR and these services can be used in other components once it registered.

ACTIVE

Component activation dependent on its type. If the component is declared as immediate component in the component description then services will be in active state. If it is delayed component then it will be get ready once it gets first request to the service object.

Immediate Component Lifecycle


When we deployed the bundle it will be loaded into OSGi container and the bundle is in active state.

Based on Component description Component will be enabled and we already know its immediate component.

If the component reference not resolved then it will goes to UNSATISFIED state.

If the all reference services resolved then it will go to active state then component will be activated.

If any case other references not resolved then it will goes to unsatisfied state and component will be deactivated.

If the bundle is stopped then component will be disabled.

Delayed Components


Delayed component is little different then immediate component.

As soon as bundle started, Based on component description bundle goes to enabled state.
Once all the dependencies resolved then the component will registered with SCR

When the component get first request then component will be in Active state. Usually we will use getService/bind method to get service.

Once it’s in Active state then component will be activated and available to use.

If any case dependences not resolved then it will goes to Deactivate state finally it will be unregistered.

When will call unGetService/Unbind method then Component will goes to registered state. It means component ready to use, when it get requested.

Before Going through implementation please go through following articles to understand develop basic bundles with OSGi framework.


Example Implementation

Step: 1

Service API Bundle

Usually Service API bundle have service interfaces. We need to declare all services in the interface. Once we declared all services then we need to export package to make available to other bundles.

HelloService.java


package com.ls.ds.lsserviceprovider.services;

public interface HelloService {
      public String greetHello();
}


Export Services Package

Now we have to Export Services package from services bundles so that these interfaces or resources can be accessible in the other bundles. Remember here only we are exporting services package not implementation package.

MANIFEST have OSGi header called “Export-Package” and we need to add package names with comma separate value, so that we can access these resources in other bundles.

Add “com.ls.ds.lsserviceprovider.services” package name under “Export-Package” in the 
Bundle MANIFEST file

Finally, MANIFEST looks as follows

MANIFEST.MF


Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: LSServiceProvider
Bundle-SymbolicName: com.ls.de.LSServiceProvider
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.ls.de.lsserviceprovider.ServiceActivator
Bundle-Vendor: LS
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: com.ls.ds.lsserviceprovider.services
Import-Package: org.osgi.framework;version="1.3.0"


Step: 2

Service Provider Bundle

We already have Service API bundle and the services exported. Now we have to implements the service method in the implementation class. Create new bundle and implement the services, which defined in Service API, bundle. Implement interface method in the implementation class, finally implementations class as follows.

HelloServiceImpl.java


package com.ls.ds.lsserviceprovider.services.impl;
import com.ls.de.lsserviceprovider.services.HelloService;
public class HelloServiceImpl implements HelloService
     @Override
      public String greetHello() {
         
        System.out.println("=====Inside HelloServiceImpl.greetHello()=====");
        return "Hello Greeting from Liferay Savvy World..";
     }
}


MANIFEST.MF

To use Service API bundle service interfaces in the Provider bundle we need to import the package in the MANIFEST file with Import-Package Header.


Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: LSServiceProviderImpl
Bundle-SymbolicName: com.ls.de.LSServiceProviderImpl
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: LS
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.ls.ds.lsserviceprovider.services,
 org.osgi.framework;version="1.3.0"
Service-Component:OSGI-INF/com.ls.ds.lsserviceproviderimpl.servicescomponent.xml


Component Declaration

We have to declare component description in services component XML file, which is in bundle OSGI-INF folder. Name can be anything in this case its “com.ls.ds.lsserviceproviderimpl.servicescomponent.xml”

The following is component declaration in the xml file


<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
     name="com.ls.ds.lsserviceprovider.services.impl.HelloServiceImpl">
     <implementation
          class="com.ls.ds.lsserviceprovider.services.impl.HelloServiceImpl" />
     <property name="service.description" value="Sample Hello Service" />
     <property name="service.vendor" value="Liferay Savvy" />
     <service>
           <provide interface="com.ls.ds.lsserviceprovider.services.HelloService" />
     </service>
</scr:component>


Note:

We have many XML tags, which we can find in the SCR XML DTD file.


Step: 3

Service Consumer Bundle

Usually in the Service Consumer bundle, we will use component services, which implemented in the other bundles. In this case, we will use services, which are developed in the Service Provider Bundle. We have to use bind method setXXX() type . If we observed in the below implementation we are using service greetHello that was implemented in other bundle. This is how we can reference one-bundle services in other bundles.

ConsumerComponent.java


package com.ls.ds.consumer.component;
import com.ls.ds.lsserviceprovider.services.HelloService;
public class ConsumerComponent {
   
      public void activate() {
         
           System.out.println("=====Consumer Component Active=====");
     }
      public void setHelloService(HelloService helloService) {
           System.out.println("=====Inside Consumer Component setService()=====");
           System.out.println(helloService.greetHello());    
     }

}


MANIFEST.MF

To use Service API bundle service interfaces in the Provider bundle we need to import the package in the MANIFEST file with Import-Package Header.


Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: LSServiceConsumer
Bundle-SymbolicName: com.ls.ds.ConsumerComponent
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: LS
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.ls.de.lsserviceprovider.services,
 org.osgi.framework;version="1.3.0"
Service-Component:OSGI-INF/com.ls.ds.consumercomponent.xml


Component Declaration

We have to declare component description in services component XML file, which is in bundle OSGI-INF folder. Name can be anything in this case its “com.ls.ds.consumercomponent.xml” to consume other services in the component we have use reference tag. We have to specify the bind method name and service interface in the properties.

The following is component declaration in the xml file


<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
     name="com.ls.ds.ConsumerComponent">
     <implementation class="com.ls.ds.ConsumerComponent" />
     <property name="service.description" value="Sample Consumer Component" />
     <property name="service.vendor" value="Liferay Savvy" />
     <reference bind="setHelloService" cardinality="1..1"
     interface="com.ls.ds.lsserviceprovider.services.HelloService" name="HelloService" policy="static" />
</scr:component>


Note:

We have many XML tags, which we can find in the SCR XML DTD file.


From the three steps, we can understand that how we can implement services and how we can referred into other bundles. This is how declarative services will help share service among bundles.

Important Note

We can implement Declarative Service with help of annotations. XML configuration will be replaced by annotations. So this article will explain how exactly happen when we use Declarative Services.

Author

Popular Posts

Recent Posts

Recent Posts Widget