| 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 |
| |
| |
| |
| |