Service Component Runtime

This document describes the set of functions provided by the Service Component Runtime bundle. It also contains a developer's guide to managing services by the means defined in the OSGi Declarative Services Specification Release 4.

Contents:


Bundle Information

Bundle JAR

The JAR file of the Service Component Runtime bundle is scr.jar, located in the bundles directory.

Import

Package Exporter Description
org.osgi.service.cm Contains interfaces for administering, processing and receiving configuration data as defined in the OSGi Configuration Admin Service Specification. These interfaces are implemented by the Config Bundle.
org.osgi.service.component Contains the Service Component API for using the Declarative Services model.
org.osgi.util.tracker Provides a utility, defined by the OSGi Service Tracker Specification, which simplifies using services from the Framework's service registry.
org.mbs.services.metatype Provides the ProSyst Metatype API, including the Metadata Manager service and an extended API for developing new metatypes.
com.prosyst.util.ref
ProSyst Util Bundle/
ProSyst Util Full Bundle
Holds the log utility that stores log messages about the runtime status of a bundle.
com.prosyst.util.xml Contains classes for reading and processing XML documents.
com.prosyst.util.threadpool Provides the Thread Pool Manager service that maintains a pool of reusable threads to execute runnable jobs.
com.prosyst.util.timer Holds the Timer service that sends notification after a specified period of time.
com.prosyst.util.pool
System Bundle/
ProSyst Util Full Bundle
Holds the object pool utility for reusing objects.
com.prosyst.util.io Provides I/O utilities for object serialization.
com.prosyst.util.hash Contains utilities for using long and integer numbers in hashtables.
com.prosyst.mbs.framework.event Provides the Event Thread utility for asynchronous event delivering and listener management.
com.prosyst.mbs.framework.access Holds the Framework Access service for accessing some of the specific features of the mBS framework.
com.prosyst.mbs.services.db Provides the DB service, used for persistent data storage.

Export

None.


Overview

The Service Component Runtime bundle provides implementation of the Service Component Runtime according to the OSGi Declarative Services Specification Release 4.

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:

Service Component

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.

Service Component Runtime

The Service Component Runtime (SCR) is the module that manages the components and their lifecycle. It performs the following functions:

Component Context

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.

Component Description

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:

Component Factories

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:

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.

Component Properties

A component can have a set of properties specified in three places in the following order of precedence:

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.


Service Component API

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.


Creating a Component

To create a component, write its implementation Java class and component description then pack them into a bundle JAR file.

Component Description Manifest Header

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

Component Description Elements

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.


Providing a Service

To create a component that provides a service, you have to go through the following stages:

  1. Write the service interface.

    package simple.service;
    
    public interface HelloService {
    	
      public void hello();
    }
    Listing 1:HelloService interface

  2. Write the service interface implementation class which will be the component's implementation class as well:

    package simple.service.impl;
    import simple.service.HelloService;
    
    public class HelloServiceImpl implements HelloService {
    
      public void hello() {
    			
         System.out.println("Hello components!");
      }
    }
    Listing 2: HelloService implementation class.

  3. Write the component description.

    <?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>
    Listing 3: HelloServiceComponent XML description


Referencing a Service

A component can reference services provided by other components or bundles in the framework by using one of the following models:

Lookup Model

To reference a service using this model:

  1. Write a reference element in the component's description to declare the referenced service(s).
  2. Get the component's ComponentContext object allocated to the instance of your component's class, passed as an argument to the component's activate method.
  3. Call the 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;
  }
}
Listing 4: Referencing a service using the Lookup model.

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>
Listing 5: HelloServiceReference class component description.


Event Model

To obtain a service using this model:

  1. Write bind and unbind methods.
  2. Declare them in the reference element of the component description.
  3. Pass the referenced service as on 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;
  } 
}
Listing 6: Referencing a service using the Event model

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>
Listing 7: HelloServiceBind component component description


Using the Component Factory service

To use the Component Factory service:

  1. Define the component you want to produce multiple instances of as a factory component. To define a component as a factory component, declare a factory="<factory_name>" attribute in the component element of its description.
  2. Declare component properties in the component's description that will be passed to the Component Factory service when creating new instances of the same component type. Component properties are declared in property or properties elements as described in the "Component Description Elements" section.
  3. Get the Component Factory OSGi service and call its 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;
 }
}
Listing 8: The implementation class of the Hello Service

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>
Listing 9: A component description of a factory 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;
   }

}
Listing 10: Creating a factory component instance

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>
Listing 11: The HelloComponentFactoryRef component description


Using a Service Factory

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="<service_factory_name>" attribute in the service element of the component's description. For example:

<service servicefactory="hello.factory">


Providing Configurable Component Properties

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>
Listing 11: Providing a component's configuration data

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.


System Properties

System Property Default Value Description
mbs.component.debug false Turns on/off debugging of SCR.
mbs.component.print false Specifies that logged entries should be printed to the framework runtime console.
mbs.component.idle_timeout
1000
Specifies the time in milliseconds after which the SCR working thread will be terminated if the SCR has no operations to perform.
mbs.component.dbstore false Enables storing the parsed XML documents of the component descriptions in the system database.
mbs.component.perf false Enables generating and printing logs about the time performance of the operations executed by the SCR.
mbs.component.block_timeout
30000
Specifies the maximum time in milliseconds, which is allowed to a user component's activate or bind method to take. If the method invocation has not finished, a new dispatcher thread will be launched to process the pending work of SCR.
mbs.scr.dontDisposeInstances
false
Turns on/off disposing of component instances that are no longer used.


References


OSGi Bundles