Difference between revisions of "Steps for Building Declarative Services"

From CDOT Wiki
Jump to: navigation, search
(Created page with '{{Ecl_menu}}__NOTOC__ <h4>1. Study the Interfaces</h4> * [http://www.osgi.org/javadoc/r4v42/org/osgi/framework/Bundle.html Bundle] * [http://www.osgi.org/javadoc/r4v42/org/osgi…')
 
(minor)
 
(4 intermediate revisions by the same user not shown)
Line 3: Line 3:
 
<h4>1. Study the Interfaces</h4>
 
<h4>1. Study the Interfaces</h4>
  
* [http://www.osgi.org/javadoc/r4v42/org/osgi/framework/Bundle.html Bundle]
+
* [http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/osgi/framework/console/package-tree.html Command Interpreter]
* [http://www.osgi.org/javadoc/r4v42/org/osgi/framework/BundleContext.html BundleContext]
+
* [http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/osgi/framework/console/package-tree.html Command Provider]
* [http://www.osgi.org/javadoc/r4v42/org/osgi/framework/BundleActivator.html BundleActivator]
+
 
 
----------
 
----------
 
<h4>2. Define the Bundle Service Interface</h4>
 
<h4>2. Define the Bundle Service Interface</h4>
Line 30: Line 30:
 
}
 
}
 
</source>
 
</source>
 +
 +
<h4>3. Define the Service Descriptor</h4> (the component.xml file)
  
 
The relationships between the interface that is exposed to the client and the implementation that is hidden, must be defined in a xml file:
 
The relationships between the interface that is exposed to the client and the implementation that is hidden, must be defined in a xml file:
Line 43: Line 45:
 
</source>
 
</source>
  
 +
<h4>3. Define the Bundle Consumer Class</h4>
  
 
The bundle consumer must implement the CommandProvider interface
 
The bundle consumer must implement the CommandProvider interface
Line 80: Line 83:
 
}
 
}
 
</source>
 
</source>
 +
 +
<h4>3. Define the Service Descriptor</h4> (the component.xml file)
 +
 +
<source lang="xml">
 +
<?xml version="1.0"?>
 +
<component name="singlesayconsumer">
 +
    <implementation class="cs.ecl.osgi.simple.declarativeservice.consumer.SaySingleConsumer"/>
 +
    <service>
 +
        <provide interface="org.eclipse.osgi.framework.console.CommandProvider"/>
 +
    </service>
 +
    <reference name="SAYABLE"
 +
        interface="cs.ecl.osgi.simple.declarativeservice.say.Sayable"
 +
        bind="bindSayable"
 +
        unbind="unbindSayable"
 +
        cardinality="0..1"
 +
        policy="dynamic"/>
 +
</component>
 +
</source>
 +
 +
The '''reference''' element in the service descriptor specifies that:
 +
* The component has a binding to a service, and the name of the binding is set to "SAYABLE"
 +
* The needed service is one which implements the "cs.ecl.osgi.simple.declarativeservice.say.Sayable" interface
 +
* To bind this component with a provider of the service, the framework must invoke the "bindSayable" method
 +
* Similarly, to unbind the component from a provider, the framework must invoke the "unbindSayable" method
 +
* The '''cardinality''' parameter has the form "'''x..y'''", where x can be either '0' or '1' and y can be either '1' or 'n'. The first parameter specifies '''optionality''', and the second one specifies '''multiplicity'''.
 +
** For instance, x='0' means that a binding to the service is optional, while x='1' means that the binding is mandatory (otherwise the component can not be resolved and activated).
 +
** On the other hand, y='1' implies single binding only, where the component can only be bound to just one service provider at a time, while y='n' implies that multiple service providers can be bound to the component simultaneously.
 +
* The last parameter, '''policy''', can be set to either "dynamic" or "static". This controls the binding to new service providers at runtime.
 +
** When the value is set to "static", then it is implied that the component cannot handle dynamic switching of service providers and thus the framework constructs a new instance of the component when the service provider changes.
 +
** On the other hand, when the policy is set to "dynamic", then the binding and unbinding of service providers takes place dynamically on the same component instance. As the former is more heavy-weight, it is recommended that the components are designed and implemented so that they support the dynamic policy. The default value is "static", which means that unless you specify the policy parameter as "dynamic", it is going to be set as "static".

Latest revision as of 22:19, 8 February 2011

1. Study the Interfaces


2. Define the Bundle Service Interface

package cs.ecl.osgi.simple.declarativeservice.say;

public interface Sayable {
	String say();
}

An implementation of this interface could be:

package cs.ecl.osgi.simple.declarativeservice.say.internals;
import java.util.Date;
import cs.ecl.osgi.simple.declarativeservice.say.Sayable;

public class TodaySay implements Sayable {
	public String say() {
		return " Declarative Service: Today is " + new Date();
	}
}

3. Define the Service Descriptor

(the component.xml file)

The relationships between the interface that is exposed to the client and the implementation that is hidden, must be defined in a xml file:

<?xml version="1.0"?>
<component name="sayable">
	<implementation class="cs.ecl.osgi.simple.declarativeservice.say.internals.TodaySay"/>
	<service>
		<provide interface="cs.ecl.osgi.simple.declarativeservice.say.Sayable"/>
	</service>
</component>

3. Define the Bundle Consumer Class

The bundle consumer must implement the CommandProvider interface

package cs.ecl.osgi.simple.declarativeservice.consumer;

import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.eclipse.osgi.framework.console.CommandProvider;

import cs.ecl.osgi.simple.declarativeservice.say.Sayable;

public class SaySingleConsumer implements CommandProvider {

	private Sayable s;

	public synchronized void bindSayable(Sayable s) {
		this.s = s;
	}

	public synchronized void unbindSayable(Sayable s) {
		this.s = null;
	}

	public synchronized void _run(CommandInterpreter ci) {
		if (s != null) {
			System.out.println(s.say());
		} else {
			ci.println("Error, No Service of type Sayable available");
		}
	}

	@Override
	public String getHelp() {
		return "\n\t run - EXECUTE the Sayable service";
	}
}

3. Define the Service Descriptor

(the component.xml file)
<?xml version="1.0"?>
<component name="singlesayconsumer">
    <implementation class="cs.ecl.osgi.simple.declarativeservice.consumer.SaySingleConsumer"/>
    <service>
        <provide interface="org.eclipse.osgi.framework.console.CommandProvider"/>
    </service>
    <reference name="SAYABLE"
        interface="cs.ecl.osgi.simple.declarativeservice.say.Sayable"
        bind="bindSayable"
        unbind="unbindSayable"
        cardinality="0..1"
        policy="dynamic"/>
</component>

The reference element in the service descriptor specifies that:

  • The component has a binding to a service, and the name of the binding is set to "SAYABLE"
  • The needed service is one which implements the "cs.ecl.osgi.simple.declarativeservice.say.Sayable" interface
  • To bind this component with a provider of the service, the framework must invoke the "bindSayable" method
  • Similarly, to unbind the component from a provider, the framework must invoke the "unbindSayable" method
  • The cardinality parameter has the form "x..y", where x can be either '0' or '1' and y can be either '1' or 'n'. The first parameter specifies optionality, and the second one specifies multiplicity.
    • For instance, x='0' means that a binding to the service is optional, while x='1' means that the binding is mandatory (otherwise the component can not be resolved and activated).
    • On the other hand, y='1' implies single binding only, where the component can only be bound to just one service provider at a time, while y='n' implies that multiple service providers can be bound to the component simultaneously.
  • The last parameter, policy, can be set to either "dynamic" or "static". This controls the binding to new service providers at runtime.
    • When the value is set to "static", then it is implied that the component cannot handle dynamic switching of service providers and thus the framework constructs a new instance of the component when the service provider changes.
    • On the other hand, when the policy is set to "dynamic", then the binding and unbinding of service providers takes place dynamically on the same component instance. As the former is more heavy-weight, it is recommended that the components are designed and implemented so that they support the dynamic policy. The default value is "static", which means that unless you specify the policy parameter as "dynamic", it is going to be set as "static".