felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r1421893 [4/24] - in /felix/site/trunk/content: ./ documentation/ documentation/community/ documentation/development/ documentation/faqs/ documentation/subprojects/ documentation/subprojects/apache-felix-commons/ documentation/subprojects/a...
Date Fri, 14 Dec 2012 14:30:22 GMT
Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-dependencies.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-dependencies.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-dependencies.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-dependencies.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,261 @@
+Title: Apache Felix Dependency Manager - Using Annotations - Dependencies
+
+# Annotations - Dependencies
+
+This section describes the various dependencies supported with annotations.
+
+## @ServiceDependency
+
+Annotates a method or a field for injecting a Service Dependency. When applied on a class field, optional unavailable dependencies are injected with a NullObject.
+
+Annotation attributes:
+
+* *added*: The callback method to be invoked when the service is available. This attribute is only meaningful when the annotation is applied on a class field.
+* *changed*: The callback method to be invoked when the service properties have changed.
+* *removed*: The callback method to invoke when the service is lost.
+* *timeout*: The max time in millis to wait for when the dependency is temporarily unavailable. Specifying a positive number allow to block the caller thread between service updates. Only useful for required stateless dependencies that can be replaced transparently. A Dynamic Proxy is used to wrap the actual service dependency (which must be an interface). When the dependency goes away, an attempt is made to replace it with another one which satisfies the service dependency criteria. If no service replacement is available, then any method invocation (through the dynamic proxy) will block during a configurable timeout. On timeout, an unchecked IllegalStateException exception is raised (but the service is not deactivated).
+Notice that the changed/removed callbacks are not used when the timeout parameter is > \-1.
+\-1 means no timeout at all (default). 0 means that invocation on a missing service will fail immediately. A positive number represents the max timeout in millis to wait for the service availability.
+* *name*: The name used when dynamically configuring this dependency from the init method. Specifying this attribute allows to dynamically configure the dependency filter and required flag from the Service's init method. All unnamed dependencies will be injected before the init() method; so from the init() method, you can then pick up whatever information needed from already injected (unnamed) dependencies, and configure dynamically your named dependencies, which will then be calculated once the init() method returns. Please refer to [Apache Felix Dependency Manager - Using Annotations - Lifecycle#Dynamic Dependency Configuration]({{ refs.apache-felix-dependency-manager-using-annotations-lifecycle-dynamic-dependency-configuration.path }}).
+* *propagate*: Returns true if the dependency service properties must be published along with the service. Any additional service properties specified directly are merged with these.
+
+Usage Example: Here, the MyComponent component is injected with a dependency over a "MyDependency" service.
+
+
+         @Component
+         class MyComponent {
+             @ServiceDependency(timeout=15000)
+             MyDependency dependency;
+             ...
+         }
+
+
+Usage example of a Service whose dependency filter is configured from ConfigAdmin, using a "named" dependency
+(please check [Apache Felix Dependency Manager - Using Annotations - Lifecycle#Dynamic Dependency Configuration]({{ refs.apache-felix-dependency-manager-using-annotations-lifecycle-dynamic-dependency-configuration.path }}) for more informations about "named" dependencies):
+
+
+          /**
+            * A Service whose service dependency "otherService" filter is configured from ConfigAdmin
+            */
+          @Service
+          class X {
+              private Dictionary m_config;
+    
+              /**
+               * Initialize our service from config ... and store the config for later usage (from our init method)
+               */
+              @ConfigurationDependency(pid="MyPid")
+              void configure(Dictionary conf) {
+                   m_config = config;
+              }
+    
+              /**
+               * All unnamed dependencies are injected: we can now configure other named
+               * dependencies, using the already injected configuration.
+               * The returned Map will be used to configure our "otherService" Dependency.
+               */
+              @Init
+              Map init() {
+                  return new HashMap() {{
+                      put("otherService.filter", m_config.get("filter"));
+                      put("otherService.required", m_config.get("required"));
+                  }};
+              }
+    
+              /**
+               * This named dependency filter/required flag will be configured by our init method (see above).
+               */
+              @ServiceDependency(name="otherService")
+              void bindOtherService(OtherService other) {
+              }
+    
+              /**
+               * All dependencies are injected and our service is now ready to be published.
+               * Notice that you can also use the publisher service attribute if you need
+               * to take control on service exposition.
+               */
+              @Start
+              void start() {
+              }
+          }
+
+
+
+
+
+## @ConfigurationDependency
+
+A configuration dependency is always required, and allows you to depend on the availability of a valid configuration for your component. This dependency requires the OSGi Configuration Admin Service.
+
+Annotation attributes:
+
+* *pid*: Returns the pid for a given service (by default, the pid is the service class name).
+* *propagate*: Returns true if the configuration properties must be published along with the service. Any additional service properties specified directly are merged with these.
+* *heading*: The label used to display the tab name (or section) where the properties are displayed. Example: "Printer Service".
+* *description*: A human readable description of the PID this annotation is associated with. Example: "Configuration for the PrinterService bundle".
+* *metadata*: an array of PropertyMetadaData\[\]({{ refs..path }}) annotation describing property types (see the FactoryConfigurationAdapterService section in the "Writing Components" section.
+
+Usage Examples
+
+In the following example, the "Printer" component depends on a configuration whose PID name is "org.apache.felix.sample.Printer". This service will initialize its ip/port number from the provided configuration:
+
+
+         package org.apache.felix.sample;
+    
+         @Component
+         public class Printer {
+             @ConfigurationDependency
+             void updated(Dictionary config) {
+                 // load printer ip/port from the provided dictionary.
+             }
+         }
+
+This other example shows how to specify a configuration dependency, as well as meta data used to customize the WebConsole GUI. Using these meta data, you can specify for example the default value for your configurations data, some descriptions, the cardinality of configuration values, etc ...
+
+
+         package org.apache.felix.sample;
+    
+         @Component
+         public class Printer {
+             @ConfigurationDependency(
+                 heading = "Printer Service",
+                 description = "Declare here parameters used to configure the Printer service",
+                 metadata = {
+                     @PropertyMetaData(heading = "Ip Address",
+                                       description = "Enter the ip address for the Printer service",
+                                       defaults = { "127.0.0.1" },
+                                       type = String.class,
+                                       id = "IPADDR",
+                                       cardinality = 0),
+                     @PropertyMetaData(heading = "Port Number",
+                                       description = "Enter the port number for the Printer service",
+                                       defaults = { "4444" },
+                                       type = Integer.class,
+                                       id = "PORTNUM",
+                                       cardinality = 0)
+    
+                 }
+             )
+             void updated(Dictionary config) {
+                 // load configuration from the provided dictionary.
+             }
+
+
+## @BundleDependency
+
+A bundle dependency allows you to depend on a bundle in a certain set of states (INSTALLED\|RESOLVED\|STARTED\|...), as indicated by a state mask. You can also use a filter condition that is matched against all manifest entries. When applied on a class field, optional unavailable dependencies are injected with a NullObject.
+
+Attributes:
+
+* *changed*: Returns the callback method to be invoked when the service have changed.
+* *removed*: Returns the callback method to invoke when the service is lost.
+* *required*: Returns whether the dependency is required or not.
+* *filter*: Returns the filter dependency
+* *stateMask*: Returns the bundle state mask (Bundle.INSTALLED \| Bundle.ACTIVE etc ...).
+* *propagate*: Specifies if the manifest headers from the bundle should be propagated to the service properties.
+* *name*: The name used when dynamically configuring this dependency from the init method. Specifying this attribute allows to dynamically configure the dependency filter and required flag from the Service's init method. All unnamed dependencies will be injected before the init() method; so from the init() method, you can then pick up whatever information needed from already injected (unnamed) dependencies, and configure dynamically your named dependencies, which will then be calculated once the init() method returns.
+Please refer to [Apache Felix Dependency Manager - Using Annotations - Lifecycle#Dynamic Dependency Configuration]({{ refs.apache-felix-dependency-manager-using-annotations-lifecycle-dynamic-dependency-configuration.path }}).
+
+Usage Examples
+
+In the following example, the "SCR" Component allows to track all bundles containing a specific "Service-Component" OSGi header, in order to load and manage all Declarative Service components specified in the SCR xml documents referenced by the header:
+
+
+         @Component
+         public class SCR {
+             @BundleDependency(required = false,
+                               removed = "unloadServiceComponents",
+                               filter = "(Service-Component=*)"
+                               stateMask = Bundle.ACTIVE)
+             void loadServiceComponents(Bundle b) {
+                 String descriptorPaths = (String) b.getHeaders().get("Service-Component");
+                 // load all service component specified in the XML descriptorPaths files ...
+             }
+    
+             void unloadServiceComponents(Bundle b) {
+                 // unload all service component we loaded from our "loadServiceComponents" method.
+             }
+         }
+
+## @ResourceDependency
+
+Annotates a method of field as a Resource Dependency. A resource dependency allows you to depend on a resource. Resources are an abstraction that is introduced by the dependency manager, represented as a URL. They can be implemented to serve resources embedded in bundles, somewhere on a file system or in an http content repository server, or database.
+A resource is a URL and you can use a filter condition based on protocol, host, port, and path.
+
+Attributes:
+
+* *added*: Returns the callback method to be invoked when the service is available. This attribute is only meaningful when the annotation is applied on a class field.
+* *changed*: Returns the callback method to be invoked when the service properties have changed.
+* *removed*: Returns the callback method to invoke when the service is lost.
+* *required*: Returns whether the Service dependency is required or not.
+* *filter*: Returns the Service dependency OSGi filter.
+* *propagate*: Specifies if the resource URL properties must be propagated. If set to true, then the URL properties ("protocol"/"host"/"port"/"path") will be propagated to the service properties of the component which is using this dependency.
+* *name*: The name used when dynamically configuring this dependency from the init method. Specifying this attribute allows to dynamically configure the dependency filter and required flag from the Service's init method. All unnamed dependencies will be injected before the init() method; so from the init() method, you can then pick up whatever information needed from already injected (unnamed) dependencies, and configure dynamically your named dependencies, which will then be calculated once the init() method returns. Please refer to [Apache Felix Dependency Manager - Using Annotations - Lifecycle#Dynamic Dependency Configuration]({{ refs.apache-felix-dependency-manager-using-annotations-lifecycle-dynamic-dependency-configuration.path }}).
+
+Usage Examples
+Here, the "VideoPlayer" component plays any provided MKV video resources
+
+
+         @Component
+         public class VideoPlayer {
+             @ResourceDependency(required=false, filter="(path=/videos/*.mkv)")
+             void playResource(URL video) { ... }
+         }
+
+And here is an example of a VideoProvider, which provides some videos using a web URL. Notice that Resource providers need to depend on the DependencyManager API:
+
+
+         import java.net.MalformedURLException;
+         import java.net.URL;
+         import java.util.HashMap;
+         import java.util.Map;
+    
+         import org.apache.felix.dm.ResourceHandler;
+         import org.apache.felix.dm.ResourceUtil;
+         import org.apache.felix.dm.annotation.api.Component;
+         import org.apache.felix.dm.annotation.api.Init;
+         import org.apache.felix.dm.annotation.api.ServiceDependency;
+         import org.osgi.framework.BundleContext;
+         import org.osgi.framework.Filter;
+         import org.osgi.framework.InvalidSyntaxException;
+    
+         @Component
+         public class VideoProvider
+         {
+             // Injected by reflection
+             private volatile BundleContext context;
+             // List of known resource handlers
+             private Map<ResourceHandler, Filter> m_handlers = new HashMap<ResourceHandler, Filter>();
+             // List of known video resources
+             private URL[] m_videos;
+    
+             @Init
+             void init() throws MalformedURLException
+             {
+                m_videos = new URL[] {
+                        new URL("http://localhost:8080/videos/video1.mkv"),
+                        new URL("http://localhost:8080/videos/video2.mkv"),
+                 };
+             }
+    
+             // Track resource handlers
+             @ServiceDependency(required = false)
+             public void add(Map<String, String> serviceProperties, ResourceHandler handler) throws InvalidSyntaxException
+             {
+                 String filterString = serviceProperties.get("filter");
+                 filterString = (filterString != null) ? filterString : "(path=*)";
+                 Filter filter = context.createFilter(filterString);
+                 synchronized (this)
+                 {
+                     m_handlers.put(handler, filter);
+                 }
+                 for (URL video : m_videos)
+                 {
+                     if (filter.match(ResourceUtil.createProperties(video)))
+                     {
+                         handler.added(video);
+                     }
+                 }
+             }
+         }
+

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-lifecycle.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-lifecycle.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-lifecycle.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-lifecycle.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,244 @@
+Title: Apache Felix Dependency Manager - Using Annotations - Lifecycle
+
+# Annotations - Lifecycle
+
+
+
+
+A component has a lifecycle that controls when it is started or stopped. A bundle must be started before the DM Runtime can process its components. When the bundle is started, the DM Runtime then parses a specific *DependencyManager-Component* manifest header, which points to a list of descriptors describing all annotated components. Such descriptors are actually generated at compilation time, and annotation are not reflectively parsed at runtime. Only the descriptor is used to process the components. For each component, the DM Runtime first ensures that all dependencies are satisfied before activating it. Likewise, the component is deactivated when some of the required dependencies are not available anymore or when the bundle is stopped. Unless the bundle is stopped, components may be deactivated and reactivated, depending on the departure and arrival of required dependencies. The manager which is in charge of maintaining the state of components is implemented in the DM Run
 time bundle (org.apache.felix.dm.runtime bundle).
+
+## Lifecycle Callbacks
+
+### Component Activation
+
+
+
+Activating a component consists of the following steps:
+1. Wait for all required dependencies to be available. When all required dependencies are available:
+1. * Instantiate the component.
+1. * Inject all required dependencies (on class fields using reflection, or by invoking callback methods).
+1. * Inject all optional dependencies defined on class fields, *possibly with a NullObject* if the dependency is not available.
+1. * Call the component init method (annotated with *@Init*). In the  Init method, you are yet allowed to add some additional dependencies  (but using the API). Alternatively, you can also configure some  dependencies dynamically (explained later, in [#Dynamic Dependency Configuration]({{ refs.-dynamic-dependency-configuration.path }})).
+1. Wait for extra dependencies optionally configured from the init() method.
+1. If the component is not using the @*LifecycleController* annotation (detailed in the [#Controlling the Lifecycle]({{ refs.-controlling-the-lifecycle.path }}) section), then:
+1. * Invoke the component start method (annotated with *@Start*).
+1. * Publish some OSGi services (if the component provides some services).
+1. * Start tracking optional dependencies applied on method callbacks (useful for the whiteboard pattern). *Notice that NullObject pattern is not applied to optional callback dependencies*. In other words, if the dependency is not there, your callback won't be invoked at all. If you need the NullObject pattern, then apply optional dependencies on class fields, not on callback methods.
+1. Else do nothing because&nbsp; the component will trigger itself the startup using the lifecycle controller.
+
+### Component Deactivation
+
+Deactivating a component consists of the following steps:
+1. If the bundle is stopped or if some required dependencies are unavailable, or if the component is deactivated by a factorySet, then:
+1. * Unbind optional dependencies (defined on callback methods). Notice that any optional dependency unavailability does not trigger the component deactivation:&nbsp; the *removed* callbacks are just invoked, if declared in the annotation.
+1. * Invoke the stop method (annotated wit *@Stop*),  and unregister some OSGi services (if the components provides some services).
+1. * invoke destroy method (annotated with *@Destroy*).
+1. * invoke *removed* callbacks for required dependencies, if any.
+
+### Example
+
+The following example shows a basic component, which uses the @Start, @Stop, annotation:
+
+    /**
+     * A Component Using lifecyce callbacks
+     */
+    @Component
+    class X implements Y {
+        @ServiceDependency
+        void bindOtherService(OtherService other) {
+           // Will be injected before we are started (because it's a required dependency).
+        }
+    
+        @Start
+        void publishing() {
+            // All required dependencies are injected: initialize our component.
+            // Once we return, our Y service will be published in the OSGi registry.
+        }
+    
+        @Stop
+        void unpublished() {
+           // We are not registered anymore in the OSGi registry.
+        }
+    }
+
+
+### 
+
+
+### Dynamic Dependency Configuration
+
+
+#### Rationale
+
+We have seen that a component may declare some dependencies and is  started when all required dependencies are available. But there are some  cases when you may need to define some dependencies filters  dynamically, possibly from data picked up from other  dependencies (like a configuration dependency for instance).
+
+So, all this is possible using *named* dependencies: When you assign a name to a dependency; for instance *@ServiceDependency(name="foo")*, then this has an impact on how the dependency is handled. Indeed, all named dependencies are calculated *after* the @Init method returns. So from your @Init method, you can then  configure your named dependencies, using data provided by  already injected dependencies.
+
+To do so, your @Init method is allowed to return a Map containing  the filters and required flags for each named dependencies. For a given  named dependency, the corresponding filter and required flag must be  stored in the Map, using the "*filter*" and "*required*" keys, prefixed with the name of the dependency.
+
+For instance, if you define a Dependency like this:
+
+
+    @ServiceDependency(name="foo")
+    FooService fooService;
+
+Then you can return this map from your @Init method:
+
+
+
+    @Init
+    Map init() {
+        return new HashMap() {{
+            put("foo.filter", "(foo=bar)");
+            put("foo.required", "false");
+        }};
+    }
+
+So, after the init method returns, the map will be used to configure  the dependency named "foo", which will then be evaluated. And once the  dependency is available, then your @Start callback will be invoked.
+
+#### Usage example:
+
+This is an example of a component X whose dependency "foo" filter is  configured from ConfigAdmin. First, we defined a ConfigurationDependency  in order to get injected with our configuration. Next, we define a  dependency on the *FooService*, but this time, we declare the annotation  like this: *@ServiceDependency(*{*}{*}name="foo"*{*}*)*. As explained  above, The  ConfigurationDependency will be injected *before* the @Init method, and  the named dependency ("foo") will be calculated *after* the @Init method  returns. So, from our Init method, we just return a map which contains  the filter and required flag for the "foo" dependency, and we actually  use the configuration which has already been injected:
+
+
+    /**
+     * A component whose FooService dependency filter is configured from ConfigAdmin
+     */
+    @Component
+    class X {
+        private Dictionary m_config;
+    
+        /**
+         * Initialize our component from config ... and store the config for later usage (from our init method)
+         */
+        @ConfigurationDependency(pid="MyPid")
+        void configure(Dictionary conf) {
+             m_config = config;
+        }
+    
+        /**
+         * All unnamed dependencies are injected: we can now configure other named
+         * dependencies, using the already injected configuration.
+         * The returned Map will be used to configure our "foo" Dependency (see below)
+         */
+        @Init
+        Map init() {
+            return new HashMap() {{
+                put("foo.filter", m_config.get("filter"));
+                put("foo.required", m_config.get("required"));
+            }};
+        }
+    
+        /**
+         * This named dependency filter/required flag will be configured by our init method (see above).
+         */
+        @ServiceDependency(name="foo")
+        FooService fooService;
+    
+        /**
+         * All dependencies are injected and our service is now ready to be published.
+         */
+        @Start
+        void start() {
+        }
+    }
+
+
+
+
+## 
+
+
+## Controlling the Lifecycle
+
+As explained in the *Component Activation* section, a  component which provides a service is automatically registered into the  OSGi registry, after the @Start method returns. But it is sometimes  required to control when the service is really started/published or  unpublished/stopped.
+
+This can be done using the @LifecycleController annotation. This  annotation injects a Runnable object that can be invoked once you want  to trigger your service startup and publication.
+
+For instance, imagine that your component publishes an OSGi service,  but before, it needs to register into a DHT (Distributed Hash Table),  whose API is asynchronous: that is: the DHT API will callback you once  you are inserted into a node in the DHT. In this case, what you would  like to do is to publish your OSGi service, but only after you are  inserted into the DHT (when the DHT callbacks you) ... Such a case  is supported using the @LifecyceController annotation, which gives you  full control of when your component is *started/published* and *unpublished/stopped*.
+
+Let's illustrate this use case with a concrete example: First here is the DHT asynchronous API:
+
+
+    /**
+     * This is an element which can be inserted into the distributed hash table.
+     */
+    public interface DHTElement {
+       void inserted(); // callback used to notify that the element is inserted into the DHT
+    }
+    
+    /**
+     * This is the DHTService, which registers a DHTElement asynchronously.
+     */
+    public interface DHTService {
+       void insert(DHTElement element); // will callback element.inserted() later, once registered into the DHT.
+    }
+
+Next, here is our service, which uses the @LifecycleController in  order to take control of when the service is published into the OSGi  registry:
+
+
+
+    @Component(provides={MyService.class})
+    public class MyServiceImpl implements MyService, DHTElement {
+        @ServiceDependency
+        DHTService dht;
+    
+        @LifecycleController
+        Runnable trigger; // will fire component startup, once invoked.
+    
+        @Init
+        void init() {
+            dht.insert(this); // asynchronous, will callback us in our inserted method once registered into the DHT
+        }
+    
+        public void inserted() {
+            // We are inserted into the DHT: we can now trigger our component startup.
+            // We just invoke the runnable injected by our @LifecycleController annotation, which will trigger our
+            // service publication (we'll be called in our @Start method before)
+            trigger.run();
+        }
+    
+        @Start
+        void start() {
+            // method called only once we invoke our trigger Runnable (see inserted method).
+            // Our Service will be published once this method returns.
+        }
+    }
+
+
+## 
+
+
+## Dynamic Service Properties
+
+When a component provides an OSGi Service, the service properties are calculated as the following:
+* Any properties specified in the @Component annotation are used to provide the OSGi Service
+* Any properties provided by a FactorySet are also inserted in the published service
+* Any Dependency whose *propagate* attribute is set to true will also insert its properties to the published service
+
+But when the component needs to specify some service properties dynamically (not statically from the annotation), then it may do so by just returning a Map from the @Start callback. For instance:
+
+
+    @Component(properties={@Property(name="foo", value="bar")})
+    public class MyServiceImpl implements MyService {
+        @ConfigurationDependency(pid="MyPid", propagate=true)
+        void updated(Dictionary conf) {
+           // "conf" contains foo2=bar2, for example, and since we have set the "propagate" attribute to true, then
+           // the property will be propagated to our published service ...
+        }
+    
+        @Start
+        Map start() {
+            // Return some extra properties to be inserted along with our published properties. This map takes
+            // precedence, and may override some properties specified in our @Component annotation, or some properties
+            // propagated from our @ConfigurationDependency dependency ...
+            return new HashMap() {{ put("foo3", "bar3"); }};
+        }
+    }
+
+Here, the service MyService will be published into the OSGi registry along with the following service properties:
+* foo=bar (specified in our @Component annotation)
+* foo2=bar2 (propagated by our ConfigurationDependency dependency)
+* foo3=bar3 (specified dynamically in the map returned from our start method)
+
+Notice that properties returned by the Map take precedence over other properties, and may override some of them.
\ No newline at end of file

Added: 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=1421893&view=auto
==============================================================================
--- 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 (added)
+++ 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 Dec 14 14:29:22 2012
@@ -0,0 +1,255 @@
+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&nbsp;  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).
+
+## 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.
+
+## 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).
+
+Now we have introduced the background, here is the SpellCheck component:
+
+
+    @Component(provides={SpellChecker.class},
+               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) {
+           // 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.
+
+
+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&nbsp; 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);
+    }
+
+And here is our previous SpellChecker component, augmented with two new ServiceDependency annotations:
+
+
+    @Component(provides={SpellChecker.class},
+               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;
+    
+        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");
+        }
+    }
+
+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.
+
+## 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 ...
+
+
+    @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);
+        }
+    }
+
+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)
+        }
+    )  
+    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:
+
+
+    @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);
+        }
+    }
+
+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.
+
+## How to run the sample code
+
+* 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.
\ No newline at end of file

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-quick-tour/apache-felix-dependency-manager-using-annotations-quick-start.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/apache-felix-dependency-manager-using-annotations-quick-start.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-quick-tour/apache-felix-dependency-manager-using-annotations-quick-start.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-quick-tour/apache-felix-dependency-manager-using-annotations-quick-start.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,126 @@
+Title: Apache Felix Dependency Manager - Using Annotations - Quick Start
+
+# Quick Start
+
+This sections presents a simple "Hello World" component defined using annotations, and also explains how to build the bundle using either Bnd, Ant, or Maven.
+
+## Hello World Component
+
+
+    package org.apache.felix.dependencymanager.samples.annotation.hello;
+    
+    import org.apache.felix.dm.annotation.api.Component;
+    import org.apache.felix.dm.annotation.api.Start;
+    
+    @Component
+    public class HelloWorld {
+        @Start
+        public void activate() {
+           System.out.println("Hello world !");
+        }
+    }
+
+
+## Compiling with Bnd:
+
+The annotations must be processed at compilation phase and you have to use a special Bnd plugin (declared using the "-plugin" bnd directive):
+
+
+    Bundle-Name: Hello World Using Dependency Manager Annotations
+    Bundle-SymbolicName: org.apache.felix.dependencymanager.samples.annotation.hello
+    Import-Package: *
+    Private-Package: org.apache.felix.dependencymanager.samples.annotation.hello
+    -plugin org.apache.felix.dm.annotation.plugin.bnd.AnnotationPlugin;log=warn
+
+
+## Compiling with Ant:
+
+Since Bnd provides a Ant task, you can use the bnd directives above with the following build.xml:
+(it is assumed that directives.bnd, bnd.jar, json-20070829.jar and org.apache.felix.dependencymanager.annotation.jar are in the current directory)
+
+
+    <project name="TestDM" default="bnd">
+    	<property name="bnd" value="bnd.jar" />
+    	<property name="json" value="json-20070829.jar" />
+    	<property name="dmannot" value="org.apache.felix.dependencymanager.annotation.jar" />
+    
+    	<target name="compile">
+    		<delete dir="target/classes" quiet="yes" />
+    		<mkdir dir="target/classes" />
+    		<javac srcdir="src/main/java" destdir="target/classes" classpath="${dmannot}" />
+    	</target>
+    
+    	<target name="bnd" depends="compile">
+    		<taskdef resource="aQute/bnd/ant/taskdef.properties" classpath="${dmannot}:${bnd}:${json}" />
+    		<bnd classpath="target/classes" eclipse="false" files="directives.bnd" output="org.apache.felix.dependencymanager.samples.annotation.hello.jar" />
+    	</target>
+    </project>
+
+
+## Compiling with Maven:
+
+When compiling with Maven, you have to use the Dependency Manager Maven annotation plugin:
+
+
+    <?xml version="1.0"?>
+    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    	<modelVersion>4.0.0</modelVersion>
+    	<properties>
+    		<osgi.version>4.2.0</osgi.version>
+    	</properties>
+    	<name>Hello World Using Dependency Manager Annotations</name>
+    	<groupId>org.apache.felix</groupId>
+    	<artifactId>org.apache.felix.dependencymanager.samples.annotation.hello</artifactId>
+    	<version>3.0.0-SNAPSHOT</version>
+    	<packaging>bundle</packaging>
+    	<dependencies>
+    		<dependency>
+    			<groupId>${pom.groupId}</groupId>
+    			<artifactId>org.apache.felix.dependencymanager.annotation</artifactId>
+    			<version>3.0.0</version>
+    		</dependency>
+    	</dependencies>
+    	<build>
+    		<plugins>
+    			<plugin>
+    				<groupId>org.apache.maven.plugins</groupId>
+    				<artifactId>maven-compiler-plugin</artifactId>
+    				<configuration>
+    					<source>1.5</source>
+    					<target>1.5</target>
+    				</configuration>
+    			</plugin>
+    			<plugin>
+    				<groupId>org.apache.felix</groupId>
+    				<artifactId>maven-bundle-plugin</artifactId>
+    				<version>2.3.4</version>
+    				<extensions>true</extensions>
+    				<configuration>
+    					<instructions>
+    						<Bundle-Name>Hello World Using Dependency Manager Annotations</Bundle-Name>
+    						<Bundle-SymbolicName>org.apache.felix.dependencymanager.samples.annotation.hello</Bundle-SymbolicName>
+    						<Import-Package>*</Import-Package>
+    						<Private-Package>org.apache.felix.dependencymanager.samples.annotation.hello</Private-Package>
+    					</instructions>
+    				</configuration>
+    			</plugin>
+    			<plugin>
+    				<groupId>org.apache.felix</groupId>
+    				<artifactId>org.apache.felix.dependencymanager.annotation</artifactId>
+    				<version>3.0.0</version>
+    				<executions>
+    					<execution>
+    						<goals>
+    							<goal>scan</goal>
+    						</goals>
+    						<configuration>
+    							<log>info</log>
+    						</configuration>
+    					</execution>
+    				</executions>
+    			</plugin>
+    		</plugins>
+    	</build>
+    </project>
+

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-background.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-background.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-background.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-background.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,19 @@
+Title: Dependency Manager Background
+Excerpt: There are a couple of concepts, explained here, that help understand the dependency manager better. This page lists them.
+
+# Background
+
+There are a couple of concepts, explained here, that help understand the dependency manager better. This page lists them.
+
+## White board pattern
+
+The white board pattern presents a more efficient way to implement listeners. Instead of having listeners track sources and registering themselves with those sources, the white board pattern has the listeners register themselves as services in the OSGi service registry. When a source needs to notify listeners, it simply looks up all listener services in the registry and notifies them.
+
+The pattern is explained in great detail in (!) TODO-ref where both the traditional listener implementation and the white board implementation are compared.
+
+## Null object pattern
+
+A null object pattern (!) TODO-ref provides an object as a surrogate for the lack of an object of a given type. It essentially provides intelligent "do nothing" behavior, hiding the details from its collaborators. The pattern is also known as "Stub" or "Active Nothing".
+
+The motivation for using it is that sometimes a class that requires a collaborator does not need the collaborator to do anything. However, the class wishes to treat a collaborator that does nothing the same way it treats one that actually provides behavior.
+

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-design.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-design.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-design.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-design.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,12 @@
+Title: Dependency Manager Design
+Excerpt: The dependency manager is a dedicated component for managing dependencies. When using service trackers or listeners, a substantial amount of code needs to be written to track other services and act on changes. From a logical point of view, through a bundle you're managing one or more services. Each service can have zero or more dependencies that can either be required or optional. Required dependencies must be available before the service can even do its work, optional dependencies are used only if they're available.
+
+The dependency manager is a dedicated component for managing dependencies. When using service trackers or listeners, a substantial amount of code needs to be written to track other services and act on changes. From a logical point of view, through a bundle you're managing one or more services. Each service can have zero or more dependencies that can either be required or optional. Required dependencies must be available before the service can even do its work, optional dependencies are used only if they're available.
+
+So as a programmer, you just want to specify these services and dependencies. The design of the dependency manager focusses on this. The class diagram below shows the DependencyActivatorBase, which is an implementation of BundleActivator. You implement the init() and destroy() methods which are directly related to the start() and stop() methods of the activator. The DependencyManager, which is passed as an argument to these methods, can then be used to define the services and dependencies. It takes care of tracking and activating the service once the dependencies have been resolved.
+
+(!) TODO class diagram
+
+Effectively, this mechanism extends the state diagram for a bundle, as shown in the OSGi specification. The overall state diagram can now be seen in the figure below. As soon as the bundle is in the active state, it starts tracking required dependencies. When they're resolved, the bundle starts tracking the optional dependencies.
+
+(!) TODO state diagram

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-shell.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-shell.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-shell.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-shell.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,21 @@
+Title: Dependency Manager Shell
+Excerpt: The shell bundle for the dependency manager extends the shell with one new command called "dm". This command can be used to list all services and dependencies that are under control of the dependency manager.
+
+# Introduction
+
+The shell bundle for the dependency manager extends the shell with one new command called "dm". This command can be used to list all services and dependencies that are under control of the dependency manager.
+
+You can use the following arguments to influence the output:
+- "notavail" will only list services that are not available for some reason, which can be helpful when debugging when you're wondering why certain services do not appear.
+- "compact" will use a more compact output format, which has the downside of being a bit more cryptic.
+- "nodeps" will only list the services, but not their dependencies.
+- <bundleid> ... a list of one or more bundle identifiers in case you want to restrict the output to those bundles only.
+
+# Usage
+
+
+    
+
+
+
+    

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-usage.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-usage.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-usage.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/dependency-manager-usage.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,218 @@
+Title: Dependency Manager Usage
+Excerpt: Let's look at how to use this implementation. When developing an OSGi bundle that uses and possibly registers services, there are two classes in particular we need to implement. The first one is the bundle activator which controls the life-cycle of the bundle. The second one is the actual service implementation.
+
+# Usage
+
+Let's look at how to use this implementation. When developing an OSGi bundle that uses and possibly registers services, there are two classes in particular we need to implement. The first one is the bundle activator which controls the life-cycle of the bundle. The second one is the actual service implementation.
+
+When using the dependency manager, your bundle activator is a subclass of DependencyActivatorBase. The following paragraphs will explain how to specify a service and its dependencies. Subsequently, some more advanced scenarios will be covered that involve listening to dependency and service state changes and interacting with the OSGi framework from within your service implementation.
+
+## Registering a service
+
+Registering a service is done using a custom implementation of the bundle activator, DependencyActivatorBase, which requires you to implement two methods: init and destroy.
+
+Each bundle can specify zero or more services in the init method. Services can optionally have an interface and properties with which they're registered into the service registry. Registering a service involves creating a new service and adding it to the dependency manager. You then specify the interface as well as the implementation, as shown in the example.
+
+
+    public HttpActivator extends DependencyActivatorBase {
+      public void init(BundleContext ctx, DependencyManager manager)
+                                      throws Exception {
+        Properties props = new Properties();
+        props.put("port", "8080");
+        manager.add(createService()
+          .setInterface(WebService.class.getName(), props)
+          .setImplementation(WebServiceImpl.class));
+      }
+      public void destroy(BundleContext ctx, DependencyManager manager)
+                                      throws Exception {
+        // cleaned up automatically
+      }
+    }
+
+
+There are a couple of alternatives that need some clarification. First of all, you might not have a public interface at all, so the setInterface call is optional. Like in OSGi itself, you can also specify multiple service interfaces in an array of strings. For the implementation you have two choices. You can either specify the class of the implementation, in which case this class needs to have a default, no-args constructor and the dependency manager will use lazy instantiation or you can specify an instance you've already created. More on the life-cycle of the service implementation can be found in the next paragraph.
+
+## Specifying service dependencies
+
+Dependencies can either be required or optional. Required dependencies need to be resolved before the service can even become active. Optional dependencies can appear and disappear while the service is active. The example demonstrates how both are specified in the activator.
+
+
+        manager.add(createService()
+          .setInterface(WebService.class.getName(), null)
+          .setImplementation(WebServiceImpl.class)
+          .add(createServiceDependency()
+            .setService(ConfigurationAdmin.class, null)
+            .setRequired(true))
+          .add(createServiceDependency()
+            .setService(LogService.class, null)
+            .setRequired(false))
+
+
+## Specifying configuration dependencies
+
+Configuration dependencies specified here are by definition required. The reason for this is that if you need an optional configuration, simply registering as a ManagedService(Factory) and implementing updated(Dictionary) works fine. For required configuration dependencies, you can use code along these lines:
+
+
+        manager.add(createService()
+          .setInterface(HttpServlet.class.getName(), null)
+          .setImplementation(MyServlet.class)
+          .add(createConfigurationDependency()
+            .setPid("org.apache.felix.myservlet")
+            .setPropagate(true))
+
+
+As you can see, you do not need to register as ManagedService yourself. You do need to implement ManagedService in your implementation though. When implementing the updated() method, take the following things into account:
+1. updated() will be called after you are instantiated, but before init() and start() are invoked, or service dependencies are injected, so make sure this method works like this;
+1. if updated() executes normally, this dependency will become resolved;
+1. if updated() throws a ConfigurationException, you are signalling the configuration is invalid and the dependency won't be resolved (or it will become unresolved if it previously was);
+1. if updated() gets a null configuration, the dependency will become unresolved too;
+
+In some cases, you might want to propagate configuration settings to your service properties. In that case, use the setPropagate(true) method to enable automatic property propagation (the default is false). That means any properties you specify yourself and any properties you get from ConfigurationAdmin will be merged, and your service will automatically be updated every time these properties change.
+
+## Implementing the service
+
+The service implementation is pretty straightforward. Basically any class that implements the service interface can be used here. Two aspects of the implementation deserve some attention though: the life-cycle model and the service dependencies.
+
+Depending on how the service was specified in the activator it is either instantiated as soon as all required dependencies become available or it was already instantiated when the activator started. The service then goes through a number of states, where each transition includes the invocation of a method on the service implementation. The default names of these methods are init, start, stop and destroy but these can be altered. As a developer, all you need to do is specify any of these methods in your service implementation and they will be invoked.
+
+
+    public class WebServiceImpl implements WebService {
+      public void init() {
+      }
+      public void start() {
+      }
+      public void stop() {
+      }
+      public void destroy() {
+      }
+    }
+
+
+Upon activation, the service implementation should initialize its internal state in the init() method and establish connections with other services in the start() method.
+
+The dependency manager will automatically fill in any references to required dependencies that are specified as attributes. The same goes for optional dependencies if they are available. If not, those will be implemented by a null object (!) TODO-ref. In short, this allows you to simply use these interfaces as if they were always available. A good example of this is the LogService. If it's available, we want to use it for logging. If not, we want to simply ignore log messages. Normally, you'd need to check a reference to this service for null before you can use it. By using a null object, this is not necessary anymore.
+
+
+    public class WebServiceImpl implements WebService {
+      private volatile ConfigurationAdmin configAdminSvc;
+      private volatile LogService logSvc;
+      
+      public void loadSettings() {
+        logSvc.log(LogService.LOG_INFO, "Loading settings.");
+        // do stuff here
+      }
+    }
+
+
+## Using an instance factory
+
+(!) TODO will explain how to provide a factory class and method that will be used to create the service implementation.
+
+## Using compositions
+
+Sometimes, a service implementation consists of more than a single instance. Instead, it can be a composition of a number of instances. That might also mean that you need dependencies injected into more than one instance. If that is the case, you can provide a list of instances to use for dependency injection yourself.
+
+To do that, you can specify the name of a method that will return a list of instances, like this:
+
+
+        manager.add(createService()
+          .setImplementation(MainServiceImpl.class)
+          .setComposition("getInstances"));
+
+
+Whenever dependencies need to be injected, the dependency manager will query the method and try to inject dependencies into all the instances this method returns (as an Object[]({{ refs..path }})). For example:
+
+
+    public class MainServiceImpl {
+        private SubComponentA m_compA;
+        private SubComponentB m_compB;
+    
+        public MainServiceImpl() {
+            m_compA = new SubComponentA();
+            m_compB = new SubComponentB();
+        }
+    
+        public Object[] getInstances() {
+            return new Object[] { this, m_compA, m_compB };
+        }
+    }
+
+
+## Listening to service dependencies
+
+Optionally, a service can define callbacks for each dependency. These callbacks are invoked whenever a new dependency is discovered, an existing dependency changes or disappears. They allow you to track these dependencies. This can be very useful if you, for example, want to implement the white board pattern.
+
+
+        manager.add(createService()
+          .setImplementation(DeviceListener.class)
+          .add(createServiceDependency()
+            .setService(Device.class, null)
+            .setCallbacks("added", "changed", "removed")
+            .setRequired(false));
+
+
+
+    public class DeviceListener {
+      public void added(ServiceReferende ref, Object service) {
+      }
+      public void changed(ServiceReference ref, Object service) {
+      }
+      public void removed(ServiceReference ref, Object service) {
+      }
+    }
+
+
+There are actually several signatures you can use for the callback methods. The dependency manager will search for them in this order (we use a dependency on Device as an example):
+1. ServiceReference, Device
+1. ServiceReference, Object
+1. ServiceReference
+1. Device
+1. Object
+1. (void)
+
+The search ends when the first signature in this list is found. That method will actually be invoked.
+
+## Listening to the service state
+
+If you're interested in the state of a service, you can register a service state listener with the service of interest. It will be notified whenever the service is starting, started, stopping and stopped.
+
+
+        Service s = createService()
+          .setInterface(WebService.class.getName(), null)
+          .setImplementation(WebServiceImpl.class);
+        s.setStateListener(new ServiceStateListener() {
+            public void starting(Service s) {
+            }
+            public void started(Service s) {
+            }
+            public void stopping(Service s) {
+            }
+            public void stopped(Service s) {
+            }
+          });
+        manager.add(s);
+
+
+## Interacting with OSGi
+
+Although interaction of the service implementation with the OSGi framework has nothing to do with dependency managemement, the dependency manager does offer support for communicating with the framework.
+
+Normally, your service implementation does not have to contain any OSGi specific classes or code. As shown before, even references to other services can be used without dealing with OSGi specifics. Sometimes, this is an advantage, since the service implementation can easily be reused in a different service oriented framework. However, there are times when you do want to access, for example, the BundleContext because you want to interact with the framework.
+
+For these cases, you can specify one or two members to get direct access to:
+1. the BundleContext that provides you with an interface to the OSGi framework;
+1. the ServiceRegistration of the service that was registered, provided you have registered a public service interface.
+
+
+    public class WebServiceImpl implements WebService {
+      private BundleContext ctx;
+      private ServiceRegistration svcReg;
+    
+      //  
+    }
+
+
+## Dynamic dependencies
+
+Most of the time, the dependency definitions are static. You define them when the bundle starts and they stay the same throughout the life-cycle of the bundle. However, in some cases you might want to add dependencies to a service afterwards. For example, you might want to start tracking a service with specific properties. To do this, simply add the dependency in the same way as you would have done in the init() method.
+

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-deployment-admin.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-deployment-admin.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-deployment-admin.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-deployment-admin.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,7 @@
+Title: Apache Felix Deployment Admin
+
+# Apache Felix Deployment Admin
+
+This project implements the OSGi Deployment Admin specification; please consult the OSGi Compendium Specification for more information. Currently, no release of this subproject is available, but the source is available in our SVN repository here:
+
+    [http://svn.apache.org/repos/asf/felix/trunk/deploymentadmin/](http://svn.apache.org/repos/asf/felix/trunk/deploymentadmin/)
\ No newline at end of file

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-event-admin.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-event-admin.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-event-admin.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-event-admin.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,160 @@
+Title: Apache Felix Event Admin
+
+# Apache Felix Event Admin
+
+The Event Admin Service Specification, part of the OSGi Compendium specification, defines a general inter-bundle communication mechanism. The communication conforms to the popular publish/subscribe paradigm and can be performed in a synchronous or asysnchronous manner.
+
+The main components in a publish/subscribe communication are:
+
+* *Event Publisher* - sends events or messages related to a specific *topic*
+* *Event Handler* (or *Subscriber*) - expresses interest in one or more topics and receives all the messages belonging to such topics.
+
+Events are composed of two attributes:
+
+* a *topic* defining the nature of the event; topic names are usually arranged in a hierarchical namespace, where slashes are used to separate the levels (i.e. "org/osgi/framework/FrameworkEvent/STARTED") and
+* a set of *properties* describing the event.
+
+## Creating an Event Publisher
+
+An event publisher is a simple Java class that creates events and sends them using the `EventAdmin` service interface, for example:
+
+
+        public void reportGenerated(Report report, BundleContext context)
+        {
+            ServiceReference ref = context.getServiceReference(EventAdmin.class.getName());
+            if (ref != null)
+            {
+                EventAdmin eventAdmin = (EventAdmin) context.getService(ref);
+                
+                Dictionary properties = new Hashtable();
+                properties.put("title", report.getTitle());
+                properties.put("path" , report.getAbsolutePath());
+                properties.put("time", System.currentTimeMillis());
+                
+                Event reportGeneratedEvent = new Event("com/acme/reportgenerator/GENERATED", properties);
+                
+                eventAdmin.sendEvent(reportGeneratedEvent);
+            }
+        }
+
+
+The `EventAdmin.sendEvent()` method sends the `Event` object synchronously. To send it asynchronously, use the `EventAdmin.postEvent()` method, such as:
+
+
+                //..		
+                Event reportGeneratedEvent = new Event("com/acme/reportgenerator/GENERATED", properties);
+                eventAdmin.postEvent(reportGeneratedEvent);
+
+
+## Creating an Event Handler
+
+Creating an event handler is as simple as implementing the `EventHandler` interface:
+
+
+    public class ReportEventHandler implements EventHandler
+    {
+        public void handleEvent(Event event)
+        {
+            String reportTitle = (String) event.getProperty("title");
+            String reportPath = (String) event.getProperty("path");
+            
+            sendReportByEmail(reportTitle, reportPath);
+        }
+        
+        //..
+
+
+## Registering an Event Handler
+
+To receive event notifications, the event handler must be registered as a OSGi service under the object class `org.osgi.service.event.EventHandler`. When registering the service, a `String\[\]({{ refs..path }})` property named `*EVENT_TOPIC*` must be specified; this property describes the list of topics in which the event handler is interested. For example:
+
+
+            String[] topics = new String[] {
+                "com/acme/reportgenerator/GENERATED"
+            };
+            
+            Dictionary props = new Hashtable();
+            props.put(EventConstants.EVENT_TOPIC, topics);
+            bundleContext.registerService(EventHandler.class.getName(), new ReportEventHandler() , props);
+
+
+It is possible to use '*' as a wildcard in the final character of the EVENT_TOPIC, like in this example:
+
+
+
+            String[] topics = new String[] {
+                "com/acme/reportgenerator/*"
+            };
+            
+            Dictionary props = new Hashtable();
+            props.put(EventConstants.EVENT_TOPIC, topics);
+            bundleContext.registerService(EventHandler.class.getName(), new ReportEventHandler() , props);
+
+
+Finally, it is possible to specify an additional `EVENT_FILTER` property to filter event notifications; the filter expression follows, the normal LDAP syntax:
+
+
+            String[] topics = new String[] {
+                "com/acme/reportgenerator/GENERATED"
+            };
+            
+            Dictionary props = new Hashtable();
+            props.put(EventConstants.EVENT_TOPIC, topics);
+            props.put(EventConstants.EVENT_FILTER, "(title=samplereport)");
+            bundleContext.registerService(EventHandler.class.getName(), new ReportEventHandler() , props);
+
+
+## OSGi Events
+
+Every OSGi framework sends (asynchronously) a number of events that can be captured by any bundle.
+
+### Framework Events
+
+* org/osgi/framework/BundleEvent/STARTED
+* org/osgi/framework/BundleEvent/ERROR
+* org/osgi/framework/BundleEvent/PACKAGES_REFRESHED
+* org/osgi/framework/BundleEvent/STARTLEVEL_CHANGED
+* org/osgi/framework/BundleEvent/WARNING
+* org/osgi/framework/BundleEvent/INFO
+
+### Bundle Events
+
+* org/osgi/framework/BundleEvent/INSTALLED
+* org/osgi/framework/BundleEvent/STARTED
+* org/osgi/framework/BundleEvent/STOPPED
+* org/osgi/framework/BundleEvent/UPDATED
+* org/osgi/framework/BundleEvent/UNINSTALLED
+* org/osgi/framework/BundleEvent/RESOLVED
+* org/osgi/framework/BundleEvent/UNRESOLVED
+
+The followig properties are always present in a bundle event object:
+
+* *bundle.id*
+* *bundle.symbolicName*
+
+### Service Events
+
+* org/osgi/framework/ServiceEvent/REGISTERED
+* org/osgi/framework/ServiceEvent/MODIFIED
+* org/osgi/framework/ServiceEvent/UNREGISTERING
+
+The following properties are always present in a service event object:
+
+* *service*
+* *service.id*
+* *service.pid*
+
+Each of the aforementioned events actually contains a wider set of properties. Check the OSGi Compendium specification, section 113.6, for a complete list.
+
+## Configuration
+
+The Apache Felix Event Admin implementation is trying the deliver the events as fast as possible. Events sent from different threads are sent in parallel. Events from the same thread are sent in the order they are received (this is according to the spec).
+A timeout can be configured which is used for event handlers. If an event handler takes longer than the configured timeout to process an event, it is blacklisted. Once a handler is in a blacklist, it doesn't get sent any events anymore.
+The Felix Event Admin can be configured either through framework properties or through the configuration admin. This is a list of configuration properties:
+|Function|Property Name|Type and Default|Description|
+|--|--|--|
+|Cache Size|org.apache.felix.eventadmin.CacheSize|Integer, 30|The size of various internal caches. The default value is 30. Increase in case of a large number (more then 100) of services. A value less then 10 triggers the default value.|
+|Thread Pool Size|org.apache.felix.eventadmin.ThreadPoolSize|Integer, 10|The size of the thread pool. The default value is 10. Increase in case of a large amount of synchronous events where the event handler services in turn send new synchronous events in the event dispatching thread or a lot of timeouts are to be expected. A value of less then 2 triggers the default value. A value of 2 effectively disables thread pooling.|
+|Timeout|org.apache.felix.eventadmin.Timeout|Integer, 5000|The black-listing timeout in milliseconds. The default value is 5000. Increase or decrease at own discretion. A value of less then 100 turns timeouts off. Any other value is the time in milliseconds granted to each event handler before it gets blacklisted.|
+|Require Topic|org.apache.felix.eventadmin.RequireTopic|Boolean, true|Are event handlers required to be registered with a topic? This is enabled by default. The specification says that event handlers must register with a list of topics they are interested in. Disabling this setting will enable that handlers without a topic are receiving all events (i.e., they are treated the same as with a topic=*).|
+|Ignore Timeouts|org.apache.felix.eventadmin.IgnoreTimeout|String, empty|Configure event handlers to be called without a timeout. If a timeout is configured by default all event handlers are called using the timeout. For performance optimization it is possible to configure event handlers where the timeout handling is not used - this reduces the thread usage from the thread pools as the timout handling requires an additional thread to call the event handler. However, the application should work without this configuration property. It is a pure optimization! The value is a list of strings. If a string ends with a dot, all handlers in exactly this package are ignored. If the string ends with a star, all handlers in this package and all subpackages are ignored. If the string neither ends with a dot nor with a start, this is assumed to define an exact class name.|



Mime
View raw message