blob: 000d7e7dd2adba3ef0bba7f5e14c49c9a107d8ca [file] [log] [blame]
This sample illustrates the usage of the new DependencyManager annotations.
Sample description:
==================
This sample shows a basic "SpellChecker" application which provides a Felix "spellcheck" GOGO shell
command. The GOGO "spellcheck" command accepts a string as parameter, which is checked for proper
existence. The SpellChecker class has a required/multiple (1..N) dependency over every available
"DictionaryService" services, which are internally used by the SpellChecker command, when checking
word existence.
A DictionaryService is defined using a FactoryConfigurationAdapterService annotation, allowing to
instantiate many "DictionaryService" instances from webconsole. This annotation actually registers a
ManagedServiceFactory into the Registry, and you can specify some meta type informations in the
annotation, allowing to configure the DictionaryService words and language from WebConsole. Each
time you instantiate a factory configuration whose factory pid equals "DictionaryImplFactoryPid",
in the webconsole "Dictionary Services" configuration section, then a corresponding "DictionaryImpl"
component is instantiated and is then injected into the SpellChecker service. So, before testing,
you first have to go to webconsole Configuration panel, and specify some dictionaries (see the
"Dictionary Services" section). Then, go to the felix GOGO shell, and you will then see the
"spellcheck" command (when typing "help").
Notice that in the sample, you will also find a DictionaryAspect Service (DictionaryAspect.java),
which decorates the EnglishDictionary service, by adding some additional words to it.
How to test:
===========
1) Install the following bundles (with same or higher version):
org.apache.felix.configadmin-1.2.8.jar
org.apache.felix.metatype-1.0.4.jar
org.apache.felix.http.jetty-2.2.0.jar
org.apache.felix.webconsole-3.1.8.jar
org.apache.felix.shell-1.4.2.jar
org.apache.felix.dependencymanager-3.0.0.jar
org.apache.felix.dependencymanager.shell-3.0.0.jar
org.apache.felix.dependencymanager.runtime-3.0.0.jar
org.apache.felix.log-1.0.1.jar (optional)
2) compile dependency manager sample.annotation from trunk:
svn checkout http://svn.apache.org/repos/asf/felix/trunk/dependencymanager dependencymanager
cd dependencymanager/sample.annotation
mvn clean install
Then install ./target/org.apache.felix.dependencymanager.samples.annotation-3.0.0-SNAPSHOT.jar into
felix.
3) Start felix
At this point, you should have the following running bundles:
g! lb
START LEVEL 1
ID|State |Level|Name
0|Active | 0|System Bundle (3.2.1)
1|Active | 1|Apache Felix Bundle Repository (1.6.2)
2|Active | 1|Apache Felix Configuration Admin Service (1.2.8)
3|Active | 1|Apache Felix Dependency Manager (3.0.0)
4|Active | 1|Apache Felix Dependency Manager Runtime (3.0.0)
5|Active | 1|Apache Felix Dependency Manager Annotation Sample (3.0.0.SNAPSHOT)
6|Active | 1|Apache Felix Dependency Manager Shell (3.0.0)
7|Active | 1|Apache Felix Gogo Command (0.8.0)
8|Active | 1|Apache Felix Gogo Runtime (0.8.0)
9|Active | 1|Apache Felix Gogo Shell (0.8.0)
10|Active | 1|Apache Felix Http Jetty (2.2.0)
11|Active | 1|Apache Felix Log Service (1.0.1)
12|Active | 1|Apache Felix Metatype Service (1.0.4)
13|Active | 1|Apache Felix Shell Service (1.4.2)
14|Active | 1|Apache Felix Web Management Console (3.1.8)
4) Inspect Dependency Manager components from gogo shell:
type "dm 5" for browsing the components for the bundle id 5
[5] org.apache.felix.dependencymanager.samples.annotation
org.osgi.service.cm.ManagedServiceFactory(service.pid=DictionaryImplFactoryPid) registered
org.osgi.service.log.LogService service optional available
org.apache.felix.dm.samples.annotation.SpellChecker(osgi.command.function={spellcheck},osgi.command.scope=dmsample.annotation) unregistered
org.apache.felix.dm.samples.annotation.DictionaryService service required unavailable
org.osgi.service.log.LogService service optional unavailable
org.apache.felix.dm.impl.AspectServiceImpl$AspectImpl@4d76b4 unregistered
org.apache.felix.dm.samples.annotation.DictionaryService (&(!(org.apache.felix.dependencymanager.aspect=*))(lang=en)) service optional unavailable
DictionaryAspectPID configuration required unavailable
org.osgi.service.log.LogService service optional unavailable
Here, the bundle [5] corresponds to our annotation.sample bundle. In this bundle, we have three
components:
* org.osgi.service.cm.ManagedServiceFactory: this is the service DM has internally registered in
order to be able to instantiate some of our "DictionaryImpl" component instances from config
admin (using the factory pid "DictionaryImplFactoryPid"). See DictionaryImpl.java and especially
the @FactoryConfigurationAdapterService annotation. The component depends on the log service
because our "DictionaryImpl" component also depends on the log service. The ManagedServiceFactory
is actually depending on all dependencies defined in our "DictionaryImpl" component, and those
dependencies will be applied on each instantiated DictionaryImpl component instances.
* org.apache.felix.dm.samples.annotation.SpellChecker: This is our "SpellChecker" component exposing
two services properties: "osgi.command.function" (the gogo shell method name), and
"osgi.command.scope" (the gogo command scope).
It also has two dependencies: "org.apache.felix.dm.samples.annotation.DictionaryService", and
"org.osgi.service.log.LogService".
* org.apache.felix.dm.impl.AspectServiceImpl$AspectImpl: this is also an internal service registered
by dependency manager, in order to instantiate our "DictionaryAspect" interceptor service. See
DictionaryAspect.java. The aspect impl depends on the three dependencies (which are initially
defined in DictionaryAspect.java):
- org.apache.felix.dm.samples.annotation.DictionaryService: this is the service our DictionaryAspect
is intercepting. The AspectServiceImpl$AspectImpl will create a DictionaryAspect instance for
every DictionaryService found from the OSGi registry (that is, for every DictionaryService you
create from web console "Dictionary Services" configuraton section).
- DictionaryAspectPID configuration: this is the config pid our DictionaryAspect is depending on (see
@ConfigurationDependency in DictionaryAspect.java).
- org.osgi.service.log.LogService: the DictionaryAspect is optionally depending on the log service
(a null object is used if there is no one).
So, when a DictionaryService will come up, the AspectServiceImpl component will instantiate a
corresponding "DictionaryAspect" instance, with all the dependencies defined in DictionaryAspect.
5) Create a DictionaryService from web console:
Go to web console: in the Configuration panel, edit the "Dictionary Services" Configuration, and add
some dictionaries. By default, an English dictionary is displayed. Just click on "save", *then click
on your refresh web browser*: you will see a new dictionary service instance. At this point, a
"DictionaryImpl" component instance will be create (with the service property "lang=en"), and the
SpellCheck component will be injected with it (the DictionaryImpl implements
DictionaryService). Then you should see the "spellcheck" command, when typing "help" on the gogo
shell.
6) test the spellchecker under gogo shell:
Just type "spellcheck hello", and the command should reply a fantastic message, like "word hello is
correct".
7) Inspect again DependencyManager components from the shell:
Type again "dm 5", for browsing the components coming from our bundle id 5:
[5] org.apache.felix.dependencymanager.samples.annotation
org.osgi.service.cm.ManagedServiceFactory(service.pid=DictionaryImplFactoryPid) registered
org.osgi.service.log.LogService service optional available
org.apache.felix.dm.samples.annotation.SpellChecker(osgi.command.function={spellcheck},osgi.command.scope=dmsample.annotation) registered
org.apache.felix.dm.samples.annotation.DictionaryService service required available
org.osgi.service.log.LogService service optional available
org.apache.felix.dm.impl.AspectServiceImpl$AspectImpl@128edf2 unregistered
org.apache.felix.dm.samples.annotation.DictionaryService (&(!(org.apache.felix.dependencymanager.aspect=*))(lang=en)) service optional unavailable
DictionaryAspectPID configuration required unavailable
org.osgi.service.log.LogService service optional unavailable
org.apache.felix.dm.samples.annotation.DictionaryService(service.pid=DictionaryImplFactoryPid.e01b70ff-d2b5-4305-9e86-84c68a2fddbb,service.factoryPid=DictionaryImplFactoryPid,lang=en) registered
org.osgi.service.log.LogService service optional available
Here, you can see the following:
* the org.osgi.service.cm.ManagedServiceFactory with factory pid "DictionaryImplFactoryPid" is now
registered, because we have created a dictionary from config admin (in the Dictionary Services"
webconsole configuration section).
* the SpellChecker is now "registered" because it has been injected with the DictionaryImpl we have
created from webconsole.
* the AspectServiceImpl$AspectImpl is not yet registered because we still have to instantiate a
configuration from webconsole for the "DictionaryAspectPID" PID: this configuration is required to
instance our DictionaryAspect component (see the @ConfigurationDependency annotation in
DictionaryAspect.java).
* One instance of the DictionaryService component is now registered (this instance corresponds to
what we just configured from webconsole, in the "Dictionary Services" section).
8) Finally, activate the "Aspect Dictionary" component:
To do so, you can click on the "Aspect Dictionary" button, from web console Configuration section,
in order to decorate the english dictionary with some custom words. By default, the "aspect" word is
pre configured, but you can click on the "+" button in order to add more words. Then click on
Save. At this point, the English DictionaryService will be decorated with the aspect service. So,
now, if you type "spellcheck aspect", then the message: "word aspect is correct" should be
displayed. What is going on is that the original DictionaryService will be replaced by the
DictionaryAspect, using a higher service.ranking (ranking 10, see DictionaryAspect.java). So the
spell checker will be transparently re-injected with the DictionayAspect, which is from his side
depending on the originial DictionaryService.
So, if you type "dm 5", you will know see two DictionaryService instances:
org.apache.felix.dm.samples.annotation.DictionaryService(service.pid=DictionaryImplFactoryPid.8390ad56-b2de-4414-9123-29c65c42e5b9,service.factoryPid=DictionaryImplFactoryPid,lang=en) registered
org.osgi.service.log.LogService service optional available
org.apache.felix.dm.samples.annotation.DictionaryService(service.pid=DictionaryImplFactoryPid.8390ad56-b2de-4414-9123-29c65c42e5b9,service.ranking=10,service.factoryPid=DictionaryImplFactoryPid,org.apache.felix.dependencymanager.aspect=57,lang=en) registered
org.apache.felix.dm.samples.annotation.DictionaryService (&(|(!(service.ranking=*))(service.ranking<=9))(|(service.id=57)(org.apache.felix.dependencymanager.aspect=57))) service required available
DictionaryAspectPID configuration required available
org.osgi.service.log.LogService service optional available
The first one is the original DictionaryService we have created using the factory pid
"DictionaryImplFactoryPid" from web console. By default, the ranking of this service is 0.
Next, you see the new DictionaryService which corresponds to our DictionaryAspect service. It has
the following properties:
* it has inherited from all service properties found from the original intercepted DictionarService.
* it has a higher service ranking than the original one (see service.ranking=10). This ranking is
actually defined in DictionaryAspect.java, in the @Aspect annotation.
* it has a dependency over the original DictionaryService (using an appropriate filter).
* it also inherits from all dependencies originally defined in the DictionaryImpl component