16 KiB
layout | title |
---|---|
developersguide | Coding tasks for OSGi |
{% include base.html %}
Coding tasks for OSGi
Introduction
OSGi coding tasks can help Java developers with no experience in OSGi and Eclipse Plug-in development to get familiar with writing bundles. This page contains tasks, related to several fundamental topics, and references to tutorials, where similar tasks are implemented.
Prerequisites
Before you start, you should first install the Eclipse IDE.
In order to run your samples in an OSGi Runtime you might want to start Equinox in a command line.
You might take a look at the Coding Guidelines as well.
Tasks
The tasks are divided in several sections:
{::options toc_levels="3"/}
- TOC {:toc}
Sample implementations are present in the openHAB docs repo.
I. Writing basic OSGi bundle
-
Create an
org.openhab.training.helloosgi
bundle, that prints a message on the console, when it is started and stopped. Test it in the OSGi Container.Hint! You can install a bundle in the OSGi Container with the
install {url}
command.
Hint! If you still have difficulties look at the reference section. -
Create an
org.openhab.training.utils
bundle, which contains classTimeUtilities
, that has a single methodString getCurrentTimeStamp()
that returns the current time stamp in format "hh:mm". Mind theTimeUtilities
class might be used in some other bundles.Hint! Find out how can you export packages in OSGi.
-
Create an
org.openhab.training.helloosgi.modified
bundle to use theTimeUtilities
class to display the current time stamp on the console when it is started.
II. Services
-
Create an
org.openhab.training.electricity.provider
bundle, which defines a service interfaceElectricityProvider
with one method:boolean provide (int value)
- discharges the provider with the 'value' parameter. It should return true, if the requested charge is available in the provider and false, if it is not;
-
Create an
org.openhab.training.electricity.homenetwork
bundle:- with
HomeElectricityNetwork
implementation of theElectricityProvider
interface with infinite charge (theprovide()
method should always return true); - which registers the
HomeElectricityNetwork
asElectricityProvider
in the OSGi Service Registry with BundleContext.
Hint! You can find similar tasks in the examples below.
- with
-
Create an
org.openhab.training.electricity.consumer
bundle, which contains an interfaceElectricityConsumer
with methods:void startConsuming()
- starts the device and displays a message on the console. If the device requires a provider (it is not energy independent), this method can set the current provider. After the device is started it should try to consume electricity equal to the device consumption from the current provider at fixed interval from 5 seconds and display a message on the console, which provider is in use at the moment;void stopConsuming()
- stops the device and displays message on the console. The device should not consume electricity anymore. The device should stop, if the current provider is discharged;void setCurrentProvider(ElectricityProvider)
- sets a current provider from a list with available providers;List<ElectricityProvider> getAllAvailableProviders()
- returns a list with available providers (a provider is available, when it is registered in the Service Registry and has more charge, than the device consumption).
-
Create an
org.openhab.training.electricity.radio
bundle, which:- implements the
ElectricityConsumer
interface in aBasicRadio
consumer, which has specific consumption (e.gint consumption = 5
) and can be connected to only one provider; - the device should be able to stop automatically, when there is no provider available and display a message on the console. After that it must be started manually;
- use the
ElectricityProvider
service by getting it directly from the BundleContext.
- implements the
III. Service Tracker
-
Create an
org.openhab.training.electricity.battery
bundle, which implements and registersBattery
implementation of theElectricityProvider
service with finite charge (e.gint capacity = 20
).Hint! An ElectricityProvider can be used by different consumers simultaneously. Consider whether it is necessary to make an implementation of this class thread-safe.
-
Create an interface
DynamicConsumer
in anorg.openhab.training.electricity.dynamicconsumer
bundle that should manage the availability of the differentElectricityProvider
. It defines two methods:void providerAdded(ElectricityProvider)
- called when a new provider is registered in the ServiceRegistry. It should add the provider in a list with available electricity sources for the current device;void providerRemoved(ElectricityProvider)
- called when a provider is unregistered from the ServiceRegistry. It should remove the provider from a list with available electricity sources for the current device.
-
Create a
TV
consumer withint consumption = 10
, that implements theElectricityConsumer
interface and theDynamicConsumer
interface in anorg.openhab.training.electricity.tv
bundle by using ServiceTracker. TheTV
should be able to dynamically switch between differentElectricityProvider
:- when both providers are available, it should work with the
HomeElectricityNetwork
; - otherwise it should use the provider that is available at the moment;
- when no provider is available or it can not provide enough charge, the
TV
should stop; - it should be able to start automatically, if a new provider is available and is able to provide enough electricity.
Hint! Install
org.eclipse.osgi.util
bundle in order to use ServiceTracker. Tutorials with examples can be found below. - when both providers are available, it should work with the
IV. Declarative Services and Components
-
Provider and consumer:
- rewrite all tasks in section II. and III. to use the
ElectricityProvider
service by injecting it by the means of Declarative Services (do not use Service Tracker and BundleContext).The name of the new bundles will be the same, but ending with a .ds (e.g.org.openhab.training.electricity.tv.ds
);
Hint! Install
org.eclipse.equinox.ds
bundle in order to use Declarative Services. - rewrite all tasks in section II. and III. to use the
-
Create a
SolarRadio
consumer that extendsBasicRadio
from IV.1 in anorg.openhab.training.electricity.solarradio
bundle. This radio does not need anyElectricityProvider
to run, but will use one, if it is available (the device should not stop when there are no providers available).Hint! Read about cardinality in OSGi Declarative Services!
-
Create a
CombinedSolarRadio
that extendsSolarRadio
and implementsDynamicConsumer
inorg.openhab.training.electricity.combinedradio
it the following way:- the consumer does not need any provider to run;
- if one is available, it must set it as current and use it;
- if more than one are available, add all to the list with available providers.
Hint! What happens when you stop the provider that is not in use? Why does the
CombinedSolarRadio
stops and starts? Modify the consumer to handle the removal of the service dynamically - without calling the stop and start methods every time! Read about service policy in OSGi!Hint! Test all the bundles in the OSGi container by starting and stopping the different
ElectricityProvider
implementations and track, if the consumers are used as expected.
V. Events
-
Create a bundle
org.openhab.training.util.sender
that registers as a serviceTimeEventSender
, that sends events with topic "org/openhab/training/time" every minute with the current time stamp (hh:mm) (you can use theTimeUtilities
class from chapter I.).Hint! Install
org.eclipse.equinox.event
bundle in order to use EventAdmin service for sending events.
Hint! ScheduledExecutorService can be used in this task. -
Extend the
org.openhab.training.electricity.tv.ds.TV
class from IV.1 in anorg.openhab.training.electricity.tv.events
bundle to listen for events and print them on the console.
VI. Managed Services
-
Implement the ManagedService interface in the
org.openhab.training.electricity.tv.events
bundle and:- add a configuration to the
TV
class with property "autoSleep" and value a timestamp (hh:mm); - modify the method that listens for events with topic "time" to stop the bundle, when the "autoSleep" property is equal to the "time" topic.
- add a configuration to the
-
Create another implementation of the
ElectricityProvider
interface (RechargableBattery
) in anorg.openhab.training.electricity.rechargeablebattery
bundle that:- has a finite charge (e.g
int capacity = 30
); - implements the ManagedService interface. After this modification, it should be possible to change the charge of a battery with a
setCharge(int capacity)
method;
Hint! Read about the ConfigurationAdmin service and how you can use it to change the configuration of a ManagedService. You might want to implement additional bundle that is using the ConfigurationAdmin service to change the configuration of the battery to perform a quick test.
Hint! Install
org.eclipse.equinox.cm
bundle in order to use ConfigurationAdmin service. - has a finite charge (e.g
-
Create a
org.openhab.training.electricity.recharger
bundle that will wait 10 seconds after it is activated and will recharge a rechargeable battery if it is registered as a service.
VII. Console Commands
-
Implement a service in the
org.openhab.training.util.console
bundle that adds console command, that:- displays all
ElectricityProvider
implementations that are registered with their charge; - displays all consumers, to which providers are they connected (which providers are available) and what is the current provider at the moment;
Hint! You might have to register all consumers as services in the OSGi ServiceRegistry.
- sets the charge of the
RechargableBattery
to a provided value; - changes the configuration of the
TV
.
Hint! You can add console commands with the help of CommandProvider
Hint! Test the console commands in the OSGi runtime by starting the different Radio consumers and the TV consumer. Start only the
Battery
provider and wait until it is discharged. Check if the consumers have stopped as expected. Recharge the battery and check, if the consumers have started. You can try out different scenarios as well! - displays all
References
Some of the tutorials listed below are not up-to-date with the latest versions of the Equinox framework or are written to be run in another implementation of the OSGi Runtime (e.g. Apache Felix). They can help you with solving the tasks above. This resources are divided in several groups.
Multiple topics
{:.no_toc}
- This tutorials simply cover more than one from the topics below:
Writing basic OSGi bundle
{:.no_toc}
- This tutorials are focused on writing basic bundle, managing the dependencies between the bundles and running them in an OSGi container:
Services
{:.no_toc}
- Registering and using Services with the low-level OSGi API:
- Getting started with OSGi: Registering a Service;
- Getting started with OSGi: Consuming a Service;
- Apache Felix Tutorial: A bundle that listens for OSGi service events;
- Apache Felix Tutorial: A bundle that implements a dictionary service;
- Apache Felix Tutorial: A bundle that implements another dictionary service;
- Apache Felix Tutorial: A bundle that implements a simple dictionary service client;
- Apache Felix Tutorial: A bundle that implements a more robust dictionary service client.
Service Trackers
{:.no_toc}
- OSGi Service Tracker simplifies using services from the Framework's registry. You can find example usage in the links below:
- Getting started with OSGi: Dynamic Service Tracking;
- Apache Felix Tutorial: A bundle that implements a dictionary service client using the Service Tracker;
- Apache Felix Tutorial: A bundle that implements a spell checker service using dictionary services.;
- Apache Felix Tutorial: A bundle that implements a spell checker service client;
- OSGi - ServiceTracker - ServiceTrackerCustomizer.
Declarative Services and Components
{:.no_toc}
- OSGi Declarative Services is a high level API for managing services in OSGi. Its functionality is widely used in the openHAB project. Tutorials about the topic:
Managed Services
{:.no_toc}