You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2013/09/20 22:06:44 UTC

svn commit: r1525122 - /felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-quick-tour.mdtext

Author: pderop
Date: Fri Sep 20 20:06:44 2013
New Revision: 1525122

URL: http://svn.apache.org/r1525122
Log:
CMS translation ...

Modified:
    felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-quick-tour.mdtext

Modified: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-quick-tour.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-quick-tour.mdtext?rev=1525122&r1=1525121&r2=1525122&view=diff
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-quick-tour.mdtext (original)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-quick-tour.mdtext Fri Sep 20 20:06:44 2013
@@ -1,256 +1,351 @@
 translation_pending: true
-Title: Apache Felix Dependency Manager - Using Annotations - Quick Tour
-
-# Spell Checker Sample
-
-This section presents a quick overview of the capabilities and usage  of  the DependencyManager java 5 annotations. In particular, we will  recap  the DependencyManager annotation architecture, and identify some   simple usage  scenarios using a SpellChecker sample application with  annotated  components (the application is available from the felix  trunk, in the  dependencymanager/samples.annotation maven subproject).
+Title: Dependency Manager Annotations Quick Tour
+Excerpt: Helps you with the basic concepts using a full SpellChecker sample code
+This section presents a quick overview of the capabilities and usage of the 
+DependencyManager java 5 annotations. In particular, we will recap the DependencyManager 
+annotation architecture, and identify some simple usage scenarios using a SpellChecker 
+sample application with annotated components. 
+The application is available from the felix trunk, in the dependencymanager/samples.annotation 
+subproject.
 
 ## Architecture
 
-Instead of writing Activators which extends the DependencyActivatorBase class, service components can now be annotated using the annotations provided by the *org.apache.felix.dependencymanager.annotation* bundle. Annotations are not reflectively parsed at runtime; but we use a BND plugin which scans annotations at compilation phase and generates a compact metadata file in the bundle's META-INF/dependencymanager subdirectory. This has the following benefits:
-* JVM startup speed is not affected, and class files are not parsed when the framework is starting
-* Moreover, since the annotations are not retained by the VM at runtime, it is not necessary to load the annotation API bundle at runtime.
-
-At runtime, the metadata generated during the compilation phase are processed by a specific DependencyManager Runtime bundle, which is in charge of managing the service component lifecycle and dependencies. This Runtime bundle actually uses the DependencyManager programmatic API in order to manage the annotated components. Annotated components can then be inspected with the DependencyManager Gogo shell, as it is the case with DM components declared through the programmatic DM API.
+Instead of writing Activators which extends the DependencyActivatorBase class, service 
+components can now be annotated using the annotations provided by the 
+*org.apache.felix.dependencymanager.annotation* bundle. Annotations are not reflectively 
+parsed at runtime; but we use a BND plugin which scans annotations at compilation phase 
+and generates a compact metadata file in the bundle's META-INF/dependencymanager 
+subdirectory. This has the following benefits:
+
+- JVM startup speed is not affected, and class files are not parsed when the framework is starting
+- Moreover, since the annotations are not retained by the VM at runtime, it is not necessary to load the annotation API bundle at runtime.
+
+At runtime, the metadata generated during the compilation phase are processed by a 
+specific DependencyManager Runtime bundle, which is in charge of managing the service 
+component lifecycle and dependencies. This Runtime bundle actually uses the 
+DependencyManager programmatic API in order to manage the annotated components. 
+Annotated components can then be inspected with the DependencyManager Gogo shell, as it is
+the case with DM components declared through the programmatic DM API.
 
 ## Registering a Service
 
-To register a service, your can annotate your class with a *@Component* annotation, and an instance of your class will be registered under all directly implemented interfaces into the OSGi registry. You can however take control on the interfaces to be exposed, and in this case, you can use the *provides* attribute, which takes a list of classes to expose from the registry.
-
-To illustrate this, we are now introducing a SpellChecker application which provides a Felix "spellcheck" Gogo shell command. Gogo is the  new shell supported by the Felix Framework. Our "spellcheck" command is implemented by the SpellChecker component which accepts a string as  parameter. This string is then checked for proper existence. To do the  checking, The SpellChecker class has a required/multiple (1..N) dependency over every available DictionaryService services. Such DictionaryService represents a real dictionary for a given language (it  has a *lang* service property), and is configurable/instantiable from Configuration Admin.
-
-The OSGi Configuration Admin service provides a mechanism for configuring components (using ManagedService interfaces), and WebConsole actually implements this service. ConfigAdmin is also able to instantiate some Services (using ManagedServiceFactory interfaces).
+To register a service, your can annotate your class with a *@Component* annotation, and 
+an instance of your class will be registered under all directly implemented interfaces 
+into the OSGi registry. You can however take control on the interfaces to be exposed, and 
+in this case, you can use the *provides* attribute, which takes a list of classes to
+expose from the registry.
+
+To illustrate this, we are now introducing a SpellChecker application which provides a 
+Felix "spellcheck" Gogo shell command. Gogo is the  new shell supported by the Felix
+Framework. Our "spellcheck" command is implemented by the SpellChecker component which 
+accepts a string as  parameter. This string is then checked for proper existence. To do 
+the  checking, The SpellChecker class has a required/multiple (1..N) dependency over 
+every available DictionaryService services. Such DictionaryService represents a real 
+dictionary for a given language (it  has a *lang* service property), and is 
+configurable/instantiable from the OSGi Configuration Admin Service.
+
+Configuration Admin service provides a mechanism for configuring components 
+(using ManagedService interfaces), and WebConsole actually implements this service. 
+ConfigAdmin is also able to instantiate some Services (using ManagedServiceFactory 
+interfaces).
 
 Now we have introduced the background, here is the SpellCheck component:
-
-
+    
+    :::java
     @Component(provides={SpellChecker.class},
-               properties={@Property(name=CommandProcessor.COMMAND_SCOPE, value="dmsample.annotation"),
-                           @Property(name=CommandProcessor.COMMAND_FUNCTION, values={"spellcheck"})})
+               properties={@Property(name=CommandProcessor.COMMAND_SCOPE, value="dmsample.annotation"),
+                           @Property(name=CommandProcessor.COMMAND_FUNCTION, values={"spellcheck"})})
     public class SpellChecker {
         // --- Gogo Shell command
     
-        @Descriptor("checks if word is found from an available dictionary")
-        public void spellcheck(@Descriptor("the word to check")String word) {
+        @Descriptor("checks if word is found from an available dictionary")
+        public void spellcheck(@Descriptor("the word to check")String word) {
            // Check the proper existence of the word parameter, using injected DictionaryService instances
            // ...
         }
     }
 
 
-In the code above, you see that the SpellCheck is annotated with the *@Component* annotation. Gogo runtime does not required shell commands to implement a  specific interface. Commands just have to register some Pojos in the  OSGi registry, but the only thing required is to provide the Pojos with  two service properties ( COMMAND*SCOPE, and COMMAND*FUNCTION) which will  be used by the Gogo runtime when instropecting the Pojo for invoking  the proper functions.
+In the code above, you see that the SpellCheck is annotated with the *@Component* 
+annotation. Gogo runtime does not required shell commands to implement a  specific 
+interface. Commands just have to register some Pojos in the  OSGi registry, but the only 
+thing required is to provide the Pojos with two service properties ( COMMAND_SCOPE, and 
+COMMAND_FUNCTION) which will  be used by the Gogo runtime when instropecting the Pojo 
+for invoking  the proper functions.
 
 
 So, coming back to the sample code, the SpellChecker class registers  itself into the OSGi registry, using the *provides* attribute, which just refer to our SpellChecker class, and the two  mandatory Gogo service properties are also specified using the *@Property* annotation. It is not shown here, but service properties can also be  provided dynamically from a method that can return a Map, and annotated  with the *@Start* lifecycle callback, but we will see this feature in a another section.
 
 ## Depending on a Service
 
-Our SpellChecker component can expose itself as a Gogo shell command,   but before being registered into the OSGi registry, we also need to be   injected with  two dependencies: one required dependency (at minimum)  on  a DictionaryService, and another optional one on a LogService.  First,  let's look at the DictionaryService, which is a simple  interface:
-
-
-     public interface DictionaryService {
-        /**
-         * Check for the existence of a word.
-         * @param word the word to be checked.
-         * @return true if the word is in the dictionary, false otherwise.
-         */
-        public boolean checkWord(String word);
+Our SpellChecker component can expose itself as a Gogo shell command, but before being 
+registered into the OSGi registry, we also need to be   injected with two dependencies: 
+one required dependency (at minimum) on a DictionaryService, and another optional one on 
+a LogService.  First, let's look at the DictionaryService, which is a simple interface:
+
+    :::java
+    public interface DictionaryService {
+        /**
+         * Check for the existence of a word.
+         * @param word the word to be checked.
+         * @return true if the word is in the dictionary, false otherwise.
+         */
+        public boolean checkWord(String word);
     }
 
-And here is our previous SpellChecker component, augmented with two new ServiceDependency annotations:
-
+And here is our previous SpellChecker component, augmented with two new ServiceDependency 
+annotations:
 
+    :::java
     @Component(provides={SpellChecker.class},
-               properties={@Property(name=CommandProcessor.COMMAND_SCOPE, value="dmsample.annotation"),
-                           @Property(name=CommandProcessor.COMMAND_FUNCTION, values={"spellcheck"})})
+               properties={@Property(name=CommandProcessor.COMMAND_SCOPE, value="dmsample.annotation"),
+                           @Property(name=CommandProcessor.COMMAND_FUNCTION, values={"spellcheck"})})
     public class SpellChecker {
-        @ServiceDependency(required = false)
-        private LogService m_log;
+        @ServiceDependency(required = false)
+        private LogService m_log;
     
-        private CopyOnWriteArrayList<DictionaryService> m_dictionaries = new CopyOnWriteArrayList<DictionaryService>();
+        private CopyOnWriteArrayList<DictionaryService> m_dictionaries = new CopyOnWriteArrayList<DictionaryService>();
     
-        @ServiceDependency(removed = "removeDictionary")
-        protected void addDictionary(DictionaryService dictionary) {
-            m_dictionaries.add(dictionary);
-        }
-        
-        protected void removeDictionary(DictionaryService dictionary) {
-            m_dictionaries.remove(dictionary);
-        }
-    
-        // --- Gogo Shell command
-    
-        @Descriptor("checks if word is found from an available dictionary")
-        public void spellcheck(@Descriptor("the word to check")String word)
-        {
-            m_log.log(LogService.LOG_INFO, "Checking spelling of word \"" + word
-                + "\" using the following dictionaries: " + m_dictionaries);
-    
-            for (DictionaryService dictionary : m_dictionaries)
-            {
-                if (dictionary.checkWord(word))
-                {
-                    System.out.println("word " + word + " is correct");
-                    return;
-                }
-            }
-            System.err.println("word " + word + " is incorrect");
-        }
+        @ServiceDependency(removed = "removeDictionary")
+        protected void addDictionary(DictionaryService dictionary) {
+           m_dictionaries.add(dictionary);
+        }
+    
+        protected void removeDictionary(DictionaryService dictionary) {
+           m_dictionaries.remove(dictionary);
+        }
+    
+        // --- Gogo Shell command
+    
+        @Descriptor("checks if word is found from an available dictionary")
+        public void spellcheck(@Descriptor("the word to check")String word) {
+           m_log.log(LogService.LOG_INFO, "Checking spelling of word \"" + word
+              + "\" using the following dictionaries: " + m_dictionaries);
+    
+           for (DictionaryService dictionary : m_dictionaries) {
+              if (dictionary.checkWord(word)) {
+                 System.out.println("word " + word + " is correct");
+                 return;
+              }
+           }
+           System.err.println("word " + word + " is incorrect");
+        }
     }
 
 There are many things to describe in the code above:
 
-First, we define an optional dependency on the LogService, by defining a *@ServiceDependency(required=false)* annotation on our m*logService field: This means that our component   will be provided into the OSGi registry even if there is no available   LogService, and in this case, a NullObject will be injected in our class   field; This will avoid to check for nullability, when using the   m*logService field. All optional dependencies applied on class fields  are  injected with a NullObject (when not available). The NullObject can  be  invoked and will do nothing. For a lot of cases  that is good  enough to  handle optional dependencies. But when you really want to  check if an  optional service is there or not, then you have to apply  the optional  dependency on a callback method, which will be called when  the optional  service is available.
-
-Next comes the dependency on the DictionaryService. Here, we use a *ServiceDependency* annotation, but this time we apply it on a method (*add/removeDictionary*). There is no need to specify the "*required=true*"   flag because it is the default value. Notice that this behavior is   different from the API, where service dependencies are optional by   default. We use a callback method, because we just need to register all   available DictionaryService services in our dictionary list, which is   used when checking word existence. This list is a copy on write list   because the dependency may be injected at any time, possibly from   another thread. So, using a copy on write list avoid us to use   synchronized methods.
+First, we define an optional dependency on the LogService, by defining a 
+*@ServiceDependency(required=false)* annotation on our m_logService field: This
+means that our component will be provided into the OSGi registry even if there 
+is no available LogService, and in this case, a NullObject will be injected in 
+our class field; 
+This will avoid to check for nullability, when using the m_logService field. 
+All optional dependencies applied on class fields are injected with a 
+NullObject (when not available). 
+The NullObject can be invoked and will do nothing. For a lot of cases that is 
+good enough to handle optional dependencies. But when you really want to check 
+if an optional service is there or not, then you have to apply the optional 
+dependency on a callback method, which will be called when the optional 
+service is available.
+
+Next comes the dependency on the DictionaryService. Here, we use a *ServiceDependency* 
+annotation, but this time we apply it on a method (*add/removeDictionary*). There is no 
+need to specify the "*required=true*"  flag because it is the default value. Notice that 
+this behavior is different from the API, where service dependencies are optional by default
+. We use a callback method, because we just need to register all available 
+DictionaryService services in our dictionary list, which is used when checking word 
+existence. This list is a copy on write list because the dependency may be injected at 
+any time, possibly from   another thread. So, using a copy on write list avoid us to use   synchronized methods.
 
 ## Creating a Service from ConfigAdmin
 
-The *@Component* annotation is not the only one for creating services. Another one is the *@FactoryConfigurationAdapterService* annotation which allows to instantiate many instances of the same   annotated service class from ConfigAdmin (and WebConsole). To illustrate  this, let's take a look at our  DictionaryImpl class which is part of  the SpellChecker sample. This service is required by the SpellChecker  component, when checking for proper word existence. And you can  instantiate as many DictionaryService as you want, from ConfigAdmin ...
-
+The *@Component* annotation is not the only one for creating services. Another one is 
+the *@FactoryConfigurationAdapterService* annotation which allows to instantiate many 
+instances of the same annotated service class from ConfigAdmin (and WebConsole). 
+To illustrate this, let's take a look at our DictionaryImpl class which is part of the 
+SpellChecker sample. This service is required by the SpellChecker component, when 
+checking for proper word existence. And you can instantiate as many DictionaryService as 
+you want, from ConfigAdmin ...
 
-    @FactoryConfigurationAdapterService(factoryPid="DictionaryImplFactoryPid", updated="updated")  
+    :::java
+    @FactoryConfigurationAdapterService(factoryPid="DictionaryImplFactoryPid", updated="updated")
     public class DictionaryImpl implements DictionaryService {
-        /**
-         * We store all configured words in a thread-safe data structure, because ConfigAdmin
-         * may invoke our updated method at any time.
-         */
-        private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>();
-    
-        /**
-         * Our Dictionary language.
-         */
-        private String m_lang;
-    
-        /**
-         * Our service will be initialized from ConfigAdmin, and we also handle updates in this method.
-         * @param config The configuration where we'll lookup our words list (key="words").
-         */
-        protected void updated(Dictionary<String, ?> config) {
-            m_lang = (String) config.get("lang");
-            m_words.clear();
-            String[] words = (String[]) config.get("words");
-            for (String word : words) {
-                m_words.add(word);
-            }
-        }
-               
-        /**
-         * Check if a word exists if the list of words we have been configured from ConfigAdmin/WebConsole.
-         */
-        public boolean checkWord(String word) {
-            return m_words.contains(word);
-        }
+       /**
+        * We store all configured words in a thread-safe data structure, because ConfigAdmin
+        * may invoke our updated method at any time.
+        */
+       private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>();
+    
+       /**
+        * Our Dictionary language.
+        */
+       private String m_lang;
+    
+       /**
+        * Our service will be initialized from ConfigAdmin, and we also handle updates in this method.
+        * @param config The configuration where we'll lookup our words list (key="words").
+        */
+       protected void updated(Dictionary<String, ?> config) {
+          m_lang = (String) config.get("lang");
+          m_words.clear();
+          String[] words = (String[]) config.get("words");
+          for (String word : words) {
+             m_words.add(word);
+          }
+       }
+
+       /**
+        * Check if a word exists if the list of words we have been configured from ConfigAdmin/WebConsole.
+        */
+       public boolean checkWord(String word) {
+          return m_words.contains(word);
+       }
     }
 
-Our DictionaryImpl class implements a DictionaryService, and our  class will be registered under that interface (all directly implemented  interfaces are used when registering the service, but you can select  some others using the *provides* attribute). The *@FactoryConfigurationAdapterService* annotation will instantiate our service for each configuration created  from web console (and matching our "DictionaryImplFactoryPid"  factoryPid).
-
-We also use the *updated* attribute, which specifies a callback  method which will handle properties configured by ConfigAdmin. The  updated callback will also be called when our properties are changing.  Every properties are propagated to our service properties, unless the  properties starting with a dot ("."). Configuration properties starting  with a dot (".") are considered private and are not propagated.
-
-Notice that this annotation also supports optional meta type  attributes, which allow to customize the ConfigAdmin GUI, with custom  messages, like heading/property title, property type, property  description, etc ...). So, let's revisit our DisctionaryImpl service,  but this time with meta type support:
-
-
-      @FactoryConfigurationAdapterService(factoryPid="DictionaryImplFactoryPid",
-        propagate=true,
-        updated="updated",
-        heading="Dictionary Services",
-        description="Declare here some Dictionary instances, allowing to instantiates some DictionaryService services for a given dictionary language",
-        metadata={
-            @PropertyMetaData(
-                heading="Dictionary Language",
-                description="Declare here the language supported by this dictionary. " +
-                    "This property will be propagated with the Dictionary Service properties.",
-                defaults={"en"},
-                id="lang",
-                cardinality=0),
-            @PropertyMetaData(
-                heading="Dictionary words",
-                description="Declare here the list of words supported by this dictionary.",
-                defaults={"hello", "world"},
-                id="words",
-                cardinality=Integer.MAX_VALUE)
-        }
-    )  
+Our DictionaryImpl class implements a DictionaryService, and our class will be registered 
+under that interface (all directly implemented  interfaces are used when registering the 
+service, but you can select  some others using the *provides* attribute). 
+The *@FactoryConfigurationAdapterService* annotation will instantiate our service for 
+each configuration created  from web console (and matching our "DictionaryImplFactoryPid" 
+factoryPid).
+
+We also use the *updated* attribute, which specifies a callback  method which will handle
+properties configured by ConfigAdmin. The  updated callback will also be called when our 
+properties are changing.  Every properties are propagated to our service properties, 
+unless the  properties starting with a dot ("."). Configuration properties starting  with 
+a dot (".") are considered private and are not propagated.
+
+Notice that this annotation also supports optional meta type attributes, which allow to 
+customize the ConfigAdmin GUI, with custom  messages, like heading/property title,
+property type, property  description, etc ...). So, let's revisit our DisctionaryImpl 
+service,  but this time with meta type support:
+
+    :::java
+    @FactoryConfigurationAdapterService(factoryPid="DictionaryImplFactoryPid",
+        propagate=true,
+        updated="updated",
+        heading="Dictionary Services",
+        description="Declare here some Dictionary instances, allowing to instantiates some DictionaryService services for a given dictionary language",
+        metadata={
+           @PropertyMetaData(
+               heading="Dictionary Language",
+               description="Declare here the language supported by this dictionary. " +
+                  "This property will be propagated with the Dictionary Service properties.",
+               defaults={"en"},
+               id="lang",
+               cardinality=0),
+           @PropertyMetaData(
+               heading="Dictionary words",
+               description="Declare here the list of words supported by this dictionary.",
+               defaults={"hello", "world"},
+               id="words",
+               cardinality=Integer.MAX_VALUE)
+        }
+    )
     public class DictionaryImpl implements DictionaryService {
         ... code same as before
     }
 
 
-## 
-
-
 ## Providing an Aspect
 
-As we have seen in the previous section, there are many annotations  that can be used to specify a service. Another one is the *@AspectService* annotation. This annotation allows to *decorate* an existing service in  order to add certain "capabilities" to it, like  adding a specific caching mechanism to a storage  service or   implementing logging. Aspects can be plugged to an existing service at   runtime, and can also be removed dynamically. This is transparent, and   the clients using the existing service are not interrupted, they are  just rebound with the aspect service.
-
-
-
-As an example, we go back to our SpellChecker application, and we are   now looking at the DictionaryAspect class. This class uses the *@Aspect{*}Service annotation in order to add some custom words to an English   DictionaryService (with the service property lang=en). The Extra words   to add to the English Dictionary will be configured from ConfigAdmin.   That's why the class also uses a *@ConfigurationDependency* annotation:
-
+As we have seen in the previous section, there are many annotations  that can be used 
+to specify a service. Another one is the *@AspectService* annotation. This annotation 
+allows to *decorate* an existing service in  order to add certain "capabilities" to it, 
+like  adding a specific caching mechanism to a storage  service or implementing logging. 
+Aspects can be plugged to an existing service at   runtime, and can also be removed 
+dynamically. This is transparent, and   the clients using the existing service are not 
+interrupted, they are  just rebound with the aspect service.
+
+As an example, we go back to our SpellChecker application, and we are now looking at the 
+DictionaryAspect class. This class uses the *@Aspect{*}Service annotation in order to add 
+some custom words to an English   DictionaryService (with the service property lang=en). 
+The Extra words   to add to the English Dictionary will be configured from ConfigAdmin.  
+That's why the class also uses a *@ConfigurationDependency* annotation:
 
+    :::java
     @AspectService(ranking = 10, filter = "(lang=en)")
     public class DictionaryAspect implements DictionaryService {
-        /**
-         * This is the service this aspect is applying to.
-         */
-        private DictionaryService m_originalDictionary;
-    
-        /**
-         * We store all configured words in a thread-safe data structure, because ConfigAdmin may
-         * invoke our updated method at any time.
-         */
-        private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>();
-    
-        /**
-         * Defines a configuration dependency for retrieving our english custom words (by default,
-         * our PID is our full class name).
-         */
-        @ConfigurationDependency
-        protected void updated(Dictionary<String, ?> config) {
-            m_words.clear();
-            String[] words = (String[]) config.get("words");
-            for (String word : words) {
-                m_words.add(word);
-            }
-        }
-    
-        /**
-         * Checks if a word is found from our custom word list. if not, delegate to the decorated
-         * dictionary.
-         */
-        public boolean checkWord(String word) {
-            if (m_words.contains(word)) {
-                return true;
-            }
-            return m_originalDictionary.checkWord(word);
-        }
+       /**
+        * This is the service this aspect is applying to.
+        */
+       private DictionaryService m_originalDictionary;
+    
+       /**
+        * We store all configured words in a thread-safe data structure, because ConfigAdmin may
+        * invoke our updated method at any time.
+        */
+       private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>();
+    
+       /**
+        * Defines a configuration dependency for retrieving our english custom words (by default,
+        * our PID is our full class name).
+        */
+       @ConfigurationDependency
+       protected void updated(Dictionary<String, ?> config) {
+          m_words.clear();
+          String[] words = (String[]) config.get("words");
+          for (String word : words) {
+             m_words.add(word);
+          }
+       }
+    
+      /**
+        * Checks if a word is found from our custom word list. if not, delegate to the decorated
+        * dictionary.
+        */
+       public boolean checkWord(String word) {
+          if (m_words.contains(word)) {
+            return true;
+          }
+          return m_originalDictionary.checkWord(word);
+        }
     }
 
-The annotation does the following: because our class implements the   DictionaryService contract, it will instantiate our service each time it   finds another existing DictionaryService matching the filter attribute   we provide in the annotation (filter="(lang=en)"). And it will inject   the existing service in our m*originalDictionary field, by reflection.   But we can also specify a *field_ attribute in the annotation, if  we  want to explicitly inject the existing service in a given class  field. So, any client depending on an English DictionaryService will be  transparently rebound to our aspect Dictionary.
-
-In the Annotation, also notice the *ranking* attribute: It is  the level used to organize the aspect chain ordering (multiple aspects  may be applied on a given service).
-
-
-The *ConfigurationDependency* is another dependency that we have  not seen before: it is used to configure the extra English words from  ConfigAdmin. This annotation normally requires a pid parameter, which is  a persistent identifier uniquely identifying our component, but by  default, the pid is set to the fully qualified name of our class.
+The annotation does the following: because our class implements the  DictionaryService 
+contract, it will instantiate our service each time it finds another existing 
+DictionaryService matching the filter attribute  we provide in the annotation 
+(filter="(lang=en)"). And it will inject the existing service in our 
+m_originalDictionary field, by reflection. But we can also specify a field attribute in 
+the annotation, if  we  want to explicitly inject the existing service in a given class 
+field. So, any client depending on an English DictionaryService will be transparently 
+rebound to our aspect Dictionary.
+
+In the Annotation, also notice the *ranking* attribute: It is  the level used to organize 
+the aspect chain ordering (multiple aspects  may be applied on a given service).
+
+
+The *ConfigurationDependency* is another dependency that we have  not seen before: it is 
+used to configure the extra English words from  ConfigAdmin. This annotation normally 
+requires a pid parameter, which is  a persistent identifier uniquely identifying our 
+component, but by  default, the pid is set to the fully qualified name of our class.
 
-Notice that like the *@FactoryConfigurationAdapterService*, the @*ConfigurationDependency* annotation also supports meta type attributes.
+Notice that like the *@FactoryConfigurationAdapterService*, the *@ConfigurationDependency*
+annotation also supports meta type attributes.
 
 ## How to run the sample code
 
-* Install the following bundles:
+Install the following bundles:
 
-&nbsp;&nbsp;&nbsp;&nbsp; org.apache.felix.configadmin
-&nbsp;&nbsp;&nbsp;&nbsp; org.apache.felix.metatype
-&nbsp;&nbsp;&nbsp;&nbsp; org.apache.felix.http.jetty
-&nbsp;&nbsp;&nbsp;&nbsp; org.apache.felix.webconsole
-
-&nbsp;&nbsp;&nbsp;&nbsp; org.apache.felix.dependencymanager
-&nbsp;&nbsp;&nbsp;&nbsp; org.apache.felix.dependencymanager.shell
-&nbsp;&nbsp;&nbsp;&nbsp; org.apache.felix.dependencymanager.runtime
-&nbsp;&nbsp;&nbsp;&nbsp; org.apache.felix.dependencymanager.samples.annotation
-
-
-* Start felix
-* Go to web console: in the Configuration panel, edit the "Dictionary  Services" Configuration. By default, an English  dictionary is displayed. Just&nbsp; click on "save", then refresh your web  browser (click on refresh): you will see a new dictionary service  instance. At this point, a DictionaryService service will be enabled  (with the service property "lang=en"),&nbsp; and the SpellCheck component  will be injected with it. Then you should see the "spellcheck" command,  when typing&nbsp; "help" on the gogo shell.
-* Just type "spellcheck hello", and the command should reply a fantastic message, like "word hello is correct".
-* You can also click on the "Aspect Dictionary" button, 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.
+    org.apache.felix.configadmin
+    org.apache.felix.metatype
+    org.apache.felix.http.jetty
+    org.apache.felix.webconsole
+
+    org.apache.felix.dependencymanager
+    org.apache.felix.dependencymanager.shell
+    org.apache.felix.dependencymanager.runtime
+    org.apache.felix.dependencymanager.samples.annotation
+
+Start felix.
+
+Go to web console: in the Configuration panel, edit the "Dictionary  Services" Configuration. By default, an English  dictionary is displayed. Just&nbsp; click on "save", then refresh your web  browser (click on refresh): you will see a new dictionary service  instance. At this point, a DictionaryService service will be enabled  (with the service property "lang=en"),&nbsp; and the SpellCheck component  will be injected with it. Then you should see the "spellcheck" command,  when typing&nbsp; "help" on the gogo shell.
+
+Just type "spellcheck hello", and the command should reply a fantastic message, like "word hello is correct".
+
+You can also click on the "Aspect Dictionary" button, 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.