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;
+
+ ...
}
+