This document describes the set of functions provided by the Service Component Runtime Bundle. It also contains a developer's guide to managing OSGi services by the means defined in the OSGi Declarative Services Specification Release 4.2.
Contents:
The JAR file of the Service Component Runtime bundle is fw.scr.jar , located in the bundles directory.
The symbolic name of the Service Component Runtime bundle is com.prosyst.mbs.scr .
|
None.
The Service Component Runtime bundle provides an implementation of the Service Component Runtime according to the OSGi Declarative Services Specification Release 4.2.
The specification defines a declarative model of using OSGi services that allows delaying the creation of the service object till the moment it will be actually used. Using the declarative services model provides the following benefits:
The declarative services model defines a service component as main unit for manipulating with OSGi services functionality.
A service component is an entity consisting of a Java class and its XML description, which can register or reference a service in a lazy fashion. Both, service component's Java class and its description are packed in a bundle that is deployed in the OSGi framework where it functions like any traditional OSGi bundle.
A service component has the following features:
A service component will be referred to as component and its XML description as component description from now on in this document.
The Service Component Runtime (SCR) is the module that manages the components and their lifecycle. It performs the following functions:
A component may receive its Component Context through its activate
method. Component Context can be used to locate services declared in
the component's description. It can be used also to enable or disable
components from the component's bundle.
The declaration of a component in an XML format is the component description . It uniquely identifies the component to the SCR and provides information about the component's functionality that will be used by the SCR to perform its management operations.
The component description provides information for:
The declarative services model supports producing multiple instances of the same component type in compliance with the Service Factory concept in the OSGi framework.
Multiple instances of same component type can be produced by:
org.osgi.framework.ServiceFactory
.
It will produce new instances of the component for each referencing bundle
or component. The properties of the service provided by the component will
be the same for all newly produced component instances.Note: A component cannot be declared as a factory component and use a Managed Service Factory and Service Factory at the same time. You have to choose only one of these factories to produce new instances of the same component type.
A component can have a set of properties specified in three places in the following order of precedence:
newInstance
method of the Component Factory service. New component properties can be passed to this method, as well. Each component also has COMPONENT_NAME
property defined in its description and COMPONENT_ID
property given by the SCR. These properties are obligatory and their
values cannot be overridden as they uniquely identify the component to
the SCR.
The Service Component API is contained in the org.osgi.service.component
package. It is a lightweight API that defines base interfaces for using components.
To create a component, write its implementation Java class and component description then pack them into a bundle JAR file.
A bundle providing a component must have special header in its manifest that specifies the XML document of the component description:
Service-Component: <path to the XML document's location>
For example:
Service-Component: myComponent/ComponentDescriptionXML.xml
The elements included in a component description vary depending on the functionality a component provides.
Generally, the possible elements of a component description are:
For further information on the component description elements, refer to the component description schema provided in the OSGi Declarative Services Specification Release 4. .
To create a component that provides a service, you have to go through the following stages:
package simple.service;
public interface HelloService {
public void hello();
}
|
package simple.service.impl;
import simple.service.HelloService;
public class HelloServiceImpl implements HelloService {
public void hello() {
System.out.println("Hello components!");
}
}
|
<?xml version="1.0" encoding="UTF-8"?> < scr:component name =" HelloServiceComponent" xmlns:scr =" http://www.osgi.org/xmlns/scr/v1.0.0"> <!-- The component's implementation class--> <implementation class =" simple.service.impl.HelloServiceImpl"/> < service > <!--The interface of the service provided by the component--> < provide interface =" simple.service.HelloService"/> </ service > </scr:component> |
A component can reference services provided by other components or bundles in the framework by using one of the following models:
locateService
or locateServices
methods of the ComponentConext
object provided to your component's Java class. The locateService(s)
method allows a component to "look up" the services it needs
instead of keeping their objects. This model is suitable for referencing services
with dynamic behavior.ServiceReference
. The binding and unbinding
methods are declared in the reference
element of the component's description. To reference a service using this model:
ComponentContext
object allocated to the
instance of your component's class, passed as an argument to the component's
activate
method.locateService
or locateServices
method
of the ComponentContext
.The code example snippet below contains a component's implementation class which references the service provided by the component introduced in the "Providing a Service " section.
package simple.service.reference;
import org.osgi.service.component.ComponentContext;
import simple.service.HelloService;
public class HelloServiceReference {
protected ComponentContext context;
HelloService helloService;
protected void activate(ComponentContext ctxt){
this.context = ctxt;
helloService = (HelloService) ctxt.locateService("helloService");
helloService.hello();
}
protected void deactivate(ComponentContext ctxt){
this.context = null;
}
}
|
And the component description:
<?xml version="1.0" encoding="UTF-8"?> < scr:component name =" HelloServiceReference" xmlns:scr =" http://www.osgi.org/xmlns/scr/v1.0.0"> <implementation class =" simple.service.reference.HelloServiceReference"/> < reference name =" helloService" interface =" simple.service.HelloService" /> </ scr:component > |
To obtain a service using this model:
The SCR passes the referenced service as an argument of the bind and unbind methods.
The listing below contains a class which implements bind (setHelloService
)
and unbind (unsetHelloService
) methods to obtain the service provided
by the component introduced in the "Providing a Service
"
section:
package simple.service.reference;
import simple.service.HelloService;
public class HelloServiceBind {
HelloService helloService;
public void setHelloService(HelloService helloService){
this.helloService = helloService;
helloService.hello();
}
public void unsetHelloService(HelloService helloSerivce){
this.helloService = null;
}
}
|
The XML description of the HelloServiceBind
class:
<?xml version="1.0" encoding="UTF-8"?> < scr:component name =" HelloServiceBind" xmlns:scr =" http://www.osgi.org/xmlns/scr/v1.0.0"> <implementation class =" simple.service.reference.HelloServiceBind"/> < reference name =" helloService" interface =" simple.service.HelloService" bind =" setHelloService" unbind =" unsetHelloService" /> </ scr:component > |
To use the Component Factory service:
newInstance
method by providing some custom properties. The Component Factory, that the SCR creates and associates with the component definition, can create multiple instances if the component is satisfied. If the a factory component's dependencies are not met, the component is disposed and the Component Factory service is unregistered.
If the factory component is supposed to provide a service, a service object
will be registered on its behalf each time the newInstance
method
of the associated ComponentFactory
is called.
Following is the implementation class of a factory component that provides
the Hello Service introduced in the "Providing a Service
"
section. For simplicity, the service's hello
method is called in
the component's activate
method:
package simple.service.impl;
import org.osgi.service.component.ComponentContext;
import simple.service.HelloService;
public class HelloServiceImpl implements HelloService {
ComponentContext context;
protected void activate(ComponentContext ctxt){
this.context = ctxt;
hello();
}
public void hello() {
System.out.println("Hello components!");
}
protected void deactivate(ComponentContext ctxt){
this.context = null;
}
}
|
And the component description where the component is declared as a factory component:
<?xml version="1.0" encoding="UTF-8"?> < scr:component name =" HelloComponentFactory" factory =" hello.component.factory" xmlns:scr =" http://www.osgi.org/xmlns/scr/v1.0.0"> <implementation class =" simple.service.impl.HelloServiceImpl"/> < service > < provide interface =" simple.service.HelloService"/> </ service > < property name =" Prop1" value =" init value"/> < property name =" Prop2" type =" Integer" value =" 0"/> </ scr:component > |
The next example is a component which gets the Component Factory service and creates an instance of the factory component from the previous example:
package simple.component.factory;
import java.util.Hashtable;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.ComponentFactory;
import org.osgi.service.component.ComponentInstance;
public class HelloComponentFactoryRef {
ComponentContext context;
ComponentFactory factory;
ComponentInstance compInstance;
Hashtable factoryProps;
public void setFactory(ComponentFactory cmpFact){
this.factory = cmpFact;
factoryProps = new Hashtable();
factoryProps.put("Prop1","new value");
factoryProps.put("Prop2",new Integer(20));
compInstance = factory.newInstance(factoryProps);
}
public void unsetFactory(ComponentFactory cmpFact){
this.factory = null;
}
}
|
The next listing contains the component description of the SimpleComponentFactoryRef
component. Its reference
element includes a target
attribute who's value is an LDAP filter that constrains the referenced
Component Factory services to the one associated with the SimpleComponent
component. The filter is in (component.factory=<component factory name>)
format.
<?xml version="1.0" encoding="UTF-8"?> < scr:component name =" HelloComponentFactoryRef" xmlns:scr =" http://www.osgi.org/xmlns/scr/v1.0.0"> < implementation class =" simple.component.factory.HelloComponentFactoryRef"/> < reference name =" ComponentFactoryRef" interface =" org.osgi.service.component.ComponentFactory" bind =" setFactory" unbind =" unsetFactory" target =" (component.factory=hello.component.factory)" /> </ scr:component > |
To create unique instances of a component-providing service for each bundle referencing the service over the traditional OSGi Framework API or by using another service component, declare a servicefactory="true" attribute in the service element of the component's description like this:
<service servicefactory="true">
To make a component's properties configurable through the Configuration Admin, write a metatype XML resource to export them as metadata as defined in the OSGi Metatype Service Specification, linking the defined metatype with the component name. Then, create the component configuration in the Configuration Admin using the component name as the configuration PID.
The example that follows is an XML document providing the metadata of a component's properties. Their IDs must be same as their names declared in the component description:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> < metatype:MetaData xmlns:metatype =" http://www.osgi.org/xmlns/metatype/v1.0.0" xmlns:xsi =" http://www.w3.org/2001/XMLSchema-instance"> <OCD name =" Hello Component Config" id =" ocd1"> < AD name =" Property One" id =" Prop1" type =" String" default =" init value"/> < AD name =" Property Two" id =" Prop2" type =" Integer" default =" 0"/> </ OCD > < Designate pid =" HelloServiceComponent"> < Object ocdref =" ocd1"/> </ Designate > </ metatype:MetaData > |
If you want to produce and preconfigure multiple component instances, set the factory attribute of the Designate element to true to indicate that this metatype will be for a Managed Service Factory.
The Services Component Runtime bundle registers a com.prosyst.util.pcommands.PluggableCommands
service that provides the console commands of the scr
group. Refer to the "Console Commands
" section for description of the scr
command.
The Services Component Runtime bundle provides the scr group of commands in the framework text console for executing operations over the components available in the framework. The scr command group is enabled only when there are instantiated components in the framework.
|
|