felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r1421893 [3/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-config-admin.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-config-admin.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-config-admin.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-config-admin.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,220 @@
+Title: Apache Felix Config Admin
+
+# Configuration Admin Service
+
+The OSGi Componendium Configuration Admin Service specifies a service, which allows for easy management of configuration data for configurable components. Basicaly configuration is a list of name-value pairs. Configuration is managed by management applications by asking the Configuration Admin Service for such configuration. After updating the configuration, it is sent back to the Configuration Admin Service. The Configuration Admin Service is like a central hub, which cares for persisting this configuration and also for distributing the configuration to interested parties. One class of such parties are the components to be configured. These are registered as `ManagedService` services. There is also a notion of `ManagedServiceFactory`, which allows for multiple configurations of the same kind to be applied.
+
+For more information, I suggest you read Chapter 104, Configuration Admin Service Specification, of the OSGi Compendium Services Specification book. IMHO this is worth reading.
+
+For a starter this page sets out to describe how you can create a component, which is interested in some configuration. As such this page is at its very beginning just highlighting the simplest of all cases: A single component being interested in its configuration.
+
+
+## `ManagedService` Example
+
+Consider you have requirement for some configuration, say the line length of a pretty printer. You want to have this configurable through configuration admin.
+
+You need the following parts:
+
+ * A service PID identifying the configuration
+ * A `ManagedService` to receive the configuration
+ * Name(s) for the configuration property/ies
+
+The PID is just a string, which must be globally unique. Assuming a simple case where your PrettyPrinter configurator receives the configuration has a unique class name, you may well use that name. So lets assume, our `ManagedService` is called `org.sample.PrettyPrinterConfigurator` and that name is also used as the PID. For more information on the Service PID, refer to Section 104.3, The Persistent Identity of the OSGi Compendium Services Specification.
+
+The class would be:
+
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>PrettyPrinterConfigurator.java</B></DIV><DIV class="codeContent panelContent">
+       package org.sample;
+       class PrettyPrinterConfigurator implements ManagedService {
+           public void update(Dictionary props)
+               throws ConfigurationException {
+               if (props == null) {
+                   // no configuration from configuration admin
+                   // or old configuration has been deleted
+               } else {
+                   // apply configuration from config admin
+               }
+           }
+       }
+
+
+Now, in your bundle activator's start() method you register the `PrettyPrinterConfigurator` as a `ManagedService`:
+
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>PrettyPrinterActivator.java</B></DIV><DIV class="codeContent panelContent">
+    ...
+    private ServiceRegistration ppcService;
+    public void start(BundleContext context) {
+        Dictionary props = new Hashtable();
+        props.put("service.pid", "org.sample.PrettyPrinterConfigurator");
+        ppcService = context.registerService(ManagedService.class.getName(),
+            new PrettyPrinterConfigurator(), props);
+    }
+    public void stop(BundleContext context) {
+        if (ppcService != null) {
+            ppcService.unregister();
+            ppcService = null;
+        }
+    }
+    ...
+
+
+That's more or less it. You may now go on to use your favourite tool to create and edit the configuration for the `PrettyPrinterConfigurator`, for example something like this:
+
+
+    Configuration config = configurationAdmin.getConfiguration(
+        "org.sample.PrettyPrinterConfigurator");
+    Dictionary props = config.getProperties();
+    
+    // if null, the configuration is new
+    if (props == null) {
+        props = new Hashtable();
+    }
+    
+    // set some properties
+    props.put(..., ...);
+    
+    // update the configuration
+    config.update(props);
+
+
+After the call to `update` the Configuration Admin service persists the new configuration data and sends an update to the `ManagedService` registered with the service PID `org.sample.PrettyPrinterConfigurator`, which happens to be our `PrettyPrinterConfigurator` class as expected.
+
+
+## ManagedServiceFactory example
+
+Registering a service as ManagedServiceFactory means that it will be able to receive several different configuration dictionaries; that's particularly useful when we want to create a Service Factory, that is, a service responsible for creating multiple instances of a specific service.
+
+A ManagedServiceFactory service needs to implement the ManagedServiceFactory interface, as showed in the example.
+
+
+    public class SmsSenderFactory implements ManagedServiceFactory
+    {	
+    	Map existingServices = new HashMap();
+    	
+    	public void updated(String pid, Dictionary dictionary) throws ConfigurationException 
+    	{
+    		// invoked when a new configuration dictionary is assigned
+    		// to service 'pid'. 
+    		if (existingServices.containsKey(pid))  //the service already exists
+    		{
+    			MyService service = (MyService) existingServices.get(pid);
+    			service.configure(dictionary);
+    		}
+    		else //configuration dictionary for a new service
+    		{
+    			MyService service = createNewServiceInstance();
+    			service.configure(dictionary);
+    			existingServices.put(pid, service);
+    		}
+    	}
+    	
+    	public void deleted(String pid) 
+    	{
+    		// invoked when the service 'pid' is deleted
+    		existingServices.remove(pid);
+    	}
+    
+    	public String getName() 
+    	{
+    		return "test.smssenderfactory";
+    	}
+    }
+
+
+The example above shows that, differently from the ManagedService, the ManagedServiceFactory is designed to manage multiple instances of a service. In fact, the `update` method accept a `pid` and a `Dictionary` as arguments, thus allowing to associate a certain configuration dictionary to a particular service instance (identified by the `pid`).
+
+Note also that the ManagedServiceFactory interface requires to implement (besides the `getName` method) a `delete` method: this method is invoked when the Configuration Admin Service asks the ManagedServiceFactory to delete a specific service instance.
+
+The registration of a `ManagedServiceFactory` follows the same steps of the `ManagedService` example:
+
+
+    private ServiceRegistration factoryService;
+    public void start(BundleContext context) {
+        Dictionary props = new Hashtable();
+        props.put("service.pid", "test.smssenderfactory");
+        factoryService = context.registerService(ManagedServiceFactory.class.getName(),
+            new SmsSenderFactory(), props);
+    }
+    public void stop(BundleContext context) {
+        if (factoryService != null) {
+            factoryService.unregister();
+            factoryService = null;
+        }
+    }
+    ...
+
+
+Finally, using the ConfigurationAdmin interface, it is possible to send new or updated configuration dictionaries to the newly created ManagedServiceFactory:
+
+
+    public class Activator implements BundleActivator 
+    {   
+        private List configurationList = new ArrayList();  
+    	 
+        public void start(BundleContext bundleContext) throws Exception 
+        {  
+            ServiceReference configurationAdminReference = 
+                bundleContext.getServiceReference(ConfigurationAdmin.class.getName());  
+                  
+            if (configurationAdminReference != null) 
+            {  
+                ConfigurationAdmin confAdmin = (ConfigurationAdmin) bundleContext.getService(configurationAdminReference);  
+                  
+                Configuration configuration = confAdmin.createFactoryConfiguration("test.smssenderfactory", null);  
+                Dictionary properties = createServiceProperties();
+                configuration.update(properties);  
+                  
+                //Store in the configurationList the configuration object, the dictionary object
+                //or configuration.getPid()  for future use  
+                configurationList.add(configuration);  
+            }  
+        }   
+    }  
+
+
+
+## Apache Felix Implementation Details
+
+The Apache Felix implementation of the Configuration Admin Service specification has a few specialities, which may be of interest when deploying it. These are described here.
+
+
+### Configuration Properties
+
+The Apache Felix implementation is configurable with Framework properties. Here is a short table listing the properties. Please refer to the later sections for a description of these properties.
+
+| Property | Type | Default Value | Description |
+|--|--|--|--|
+| `felix.cm.loglevel` | int | `2` | Logging level to use in the absence of an OSGi LogService. See the *Logging* section below. |
+| `felix.cm.dir` | String | `BundleContext.getDataFile("config")` | Location of the Configuration Admin configuration files. See the *Configuration Files* section below. |
+
+### Logging
+
+Logging goes to the OSGi LogService if such a service is registered int the OSGi framework. If no OSGi LogService is registered, the log output is directed to the Java platform standard error output (`System.err`).
+
+To limit the output in the absence of an OSGi LogService, the `felix.cm.loglevel` framework property may be set to an integer value limiting the level of the log messages actually written: Only messages whose level is lower than or equal to the limit is actually written. All other messages are discarded.
+
+The log levels correspond to the predefined log levels of the OSGi Log Service Specification as listed in the following table:
+
+| Level Number | LogService Constant | Remark |
+|--|--|--|
+| 1 | LOG_ERROR | Used for error messages |
+| 2 | LOG_WARNING | Used for warning messages. This is the default value of the `felix.cm.loglevel` property if it is not set or if the value cannot be converted to an integer. |
+| 3 | LOG_INFO | Used for informational messages |
+| 4 | LOG_DEBUG | Used for debug messages |
+
+*Note*: The `felix.cm.loglevel` property is ignored if an OSGi LogService is actually used for logging because it is then the responsibility of the LogService to limit the actual log output.
+
+
+### Configuration Files
+
+By default the Apache Felix Configuration Admin Implementation stores the configuration data in the platform filesystem. The location of the configuration data can be configured with the `felix.cm.dir` framework property.
+
+The resolution of the location using the `felix.cm.dir` and the `BundleContext` is implemented according to the following algorithm.
+
+1. If the `felix.cm.dir` property is not set, a directory named `config` is used inside the persistent storage area of the Apache Felix Configuration Admin Service bundle is used. This is the default behaviour.
+1. If the `felix.cm.dir` property is not set and the framework does not support persistent storage area for bundles in the filesystem, the `config` directory is used in the current working directory as specified in the `user.dir` system property is assumed.
+1. Otherwise the `felix.cm.dir` property value is used as the directory name to take the configuration data.
+
+The result of these steps may be a relative file. In this case and if the framework provides access to persistent storage area, the directory name is resolved as being inside the persistent storage area. Otherwise the directory name is resolved to an absolute path calling the File.getAbsoluteFile() method.
+
+If a non-directory file exists as the location found in the previous step or the named directory (including any parent directories) cannot be created, the configuration data cannot be stored in the filesystem. Generally this will result in failure to store configuration data at all, except if there is a `org.apache.felix.cm.PersistenceManager` service registered, which is then used.

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,15 @@
+Title: Apache Felix Dependency Manager
+
+# Apache Felix Dependency Manager
+
+{include:Apache Felix Dependency Manager - Introduction}
+
+## Table of Contents
+
+* [Background]({{ refs.apache-felix-dependency-manager-background.path }}) explains the problem being solved and the main design goals.
+* [Getting Started]({{ refs.apache-felix-dependency-manager-getting-started.path }}) helps you with the basic concepts by example.
+* [Migrating from Earlier Versions]({{ refs.apache-felix-dependency-manager-migrating-from-earlier-versions.path }}) explains the differences and migration options.
+* [OSGi Design Patterns]({{ refs.apache-felix-dependency-manager-osgi-design-patterns.path }}) explains the more advanced design patterns available.
+* [Reference Guide]({{ refs.apache-felix-dependency-manager-reference-guide.path }}) a full reference guide to lookup all implementation details.
+* [Using Annotations]({{ refs.apache-felix-dependency-manager-using-annotations.path }}) for declaring your service components using DependencyManager annotations.
+* [Building Dependency Manager]({{ refs.apache-felix-dependency-manager-how-to-build.path }}) explains how to build Dependency Manager bundles from trunk.
\ No newline at end of file

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-background.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-background.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-background.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-background.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,26 @@
+Title: Apache Felix Dependency Manager - Background
+
+## Background
+
+In an OSGi framework, services are deployed using bundles and these bundles feature two types of dependencies: 
+1. Package dependencies. A bundle can export a package which others import. These dependencies, although dynamic, are relatively easy to handle and the whole resolution process is handled by the OSGi framework for you.
+1. Service dependencies. Services, implemented by components inside of bundles, can have their own life cycle within that of their containing bundle and therefore can be registered and unregistered at any time. Other components often depend on these services and need to deal with changes in their availability. 
+
+When you look at dependency management, there are two aspects you need to take into account: 
+
+The first is managing software configurations. This means you need to manage the dependencies from a configuration standpoint. What you are managing are bundles, since those are the units of deployment. What you need to manage are the package and service dependencies between bundles. Package dependencies are always visible by examining the bundle manifest and when a bundle is installed the framework will try to resolve such dependencies before that bundle can even be started. Service dependencies are only optionally described in the manifest by a list of services a bundle might export as well as a list it might use (import). The words 'optionally' and 'might' already indicate that these aren't things we can depend on. Even worse, these keywords have by now been deprecated. Besides that, the framework doesn't have to perform any checks on these attributes.
+
+The second is managing service dependencies at runtime. As mentioned before, a service oriented architecture is dynamic by design, so your implementation should be able to deal with this. Bundles can start in any order and any service can go away or be replaced by a different implementation at any point in time. OSGi itself offers basic assistance for tracking services. You can track them yourself by registering as a service listener. A slightly more advanced way is to create a service tracker, which you can subsequently query, or have it notify you on changes. All of these are too low-level to be good building blocks for developers.
+
+In real implementations, you are probably going to track multiple services. Using service trackers in such a scenario has the tendency to result in dependency logic that is entangled in the implementation instead of being expressed in a declarative way. Using a declarative way to specify dependencies has clear advantages when it comes to monitoring and managing them, a task that becomes more and more important in modern, federated, service oriented environments.
+
+The Dependency Manager provides you with the right building blocks to declaratively specify dependencies using a straightforward Java API that is easy to maintain and refactor.
+
+### Design Goals
+
+The goals that drove the design of the dependency manager are:
+* Provide a clean separation between a component implementation and the "glue" that binds it to the OSGi framework. The component implementation should not have to contain any OSGi specific code. In other words, it should be a POJO (Plain Old Java Object).
+* Minimize the amount of code that needs to be written. The specification and management of dependencies should be automated as much as possible, whilst still providing enough flexibility to customize the system.
+* Be extensible. Even though the core bundle provides a lot of different dependencies already, you should be able to add your own types of dependencies easily.
+* Easy to monitor and debug. Being a dynamic system, it's important to be able to see what the state of all components and dependencies are at any point in time.
+* Supporting powerful high level design patterns. When building real-world applications, more complex patterns need to be used, such as aspects and adapters. Support for these needs to be built into the core.
\ No newline at end of file

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-getting-started.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-getting-started.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-getting-started.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-getting-started.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,195 @@
+Title: Apache Felix Dependency Manager - Getting Started
+
+## Getting Started
+
+When developing an OSGi bundle that has dependencies and possibly registers services, there are two classes in particular we need to implement:
+1. The bundle activator which controls the life-cycle of the bundle.
+1. The actual component implementation, which can be a POJO.
+
+When using the dependency manager, your bundle activator is a subclass of `DependencyActivatorBase`. It needs to implement two life cycle methods: `init` and `destroy`. Both methods take two arguments: `BundleContext` and `DependencyManager`. The latter is your interface to the declarative API you can use to define your components and dependencies.
+
+The following paragraphs will show various examples that explain how to do this. Subsequently, some more advanced scenarios will be covered that involve listening to dependency and component state changes and interacting with the OSGi framework from within your component implementation.
+
+### Registering a service
+
+The first example is about registering a service. We extend `DependencyActivatorBase` and in the init method we use the reference to the `DependencyManager` to create and add a component. For this component we subsequently set its service interface and implementation. In this case the interface is the `Store` interface, the second parameter, null, allows you to provide properties along with the service registration. For the implementation, we only mention the `Class` of the implementation, which means the dependency manager will lazily instantiate it. In this case, there is not much point in doing that because the component has no dependencies, but if it had, the instantiation would only happen when those dependencies were resolved.
+
+Notice that the dependency manager API uses method chaining to create a more or less "fluent" API that, with proper indentation, is very easy to read.
+
+
+    public class Activator extends DependencyActivatorBase {
+        public void init(BundleContext context, DependencyManager manager) throws Exception {
+            manager.add(createComponent()
+                .setInterface(Store.class.getName(), null)
+                .setImplementation(MemoryStore.class)
+            );
+        }
+        
+        public void destroy(BundleContext context, DependencyManager manager) throws Exception {}
+    }
+
+
+This is the service interface. Nothing special here.
+
+
+    public interface Store {
+        public void put(String key, Object value);
+        public Object get(String key);
+    }
+
+
+And finally the implementation. Again, this is just a POJO, there is no reference here to any OSGi or dependency manager specific class or annotation.
+
+
+    public class MemoryStore implements Store {
+        private Map m_map = new HashMap();
+    
+        public Object get(String key) {
+            return m_map.get(key);
+        }
+    
+        public void put(String key, Object value) {
+            m_map.put(key, value);
+        }
+    }
+
+
+### Depending on a service
+
+Our second example is that of a component that depends on two other services: our `Store` from the previous example and the standard OSGi `LogService`. Looking at the code, there is a small but important difference between the two: `Store` is a required dependency and `LogService` is not. This means that our component really needs a store to work, but if there is no logging available, it can work without. Also note that this component has no `setInterface` method, which simply means it is not itself a service. This is perfectly fine.
+
+
+    public class Activator extends DependencyActivatorBase {
+        public void init(BundleContext context, DependencyManager manager) throws Exception {
+            manager.add(createComponent()
+                .setImplementation(DataGenerator.class)
+                .add(createServiceDependency()
+                    .setService(Store.class)
+                    .setRequired(true)
+                )
+                .add(createServiceDependency()
+                    .setService(LogService.class)
+                    .setRequired(false)
+                )
+            );
+        }
+        
+        public void destroy(BundleContext context, DependencyManager manager) throws Exception {}
+    }
+
+
+Now let's look at our POJO. There are a couple of interesting things to explain. First of all, our dependencies are declared as fields, and they don't even have setters (or getters). When the dependency manager instantiates our class, it will (through reflection) inject the dependencies so they are just available for our class to use. That is also the reason these fields are declared as volatile: to make sure they are visible to all threads traversing our instance.
+
+One final note, since we defined our `LogService` dependency as optional, it might not be available when we invoke it. Still, the code does not contain any checks to avoid a null pointer exception. It does not need to, since the dependency manager makes sure to inject a null object when the real service is not available. The null object can be invoked and will do nothing. For a lot of cases that is good enough, but for those cases where it is not, our next example introduces callbacks that notify you of changes.
+
+
+    public class DataGenerator {
+        private volatile Store m_store;
+        private volatile LogService m_log;
+        
+        public void generate() {
+            for (int i = 0; i < 10; i++) {
+                m_store.put("#" + i, "value_" + i);
+            }
+            m_log.log(LogService.LOG_INFO, "Data generated.");
+        }
+    }
+
+
+### Tracking services with callbacks
+
+Sometimes, simply injecting services does not give you enough control over a dependency because you might want to track more than one, or you might want to execute some code on changes. For all those cases, callbacks are your friends. Since one of our goals is to not introduce any kind of API in our POJO, callbacks are declared by specifying their method names instead of through some interface. In this case, we have a dependency on `Translator` services, and we define `added` and `removed` as callbacks.
+
+
+    public class Activator extends DependencyActivatorBase {
+        public void init(BundleContext context, DependencyManager manager) throws Exception {
+            manager.add(createComponent()
+                .setImplementation(DocumentTranslator.class)
+                .add(createServiceDependency()
+                    .setService(Translator.class)
+                    .setRequired(false)
+                    .setCallbacks("added", "removed")
+                )
+            );
+        }
+        
+        public void destroy(BundleContext context, DependencyManager manager) throws Exception {}
+    }
+
+
+This is the actual `Translator` service, which, for the purpose of this example, is not that important.
+
+
+    public interface Translator {
+        public boolean canTranslate(String from, String to);
+        public Document translate(Document document, String from, String to);
+    }
+
+
+Finally, here's our implementation. It declares the callback methods with one parameter: the `Translator` service. Actually, the dependency manager will look for several different signatures (all explained in more detail in the reference section).
+
+
+    public class DocumentTranslator {
+        private List<Translator> m_translators = new ArrayList<Translator>();
+        
+        public void added(Translator translator) {
+            m_translators.add(translator);
+        }
+        
+        public void removed(Translator translator) {
+            m_translators.remove(translator);
+        }
+        
+        public Document translate(Document document, String from, String to) {
+            for (Translator translator : m_translators) {
+                if (translator.canTranslate(from, to)) {
+                    return translator.translate(document, from, to);
+                }
+            }
+            return null;
+        }
+    }
+
+
+
+### Depending on a configuration
+
+Not all dependencies are on services. There are several other types of dependencies that are supported, one of them is the configuration dependency. In fact, only *required* configuration dependencies are supported, because optional ones can just be achieved by registering as a `ManagedService` yourself. When defining the dependency, you must define the persistent ID of the service. The component will not become active until the configuration you depend on is available *and* is valid. The latter can be checked by your implementation as we will see below.
+
+
+    public class Activator extends DependencyActivatorBase {
+        public void init(BundleContext context, DependencyManager manager) throws Exception {
+            manager.add(createComponent()
+                .setImplementation(Task.class)
+                .add(createConfigurationDependency()
+                    .setPid("config.pid")
+                )
+            );
+        }
+        
+        public void destroy(BundleContext context, DependencyManager manager) throws Exception {}
+    }
+
+
+Here's our code that implements `ManagedService` and has an `updated` method. This method checks if the provided configuration is valid and throw a `ConfigurationException` if it is not. As long as this method does not accept the configuration, the corresponding component will not be activated.
+
+
+    public class Task implements ManagedService {
+        private String m_interval;
+    
+        public void execute() {
+            System.out.println("Scheduling task with interval " + m_interval);
+        }
+    
+        public void updated(Dictionary properties) throws ConfigurationException {
+            if (properties != null) {
+                m_interval = (String) properties.get("interval");
+                if (m_interval == null) {
+                    throw new ConfigurationException("interval", "must be specified");
+                }
+            }
+        }
+    }
+
+
+### ...

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-introduction.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-introduction.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-introduction.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-introduction.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,11 @@
+Title: Apache Felix Dependency Manager - Introduction
+
+## Introduction
+
+In a service oriented architecture, applications are built out of components that are packaged in bundles and interact through services.
+
+These components, that both publish services and depend on other services, form networks that are often dynamic in nature. That makes managing these dependencies something the developer needs to take into account.
+
+Whilst the OSGi framework provides the low-level building blocks to do that in the form of service listeners and trackers, these should not be used directly by developers. Instead, a more declarative approach works best, and the Dependency Manager provides this in the form of a declarative API that allows you to dynamically declare and change dependencies.
+
+On top of that, a set of OSGi design patterns are defined that can be used as building blocks for more complex applications.

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-migrating-from-earlier-versions.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-migrating-from-earlier-versions.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-migrating-from-earlier-versions.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-migrating-from-earlier-versions.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,10 @@
+Title: Apache Felix Dependency Manager - Migrating from Earlier Versions
+
+## Migrating from Earlier Versions
+
+### Design changes
+
+### Binding to the right version
+
+### When to use the compatibility bundle
+

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-osgi-design-patterns.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-osgi-design-patterns.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-osgi-design-patterns.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-osgi-design-patterns.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,163 @@
+Title: Apache Felix Dependency Manager - OSGi Design Patterns
+
+## OSGi Design Patterns
+
+This section lists a couple of design patterns as they can be applied in an OSGi context.
+
+### (Singleton) Service
+
+Provides a service as long as its dependencies are resolved.
+
+#### Motivation
+
+In a dynamic framework, services can come and go. Components that publish a service are often themselves dependent on other services to perform their task. In such cases, they have a dependency on those services and it makes sense to only publish their own services when these dependencies are available. Being able to declare such dependencies in code ensures consistent life cycle behavior.
+
+#### Structure
+
+{gliffy:name=singleton|space=FELIX|page=Apache Felix Dependency Manager - OSGi Design Patterns|pageid=9374247|align=center|size=L|border=false}
+
+#### Code Example
+
+
+    public class Activator extends DependencyActivatorBase {
+        public void init(BundleContext context, DependencyManager manager) throws Exception {
+            manager.add(createComponent()
+                .setInterface(UserStore.class, new Properties() {{ put("store.id", "users"); }})
+                .setImplementation(UserStoreImpl.class)
+                .add(createServiceDependency()
+                    .setService(Store.class)
+                    .setRequired(true)
+                )
+                .add(createServiceDependency()
+                    .setService(LogService.class)
+                    .setRequired(false)
+                )
+            );
+        }
+        
+        public void destroy(BundleContext context, DependencyManager manager) throws Exception {}
+    }
+
+
+### Aspect Service
+
+Provides an aspect on top of a specific type of service.
+
+#### Motivation
+
+In aspect oriented programming, supporting functions are isolated from the main application's business logic. This increases modularity at the source level by allowing the separation of cross-cutting concerns. In OSGi we want to extend this modularity to the runtime, therefore we implement aspects to work on certain services, where the aspect itself publishes that same service but (usually) with a higher priority. This allows you to dynamically add and remove aspects.
+
+#### Structure
+
+{gliffy:name=aspect|space=FELIX|page=Apache Felix Dependency Manager - OSGi Design Patterns|pageid=9374247|align=center|size=L|border=false}
+
+#### Code Example
+
+
+    public class Activator extends DependencyActivatorBase {
+        public void init(BundleContext context, DependencyManager manager) throws Exception {
+            manager.add(createAspectService(Manageable.class, "(monitor=true)", 50)
+                .setImplementation(ManageableMonitor.class)
+            );
+        }
+        
+        public void destroy(BundleContext context, DependencyManager manager) throws Exception {}
+    }
+    
+    public interface Manageable {
+        public void setProperty(String key, String value);
+    }
+    
+    public class ManageableMonitor implements Manageable {
+        private volatile Manageable m_manageable;
+    
+        public void setProperty(String key, String value) {
+            System.out.println("Someone set " + key + " to " + value);
+            m_manageable.setProperty(key, value);
+        }
+    }
+
+
+### Adapter Service
+
+Provides an adapter for a specific type of service.
+
+#### Motivation
+
+Like with aspects, sometimes you want to create adapters for certain services, which add certain behavior that results in the publication of (in this case) a different service. Adapters can dynamically be added and removed and allow you to keep your basic services implementations clean and simple, adding extra features on top of them in a modular way. 
+
+#### Structure
+
+{gliffy:name=adapter|space=FELIX|page=Apache Felix Dependency Manager - OSGi Design Patterns|pageid=9374247|align=center|size=L|border=false}
+
+#### Code Example
+
+
+    public class Activator extends DependencyActivatorBase {
+        public void init(BundleContext context, DependencyManager manager) throws Exception {
+            manager.add(createAdapterService(Manageable.class, "(publish=servlet)")
+                .setInterface(HttpServlet.class.getName(), null)
+                .setImplementation(ManageableServlet.class)
+            );
+        }
+        
+        public void destroy(BundleContext context, DependencyManager manager) throws Exception {}
+    }
+    
+    public interface Manageable {
+        public void setProperty(String key, String value);
+    }
+    
+    public class ManageableServlet implements HttpServlet {
+        private volatile Manageable m_manageable;
+    
+        public void doPost(HttpRequest req, HttpResponse response) {
+            String key = req.getProperty("key");
+            String value = req.getProperty("value");
+            m_manageable.setProperty(key, value);
+        }
+    }
+
+
+### Resource Adapter Service
+
+Provides an adapter for a specific type of resource.
+
+#### Motivation
+
+Resource adapters are similar to normal adapters, but instead of requiring a service, they require a resource and provide a service on top of it. 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 a content repository or database.
+
+#### Structure
+
+{gliffy:name=resource-adapter|space=FELIX|page=Apache Felix Dependency Manager - OSGi Design Patterns|pageid=9374247|align=center|size=L|border=false}
+
+### Temporal Dependency
+
+Provides a proxy that hides the service dynamics of a dependency, even if it disappears for a short time.
+
+#### Motivation
+
+As a service consumer, you sometimes do not want to deal with the dynamics of services and the fact that they tend to go away for short periods of time whilst their hosting bundle gets updated. A temporal dependency provides you with a proxy that hides these dynamics and blocks your calls if you try to invoke a method on a service that is currently "updating". The maximum time to wait is configurable and you will get an exception if no new service becomes available before that time.
+
+#### Structure
+
+### Null Object
+
+Provides an implementation of an object that does nothing and can be used in the absence of the real object.
+
+#### Motivation
+
+When a component depends on a service, but the dependency is optional, it means that it will use this service when available, but it can still operate if it's not. Constantly checking in your code if a service is actually available tends to lead to code with a lot of "`if (service != null) service.invoke();`" constructions which do not help with code readability. Instead, the dependency manager offers you a mechanism where it will inject null objects for services that are currently not available so you can simply invoke methods on them that "do nothing".
+
+#### Structure
+
+### Whiteboard
+
+Handles listeners by leveraging the OSGi service registry to publish and look them up.
+
+#### Motivation
+
+The traditional model for dealing with listeners in Java needlessly complicates things in an OSGi context. Instead of having listeners registering themselves with the component that will invoke them on any change, a listener simply registers itself in the service registry and the component will do a lookup of all relevant services. This is explained in more detail on the OSGi.org wiki in the ["Listeners considered harmful: the 'whiteboard' pattern"](http://www.osgi.org/wiki/uploads/Links/whiteboard.pdf) article.
+
+#### Structure
+

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-reference-guide.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-reference-guide.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-reference-guide.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-reference-guide.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,105 @@
+Title: Apache Felix Dependency Manager - Reference Guide
+
+## Reference Guide
+
+### Components
+
+Components are declared by the dependency manager and can be implemented by POJOs that contain no references to the OSGi framework whatsoever. Components are the main building blocks of your OSGi application. They have a life cycle, can register themselves as services and have zero or more dependencies.
+
+#### Life cycle
+
+The dependency manager, as part of a bundle, shares the generic bundle life cycle explained in the OSGi specification. The life cycle of the dependency manager itself, and the components it manages, can be located inside the *active* state of the hosting bundle.
+
+Each component you define gets its own life cycle, which is explained in the state diagram below.
+
+{gliffy:name=state-diagram|align=center|size=L|version=2}
+
+A component is associated with an instance. This instance can either be specified directly, or you can specify its class. If you do the latter, the actual instance will be created lazily. 
+
+Changes in the state of the component will trigger the following life cycle methods:
+* `init`, 
+* `start`, 
+* `stop` and 
+* `destroy`.
+
+The dependency manager will look for methods with these names and one of the following signatures in this order:
+* (Component),
+* ().
+
+If you don't specify anything, the methods with these names will be invoked on the instance. By using `setCallbacks()` you can however change this behavior: You can change the names of the methods to look for. Any methods that are set to ` null ` will not be invoked at all. Another thing you can do is to specify a different instance to invoke these methods on. If you do that, you will usually want to use the first signature, which gives you a reference to the ` Component ` whose life cycle method was invoked.
+
+#### Interfaces and properties
+
+Components in the context of the dependency manager can be published as OSGi services under one or more interface names, plus optionally a set of properties. This is no different than a normal OSGi service. It's important to mention that you don't have to register a service. If you don't, you basically created a component that can do work and have dependencies and a managed life cycle.
+
+#### Composition
+
+When implementing more complex components, you often find yourself using more than one instance. However, several of these instances might want to have dependencies injected. In such cases you need to tell the dependency manager which instances to consider. This has to be a fixed set of instances however.
+
+#### Factories
+
+Out of the box, there already is support for lazy instantiation, meaning that the dependency manager can create component instances for you when their required dependencies are resolved. However, sometimes creating a single instance using a default constructor is not enough. In those cases, you can tell the dependency manager to delegate the creation process to a factory.
+
+#### Aspects
+
+Aspects, as part of aspect oriented programming, can be used in a dynamic environment such as OSGi to "extend" existing services and add certain "capabilities" to them. Examples of these are adding a specific caching mechanism to a storage service or implementing logging. Aspects in OSGi can be applied to services and can be added and removed at runtime.
+
+#### Adapters
+
+Adapters, like aspects, are used to "extend" existing services, and can publish different services based on the existing one. An example would be implementing a management interface.
+
+#### Resource Adapters
+
+Resource adapters work just like adapters, but instead of working with services, they work with resources. Resources, represented as a URL, are an abstraction introduced to provide a generic way of dealing with "blobs" and can be resources inside a bundle, filesystem or some kind of data store.
+
+### Dependencies
+
+The dependency manager supports many different types of dependencies, all of which can be required or optional. A dependency can be added to one or more components and it is possible to add them dynamically (even from within the component itself if necessary, which allows for some really dynamic dependency configuration).
+
+#### Injection
+
+One way to deal with dependencies is to have them injected into your component instances automatically. All you need to do is simply declare a field of the same type as your dependency, make the member volatile so any changes will become visible immediately and you're done. If a dependency is optional, a null object will be injected if the dependency is not available.
+
+Sometimes you need more control over injection, so optionally you can even specify the name of the field to inject into. This allows you to depend on different dependencies of the same type, or simply to prevent injection into more than one field.
+
+#### Callbacks
+
+When keeping track of multiple instances of a dependency, or when you simply want something to happen whenever a dependency becomes (un)available or changes, you can define callbacks, like `added`, `changed` and `removed`. Optionally, you can provide the dependency manager with an instance to invoke these callback methods on. If you don't, they'll be invoked on the component instance.
+
+#### Types of Dependencies
+
+Out of the box, several types of dependencies are supported: service, bundle, configuration, resource and temporal service. However, it's quite easy to add your own custom type of dependency too.
+
+##### Service
+
+A service dependency allows you to depend on a service, either by type or by using an additional filter condition. You can even depend on an existing service directly by providing a reference to it.
+
+##### Bundle
+
+A bundle dependency allows you to depend on a bundle in a certain set of states, as indicated by a state mask. You can also use a filter condition that is matched against all manifest entries. Finally you can provide a reference to an existing bundle.
+
+##### Configuration
+
+A configuration dependency is always required, and allows you to depend on the availability of a valid configuration for your component. Optional configuration dependencies are not supported because in that case you can just as well register as a ` ManagedService ` yourself.
+
+##### Resource
+
+A resource dependency allows you to depend on a resource. A resource is a URL and you can use a filter condition based on protocol, host, port, path and URL.
+
+##### Temporal Service
+
+A temporal service dependency is a special type of service dependency which does not go away anymore. If you invoke it, and in reality the service is temporarily not available, your call will block until a configurable time-out passes. If during that time the service becomes available again, the new service method is invoked. If not, you will get an exception indicating the time-out expired.
+
+##### Implementing Your Own Dependency
+
+All dependencies share a common API which you can implement yourself if you need a special type of dependency. Whilst not entirely trivial, this allows you to create your own types of dependencies. This can be useful for various scenarios where you want to have components that depend on things that are not services, bundles or configuration.
+
+An example implementation can be found in one of the many test cases for the dependency manager: ` CustomDependencyTest `. This implements a dependency that can be made available and unavailable by manipulating a ` Toggle ` which can be made available or unavailable. You basically have to implement two interfaces: ` Dependency ` and ` DependencyActivation `. The former contains the bulk of the methods that you will need to implement and depending on the actual features you want your dependency to support, you have to implement some or all of them. The JavaDoc for each method plus the example code should get you started. The latter contains a couple of life cycle methods to start and stop tracking your custom dependency.
+
+### Monitoring and Shell
+
+The dependency manager has shell commands that allow you to inspect at runtime the state of the individual components and their dependencies. A separate bundle exists that enables these commands, and the shells it currently supports are: Apache Felix, Gogo and Eclipse Equinox Shell.
+
+### Filter Indices
+
+These are still experimental.
\ No newline at end of file

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,16 @@
+Title: Apache Felix Dependency Manager - Using Annotations
+
+# Using Annotations
+
+Dependency Manager provides a compact and versatile java API,  allowing to declaratively and programmatically register, acquire, and  manage dynamic OSGi services. But since recently, support for  annotations has been introduced in Dependency Manager, and you can also  manage your service component dependencies using Java 5 annotations. In  this chapter, we will detail the Dependency Manager Annotations which  can be used to describe service components. We will also discuss the DM  component lifecycle and how components can interract with the dynamic  OSGi service model.
+
+# Table of Contents
+
+* [Quick Start]({{ refs.apache-felix-dependency-manager-using-annotations-quick-start.path }}) Provides a "Hello World" example, and shows how to compile it.
+* [Spell Checker Sample]({{ refs.apache-felix-dependency-manager-using-annotations-quick-tour.path }}) Helps you with the basic concepts using a full SpellChecker sample code.
+* [Writing Components]({{ refs.apache-felix-dependency-manager-using-annotations-components.path }}) Explains how to write DM service components using annotations.
+* [Using Dependencies]({{ refs.apache-felix-dependency-manager-using-annotations-dependencies.path }}) Explains how to annotate dependencies for a given component.
+* [Lifecycle]({{ refs.apache-felix-dependency-manager-using-annotations-lifecycle.path }}) Explains the DM component lifecycle and how components interact with the dynamic OSGI service model.
+* [Composition]({{ refs.apache-felix-dependency-manager-using-annotations-composition.path }}) Explains how a component may be implemented using multiple object instances.
+
+# 

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-how-to-build.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-how-to-build.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-how-to-build.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-how-to-build.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,19 @@
+Title: Apache Felix Dependency Manager - How To Build
+
+# Building Dependency Manager from trunk
+
+## Checkout from trunk:
+
+svn checkout [http://svn.apache.org/repos/asf/felix/trunk/dependencymanager](http://svn.apache.org/repos/asf/felix/trunk/dependencymanager) dependencymanager
+
+## Compilation
+
+mvn \-Dpackaging=plugins \-Dmaven.test.skip=true install
+
+## Installation
+
+* Deploy the Dependency Manager core bundle: dependencymanager/core/target/core/target/org.apache.felix.dependencymanager-3.x.x-SNAPSHOT.jar.
+
+* Optionally deploy the Dependency Manager Shell: dependencymanager/shell/target/org.apache.felix.dependencymanager.shell-3.x.x-SNAPSHOT.jar
+
+* If you are using annotations, deploy the Dependency Manager Runtime bundle: dependencymanager/runtime/target/org.apache.felix.dependencymanager.runtime-3.x.x-SNAPSHOT.jar
\ 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-components.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-components.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-components.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-components.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,378 @@
+Title: Apache Felix Dependency Manager - Using Annotations - Components
+
+# Annotations - Writing Components
+
+
+## Component Types
+
+Before diving into all annotations, we must first introduce the  different types of components DependencyManager is supporting. In  Dependency Manager, you may use the following types of components,  depending on what you need:
+
+
+* *Component*: Components are the main building blocks for OSGi applications. They can publish themselves as a service, and/or they can have dependencies. These dependencies will influence their life cycle as component will only be activated when all required dependencies are available.
+
+* *Aspect Service*: A service that provides a non-functional aspect on top of an existing service. In aspect oriented programming, an aspect, or interceptor can sit between a client and another target service used by the client. An Aspect Service first tracks a target service and is created once the target service is detected. Then the Aspect Service is provided, but with a higher  ranking, and the client is transparently updated with the aspect. Aspects can be chained and may apply to the same target service (and in this case, the ranking of the Aspect service is used to chain aspects in  the proper order).
+
+* *Adapter Service*: A Service that adapts another existing service into a new one. Like with aspects, sometimes you want to create adapters for certain services, which add certain behavior that results in the publication of (in this case) a different service. Adapters can dynamically be added and removed and allow you to keep your basic services implementations clean and simple, adding extra features on top of them in a modular way.
+
+Now we have introduced the different types of components, here is the list of annotations, allowing to declare DependencyManager service components:
+
+* *@Component:* for declaring a Component that eventually publishes a singleton OSGi service as long as its dependencies are resolved.
+* *@AspectService*: provides a non-functional aspect on top of an existing service.
+* *@AdapterService*: creates an OSGi service that adapts another existing service into a new interface.
+* *@BundleAdapterService*: creates an OSGi service a service on top of a given bundle.
+* *@ResourceAdapterService*: creates an OSGi service on top of a specific Resource.
+* *@FactoryConfigurationAdapterService*: creates an OSGi service from ConfigAdmin, using a factoryPid, and a ManagedServiceFactory.
+
+## @Component
+
+This annotation annotates an implementation class that optionally publishes an OSGi service, and optionally has some dependencies, with a managed lifecycle. The annotation has the following attributes:
+
+* *provides*: By default, the component is registered into the OSGi registry under all directly implemented interfaces. If no interfaces are implemented, then the component is not registered, but it still has a managed lifecycle, and may have some dependencies. If you need to  explicitly define the list of interfaces (or classes) under which the  component must be registered in the OSGi registry, then use the *provides* attribute. You can also set this property to an empty array of classes  if you don't want at all your component to be exposed in the OSGi  registry (even if it implements some interfaces).
+* *properties*: enumerates the list of properties that are part of the Service exposed by the component in the OSGi Registry. Each property is defined using the @Property annotation, which represents a  key/value pair. When a value is actually an array of strings, then the *values* attribute of the @Property annotation can be used. This attribute  is not the only way to specify OSGi Service properties (see Setting Service properties in the lifecycle section).
+* *factoryMethod*: may match a static method name from the annotated class which can be used to instantiate the component instance. Normally, DependencyManager instantiates the component using its class name, and with the default constructor of the class, but there are some cases where it is required to take control of  how the component is created. For instance, this method may be used to create the component as a dynamic proxy ...
+* *factorySet*: The component factory ID. By default, a component is automatically instantiated as a singleton when the bundle is started, and when all required dependencies are satisfied. But when a component must be created, configured, or disposed dynamically, and when multiple instances of the same component are needed, a factorySet should  be used. When you use this attribute, a java.util.Set<Dictionary>  object is registered into the OSGi regitry, with a specific *{*}dm.factory.name{*}* property matching the ID you specify in the attribute. This Set<Dictionary> will act as a Factory API, and another component may define a dependency on this Set and add some configuration dictionaries in  it, in order to fire some component instantiation/activation. There is one component instantiated per added dictionary, which is passed to component instances via a configurable callback method (using the *{*}factoryConfigure{*}* attribute). All public properties will be propagated  al
 ong with eventual published service. A public property is a property  which does not start with a dot ("."). Properties starting with a dot are considered private to the component, and won't be propagated to published service. This model is actually similar to the Declarative Service "Component Factories" concept, except that you don't have a dependency on a specific API, but rather on a basic jdk class  (java.util.Set<Dictionary>). Notice that, unlike in Declarative Service, the component factory is provided once the component bundle is started, even if required dependencies are not satisfied. This is useful when the component want  to dynamically configure its dependency filters. So, to summarize:
+** Each time a new Dictionary is added into the Set, then a new instance of the annotated component will be instantiated, and this dictionary is passed to the component callback specified with the factoryConfigure attribute.
+** Each time an existing Dictionary is re-added into the Set, then the corresponding component instance is updated, and the updated dictionary is also passed to the callback specified in the factoryConfigure attribute.
+** Each time an existing Dictionary is removed from the Set, then the  corresponding component instance will be stopped and destroyed.
+* *factoryConfigure*: Sets the "configure" method name to be called with the factory configuration. This attribute only makes sense if the factorySet() attribute is used. If specified, then this attribute references a component callback method, which is called for providing the configuration supplied by the factory that instantiated this component. The current Service properties will be also updated with all public properties (which don't start with a dot).
+
+Usage example:
+
+
+     /**
+       * This component will be activated once the bundle is started and when all required dependencies
+       * are available.
+       */
+     @Component
+     class X implements Z {
+         @ConfigurationDependency(pid="MyPid")
+         void configure(Dictionary conf) {
+              // Configure or reconfigure our service.
+         }
+    
+         @Start
+         void start() {
+             // Our component is starting and is about to be registered in the OSGi registry as a Z service.
+         }
+    
+         public void doService() {
+             // ...
+         }
+     }
+    
+
+Example using a factorySet, where the X component is instantiated/updated/disposed by another Y component:
+
+
+
+      @Component(factorySet="MyComponentFactory", factoryConfigure="configure")
+      class X implements Z {
+          void configure(Dictionary conf) {
+              // Configure or reconfigure our component. The conf is provided by the factory,
+              // and all public properties (which don't start with a dot) are propagated with the
+              // Service properties eventually specified in the properties annotation attribute.
+          }
+    
+          @ServiceDependency
+          void bindOtherService(OtherService other) {
+              // store this require dependency
+          }
+    
+          @Start
+          void start() {
+              // Our component is starting and is about to be registered in the OSGi registry as a Z service.
+          }
+    
+          public void doService() {
+              // ... part of Z interface
+          }
+      }
+    
+      /**
+        * This class will instantiate some X component instances
+        */
+      @Component
+      class Y {
+          @ServiceDependency(filter="(dm.factory.name=MyComponentFactory)")
+          Set<Dictionary> _XFactory; // This Set acts as a Factory API for creating X component instances.
+    
+          @Start
+          void start() {
+              // Instantiate a X component instance
+              Dictionary x1 = new Hashtable() {{ put("foo", "bar1"); }};
+              _XFactory.add(x1);
+    
+              // Instantiate another X component instance
+              Dictionary x2 = new Hashtable() {{ put("foo", "bar2"); }};
+              _XFactory.add(x2);
+    
+              // Update the first X component instance
+              x1.put("foo", "bar1_modified");
+              _XFactory.add(x1);
+    
+              // Destroy all components (Notice that invoking _XFactory.clear() also destroys every X instances)
+              _XFactory.remove(x1);
+              _XFactory.remove(x2);
+          }
+      }
+
+
+## @AspectService
+
+Aspects allow you to define an interceptor, or chain of interceptors for a service (to add features like caching or logging, etc ...). The dependency manager intercepts the original service, and allows you to execute some code before invoking the original service ... The aspect will be applied to any service that matches the specified interface and filter and will be registered with the same interface and properties as the original service, plus any extra properties you supply here. It will also inherit all dependencies, and if you declare the original service as a member it will be injected.
+
+Annotation attributes:
+
+* *ranking*: Sets the ranking of this aspect. Since aspects are chained, the ranking defines the order in which they are chained. Chain ranking is implemented as a service ranking so service lookups automatically retrieve the top of the chain.
+* *service*: Sets the service interface to apply the aspect to. By default, the directly implemented interface is used.
+* *filter*: Sets the filter condition to use with the service interface this aspect is applying to.
+* *properties*: Sets Additional properties to use with the aspect service registration.
+* *field*: Sets the field name where to inject the original service. By default, the original service is injected in any attributes in the aspect implementation that are of the same type as the aspect interface.
+* *factoryMethod*: Sets the static method used to create the AspectService implementation instance. The default constructor of the annotated class is used. The factoryMethod can be used to provide a specific aspect implements, like a DynamicProxy.
+
+Usage example:
+
+
+     @AspectService(ranking=10), properties={@Property(name="param", value="value")})
+     class AspectService implements InterceptedService {
+         // The service we are intercepting (injected by reflection)
+         protected InterceptedService intercepted;
+       
+         public void doWork() {
+            intercepted.doWork();
+         }
+     }
+
+
+## @AdapterService
+
+Adapters, like with @AspectService, are used to "extend" existing services, and can publish different services based on the existing one. An example would be implementing a management interface for an existing service, etc .... When you annotate an adapter class with the @AdapterService annotation, it will be applied to any service that matches the implemented interface and filter. The adapter will be registered with the specified interface and existing properties from the original service plus any extra properties you supply here. If you declare the original service as a member it will be injected. 
+
+Annotation attributes:
+
+* *adapteeService*: Sets the adaptee service interface this adapter is applying to.
+* *provides*: Sets the adapter service interface(s). By default, the directly implemented interface(s) is (are) used. 
+* *properties*: Sets some additional properties to use with the adapter service registration. By default, the adapter will inherit all adaptee service properties.
+* *adapteeFilter*: Sets the filter condition to use with the adapted service interface.
+* *factoryMethod*: Sets the static method used to create the adapter service implementation instance. By default, the default constructor of the annotated class is used.
+
+Usage example: Here, the AdapterService is registered into the OSGI registry each time an AdapteeService is found from the registry. The AdapterImpl class adapts the AdapteeService to the AdapterService. The AdapterService will also have a service property (param=value), and will also include eventual service properties found from the AdapteeService:
+
+
+     @AdapterService(adapteeService = AdapteeService.class, properties={@Property(name="param", value="value")})
+     class AdapterImpl implements AdapterService {
+         // The service we are adapting (injected by reflection)
+         protected AdapteeService adaptee;
+       
+         public void doWork() {
+            adaptee.mehod1();
+            adaptee.method2();
+         }
+     }
+
+
+## @BundleAdapterService
+
+Bundle adapters are similar to AdapterService, but instead of adapting a service, they adapt a bundle with a certain set of states (STARTED|INSTALLED|...), and provide a service on top of it.
+
+The bundle adapter will be applied to any bundle that matches the specified bundle state mask and filter conditions, which may match some of the bundle OSGi manifest headers. For each matching bundle an adapter will be created based on the adapter implementation class. The adapter will be registered with the specified interface and with service properties found from the original bundle OSGi manifest headers plus any extra properties you supply here. If you declare the original bundle as a member it will be injected. 
+
+Annotation attributes:
+
+* *filter*: The filter used to match some OSGi manifest headers from a given bundle.
+* *provides*: The interface(s) to use when registering adapters. By default, the interface(s) directly implemented by the annotated class is (are) used.
+* *properties*: Additional properties to use with the service registration.
+* *stateMask*: the bundle state mask to apply. The mask is made up of the flags provided by the org.osgi.framework.Bundle states (UNINSTALLED | INSTALLED | RESOLVED | STARTING | STARTED | ACTIVE).
+* *propagate*: Specifies if manifest headers from the bundle should be propagated to the exposed service properties.
+* *factoryMethod*: Sets the static method used to create the BundleAdapterService implementation instance.
+
+Usage Examples
+
+In the following example, a "VideoPlayer" Service is registered into the OSGi registry each time an active bundle containing a "Video-Path" manifest header is detected:
+
+
+     @BundleAdapterService(filter = "(Video-Path=*)", stateMask = Bundle.ACTIVE, propagate=true)
+     public class VideoPlayerImpl implements VideoPlayer {
+         Bundle bundle; // Injected by reflection
+             
+         void play() {
+             URL mpegFile = bundle.getEntry(bundle.getHeaders().get("Video-Path"));
+             // play the video provided by the bundle ...
+         }
+           
+         void stop() {}
+     }
+
+
+## @ResourceAdapterService
+
+Resource adapters are things that adapt a resource instead of a service, and provide an adapter service on top of this 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.
+
+The adapter will be applied to any resource that matches the specified filter condition, which can match some part of the resource URL (with "path", "protocol", "port", or "host" filters). For each matching resource an adapter will be created based on the adapter implementation class. The adapter will be registered with the specified interface and with any extra service properties you supply here. Moreover, the following service properties will be propagated from the resource URL:
+
+* *host*: this property exposes the host part of the resource URL
+* *path*: the resource URL path
+* *protocol*: the resource URL protocol
+* *port*: the resource URL port 
+
+Usage Examples:
+
+Here, the "VideoPlayer" service provides a video service on top of any movie resources, with service properties "host"/"port"/"protocol"/"path" extracted from the resource URL:
+
+
+     @ResourceAdapterService(filter = "(&(path=/videos/*.mkv)(host=localhost))", propagate = true)
+     public class VideoPlayerImpl implements VideoPlayer {
+         // Injected by reflection
+         URL resource;
+             
+         void play() {} // play video referenced by this.resource     
+         void stop() {} // stop playing the video
+         void transcode() {} // ...
+     }
+
+
+
+
+## @FactoryConfigurationAdapterService
+
+Annotates a class that acts as a Factory Configuration Adapter Service. For each new Config Admin factory configuration matching the specified factoryPid, an instance of this service will be created. The adapter will be registered with the specified interface, and with the specified adapter service properties. Depending on the propagate parameter, every public factory configuration properties (which don't start with ".") will be propagated along with the adapter service properties.
+
+Like in @ConfigurationDependency, you can optionally specify the meta types of your configurations for Web Console GUI customization (configuration heading/descriptions/default values/etc ...). 
+
+Annotation attributes:
+
+* *provides*: The interface(s) to use when registering adapters. By default, directly implemented interfaces will be registered in the OSGi registry. 
+* *properties*: Adapter Service properties. Notice that public factory configuration is also registered in service properties, (only if propagate is true). Public factory configuration properties are those which don't starts with a dot (".").
+* *factoryPid*: Returns the factory pid whose configurations will instantiate the annotated service class. (By default, the pid is the service class name). 
+* *updated*: The Update method to invoke (defaulting to "updated"), when a factory configuration is created or updated 
+* *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". 
+* *factoryMethod*: Sets the static method used to create the adapter instance.
+* *metadata*: an array of  "PropertyMetaData[]({{ refs..path }})" annotations, specifying property types used to expose properties in web console
+
+PropertyMetaData anotation attribute: 
+
+* *description*: Returns the property description. The description may be localized and must describe the semantics of this type and any constraints. Example: "Select the log level for the Printer Service".
+* *type*: Return the property primitive type (java.lang.String.class by default). If must be either one of the following types:
+** String.class
+** Long.class
+** Integer.class
+** Character.class
+** Byte.class
+** Double.class
+** Float.class
+** Boolean.class
+* *defaults*: Return a default for this property. The object must be of the appropriate type as defined by the cardinality and getType(). The return type is a list of String objects that can be converted to the appropriate type. The cardinality of the return array must follow the absolute cardinality of this type. E.g. if the cardinality = 0, the array must contain 1 element. If the cardinality is 1, it must contain 0 or 1 elements. If it is -5, it must contain from 0 to max 5 elements. Note that the special case of a 0 cardinality, meaning a single value, does not allow arrays or vectors of 0 elements. 
+* *cardinality*: Return the cardinality of this property (0 by default). The OSGi environment handles multi valued properties in arrays ([]({{ refs..path }})) or in Vector objects. The return value is defined as follows:
+** x = Integer.MIN_VALUE no limit, but use Vector
+** x < 0 -x = max occurrences, store in Vector
+** x > 0 x = max occurrences, store in array []({{ refs..path }})
+** x = Integer.MAX_VALUE no limit, but use array []({{ refs..path }})
+** x = 0 1 occurrence required
+* *required*: Tells if this property is required or not. 
+* *optionLabels*: Return a list of valid option labels for this property. The purpose of this method is to allow menus with localized labels. It is associated with the *optionValues* attribute. The labels returned here are ordered in the same way as the *optionValues* attribute values. 
+* *optionValues*: Return a list of option values that this property can take. This list must be in the same sequence as the *optionLabels* attribute. 
+
+Usage Examples
+Here, a "Dictionary" service instance is instantiated for each existing factory configuration instances matching the factory pid "DictionaryServiceFactory".
+
+         @FactoryConfigurationAdapterService(factoryPid="DictionaryServiceFactory", updated="updated")
+         public class DictionaryImpl implements DictionaryService
+         {
+             /**
+              * The key of our config admin dictionary language.
+              */
+             final static String LANG = "lang";
+             
+             /**
+              * The key of our config admin dictionary values.
+              */
+             final static String WORDS = "words";
+             
+             /**
+              * 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;
+         
+             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);
+                 }
+             }   
+             ...
+         }
+
+
+Here, this is the same example as above, but using meta types:
+
+
+         @FactoryConfigurationAdapterService(
+             factoryPid="DictionaryServiceFactory", 
+             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=DictionaryImpl.LANG,
+                     cardinality=0),
+                 @PropertyMetaData(
+                     heading="Dictionary words",
+                     description="Declare here the list of words supported by this dictionary. This properties starts with a Dot and won't be propagated with Dictionary OSGi service properties.",
+                     defaults={"hello", "world"},
+                     id=DictionaryImpl.WORDS,
+                     cardinality=Integer.MAX_VALUE)
+             }
+         )  
+         public class DictionaryImpl implements DictionaryService
+         {
+             /**
+              * The key of our config admin dictionary language.
+              */
+             final static String LANG = "lang";
+             
+             /**
+              * The key of our config admin dictionary values.
+              */
+             final static String WORDS = "words";
+             
+             /**
+              * 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;
+         
+             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);
+                 }
+             }
+             
+             ...
+         }
+
+
+
+

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-composition.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-composition.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-composition.mdtext (added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations/apache-felix-dependency-manager-using-annotations-composition.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,63 @@
+Title: Apache Felix Dependency Manager - Using Annotations - Composition
+
+# Annotations - Composition
+
+When implementing more complex services, you often find yourself using more than one instance for a given service. However, several of these instances might want to have dependencies injected. In such cases you need to tell the dependency manager which instances to consider. Within a Component (or an Aspect/Adapter), you can annotate a method with the @Composition annotation. This method is meant to return such composition of service instances, and the objects will be considered as part of the service implementation. So, all  dependencies, as well as lifecycle annotations (@Init, @Start, @Stop, @Destroy) will be applied on every objects returned by the method annotated with the @Composition annotation.
+
+The following example illustrates a composition of two object instances, which are part of the implementation of a *MyService* service:
+
+
+    /**
+     * Main implementation for the MyService Service
+     */
+    @Component
+    public class MyServiceImpl implements MyService {
+      // This object instance is also used to implement the service.
+      private Helper helper = new Helper();
+    
+      // MyServiceImpl, and Helper objects are part of the composition
+      @Composition
+      Object[] getComposition() {
+        return new Object[] { this, helper };
+      }
+    
+      // This dependency is also applied to the Helper
+      @ServiceDependency
+      Dependency dep;
+    
+      // Same thing for this dependency
+      @ServiceDependency
+      void bind(Dependency2 dep2) {}
+    
+      // Lifecycle callbacks also applied on the Helper ...
+      @Init
+      void init() {}
+    
+      @Start
+      void start() {}
+    
+      @Stop
+      void stop() {}
+    
+      @Destroy()
+      void destroy() {}
+    }
+    
+    public class Helper {
+      // Also injected, since we are part of the composition
+      Dependency dep;
+    
+      // But since we are not interested by the Dependency2, we don't have to declare the bind(Dependency2) method ...
+    
+      // We only specify the start lifecycle callback because we need to return some extra service properties which will be published
+      // along with the provided service ...
+    
+      Map start() {
+         Map extraServiceProperties = new HashMap();
+         extraServiceProperties.add("foo", "bar");
+         return extraServiceProperties;
+      }
+    }
+    
+
+Here, MyServiceImpl is the main component implementation, but is   composed of the Helper object instance. So all Dependencies defined in  MyServiceImpl will be also injected to the Helper (if the Helper  declares the fields or methods). The Helper may also declare lifecycle  callbacks (optionally).
\ No newline at end of file



Mime
View raw message