You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2018/10/01 20:17:07 UTC

svn commit: r1842559 - /felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/component-singleton.mdtext

Author: pderop
Date: Mon Oct  1 20:17:06 2018
New Revision: 1842559

URL: http://svn.apache.org/viewvc?rev=1842559&view=rev
Log:
[FELIX-5939] - DM annotations enhancements

Modified:
    felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/component-singleton.mdtext

Modified: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/component-singleton.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/component-singleton.mdtext?rev=1842559&r1=1842558&r2=1842559&view=diff
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/component-singleton.mdtext (original)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/reference/component-singleton.mdtext Mon Oct  1 20:17:06 2018
@@ -2,180 +2,91 @@ Title: Dependency Manager - Singleton Co
 
 Components are the main building blocks for OSGi applications. They can publish themselves as a service, and they can have dependencies. These dependencies will influence their life cycle as component will only be activated when all required dependencies are available.
 
-Usage example:
+## Example using API
 
-	dm.add(createComponent()
-		.setInterface(TranslationService.class.getName(), null)
-		.setImplementation(GoogleBasedTranslationService.class)
-		.add(createServiceDependency()
-			.setService(LocalizationService.class, "(language=en)")
-			.setRequired(true)
-		)
-		.add(createServiceDependency()
-			.setService(LogService.class)
-			.setRequired(false)
-		)
-	);
-
-## @Component
-
-This annotation annotates an implementation class that optionally publishes 
-an OSGi service, and optionally has some dependencies, with a managed 
-lifecycle. 
-
-### Annotation attributes
-
-----
-**`provides`**    
-*Required*: No    
-*Default*: all implemented interfaces, if any.   
-
-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`**    
-*Required*: No    
-*Default*: --  
-
-the *properties" attribute 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`**    
-*Required*: No    
-*Default*: --  
-
-This attribute refers to 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 ...
-
-----
-**`factoryName`**    
-*Required*: No    
-*Default*: --  
+To define a singleton component, you can use the DependencyManager.createComponent() method, like in the following example which defines a "TranslationService" osgi service having one required dependency on the "LocalizationService" and one optional dependency on a "LogService".
+Dependencies are optional by default, unless you invoke the ServiceDependency.setRequired(boolean) method:
+
+    :::java
+    public class GoogleBasedTranslationService implements TranslationService {
+        volatile LocalizationService m_localizationService; // injected by reflection
+        volatile LogService m_log;
+        
+        ...
+    }
  
-This attribute is the identifier for a component factory. 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 factoryName can  be 
-used. When you use this attribute, a *org.apache.felix.dm.runtime.api.ComponentFactory* 
-OSGi Service will be provided with a *dm.factory.name* service property matching your 
-specified factoryName attribute. The ComponentFactory will be provided once the 
-component bundle is started, even if required dependencies are not available, 
-and the ComponentFactory will be unregistered from the OSGi registry once the component 
-bundle is stopped or disposed using the *ComponentInstance.dispose()* method.
-
-----
-**`factoryConfigure`**    
-*Required*: No    
-*Default*: --  
-
-This attributes sets the *configure* method name to be called with the factory 
-configuration. This attribute only makes sense if the *factoryName* 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).
+    public class Activator extends DependencyManagerActivator {
+        public void init(BundleContext ctx, DependencyManager dm) throws Exception {
+            Component c = createComponent()
+               .setInterface(TranslationService.class.getName(), null)
+               .setImplementation(GoogleBasedTranslationService.class)
+               .add(createServiceDependency()
+                  .setService(LocalizationService.class, "(language=en)")
+                  .setRequired(true))
+               .add(createServiceDependency()
+                  .setService(LogService.class)
+                  .setRequired(false)));
+            dm.add(c);
+       }
+    }
+	
 
-### Usage example:
+You can also inject dependencies using callbacks:
 
     :::java
-    /**
-     * 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() {
-            // ...
+    public class GoogleBasedTranslationService implements TranslationService {
+        volatile LocalizationService m_localizationService; // injected by reflection        
+        void bind(LogService log {...}
+        ...
+    }
+
+    public class Activator extends DependencyManagerActivator {
+        public void init(BundleContext ctx, DependencyManager dm) throws Exception {
+            Component c = createComponent()
+               .setInterface(TranslationService.class.getName(), null)
+               .setImplementation(GoogleBasedTranslationService.class)
+               .add(createServiceDependency()
+                  .setService(LocalizationService.class, "(language=en)")
+                  .setRequired(true))
+               .add(createServiceDependency()
+                  .setService(LogService.class)
+                  .setCallbacks("bind", null /* no unbind method */)
+                  .setRequired(false)));
+            dm.add(c);
+       }
+    }
+
+Notice that when you define an optional dependency without using callbacks, then a "NullObject" method is injected in the class field (by reflection) when the actual optional service is not available. In this case any invocation on the optional service won't do anything.
+
+## Example using lambda API
+
+This is the same example using the Dependency Manager Lambda API:
+
+    :::java
+    public class Activator extends DependencyManagerActivator {
+        public void init(BundleContext ctx, DependencyManager dm) throws Exception {
+            component(comp -> comp
+                .impl(GoogleBasedTranslationService.class)
+                .provides(TranslationService.class)
+                .withSvc(LocalizationService.class, true)
+                .withSvc(LogService.class, false));
         }
     }
-    
 
-Example using a factoryName, where the X component is instantiated/updated/disposed by another Y component:
+## Example using annotations:
+
+This is the same example as before, using Annotations: (notice that unlike with the api, the dependencies are required by default):
 
     :::java
-     import org.apache.felix.dm.runtime.api.ComponentFactory;
-     import org.apache.felix.dm.runtime.api.ComponentInstance;
+    @Component
+    public class GoogleBasedTranslationService implements TranslationService {
+        @ServiceDependency(required=true)
+        volatile LocalizationService localizationService;
 
-     @Component(factoryName="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 {
-         // This Set acts as a Factory API for creating X component instances.
-         @ServiceDependency(filter="(dm.factory.name=MyComponentFactory)")
-         ComponentFactory _XFactory; 
-    
-         @Start
-         void start() {
-             // Instantiate a X component instance
-             Dictionary x1 = new Hashtable() {{ put("foo", "bar1"); }};
-             ComponentInstance i1 = _XFactory.newInstance(x1);
-    
-             // Instantiate another X component instance
-             Dictionary x2 = new Hashtable() {{ put("foo", "bar2"); }};
-             ComponentInstance i2 = _XFactory.newInstance(x2);
-    
-             // Update the first X component instance
-             x1 = new Hashtable() {{ put("foo", "bar1_modified"); }};
-             i1.update(x1);
-    
-             // Destroy components
-             i1.dispose();
-             i2.dispose();
-         }
+        @ServiceDependency(required=false)
+        volatile LogService log;
+
+        ...
     }
 
+