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
0 comments :
Post a Comment