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/23 22:35:11 UTC

svn commit: r1844705 - /felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/tutorials/sample-code.mdtext

Author: pderop
Date: Tue Oct 23 22:35:11 2018
New Revision: 1844705

URL: http://svn.apache.org/viewvc?rev=1844705&view=rev
Log:
dm sample code

Added:
    felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/tutorials/sample-code.mdtext
      - copied, changed from r1844524, felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/tutorials/getting-started.mdtext

Copied: felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/tutorials/sample-code.mdtext (from r1844524, felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/tutorials/getting-started.mdtext)
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/tutorials/sample-code.mdtext?p2=felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/tutorials/sample-code.mdtext&p1=felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/tutorials/getting-started.mdtext&r1=1844524&r2=1844705&rev=1844705&view=diff
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/tutorials/getting-started.mdtext (original)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-dependency-manager/tutorials/sample-code.mdtext Tue Oct 23 22:35:11 2018
@@ -1,195 +1,65 @@
 Title: Dependency Manager - Getting Started
 
-When developing an OSGi bundle that has dependencies and possibly registers services, there are two classes in particular we need to implement:
+# Dependency Manager sample code
 
-1. The bundle activator which controls the life-cycle of the bundle.
-1. The actual component, which can be a POJO.
+You can download this [archive](dm.hello.tgz) which contains the following directories:
 
-When using the dependency manager, your bundle activator is a subclass of `DependencyActivatorBase`. It needs to implement the `init` life cycle method and can optionally also implement a `destroy` method. 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.
+- felix-framework-6.0.1/ -> this is a felix framework with pre-installed dependency manager r13 artifacts, as well as with 
+configadmin and metatype bundles (these dependencies are required by dm)
+- hello.api/ -> provides a sample component using the dependency manager API. 
+- hello.lambda/ -> provides a sample component using the dependency manager Lambda API. 
+- hello.annotations -> provides a sample component using the dependency manager annotations.
 
-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.
+All samples can be built using either gradle or maven. 
+To build with gradle, simply type "./gradlew jar", and to build with maven, type "mvn clean install".
+If you are using an http proxy, you must set the following environment:
 
-To use the dependency manager, you should put the `org.apache.felix.dependencymanager.jar` in your classpath while compiling and in your OSGi framework when running.
+- for gradle: export GRADLE_OPTS="-Dhttp.proxyHost=<ip> -Dhttp.proxyPort=<port> -Dhttps.proxyHost=<ip> -Dhttps.proxyPort=<port>
+- for maven, you must setup your http proxy in your ~/.m2/settings.xml
 
-A recent java 8 jdk is required since the dependency manager r8 (the dm r8 release has been built and tested using java version 1.8.74).
+Once built, the three jars for all hello projects can be put in the felix-framework-6.0.1/bundles/ directory.
+Now start felix like this:
 
-## Registering a service
+    cd felix-framework-6.0.1
+    java -jar bin/felix.jar
 
-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.
+You should then see the following logs displayed to stdout:
 
-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.
+    HelloComponent started using Dependency Manager API
+    HelloComponent started using Dependency Manager Lambda
+    HelloComponent started using Dependency Manager Annotations
 
+You can also play with the dm shell commands. First, type "help dm":
 
-    public class Activator extends DependencyActivatorBase {
-        public void init(BundleContext context, DependencyManager manager) throws Exception {
-            manager.add(createComponent()
-                .setInterface(Store.class, null)
-                .setImplementation(MemoryStore.class)
-            );
-        }
-    }
-
-
-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)
-                )
-            );
-        }
-    }
-
-
-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")
-                )
-            );
-        }
-    }
-
-
-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. 
-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")
-                )
-            );
-        }
-    }
-
-
-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.
-Notice that your component does not necessarily implement the ManagedService interface, and the updated callback
-can also throw any exceptions:
-
-
-    public class Task implements ManagedService {
-        private String m_interval;
-    
-        public void execute() {
-            System.out.println("Scheduling task with interval " + m_interval);
-        }
+    g! help dm
     
-        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");
-                }
-            }
-        }
-    }
+    dm - List dependency manager components
+       scope: dependencymanager
+       flags:
+          compact, cp   Displays components using a compact form
+          nodeps, nd   Hides component dependencies
+          notavail, na   Only displays unavailable components
+          stats, stat, st   Displays components statistics
+          wtf   Detects where are the root failures
+       options:
+          bundleIds, bid, bi, b   <List of bundle ids or bundle symbolic names to display (comma separated)> [optional]
+          componentIds, cid, ci   <List of component identifiers to display (comma separated)> [optional]
+          components, c   <Regex(s) used to filter on component implementation class names (comma separated), can be negated using "!" prefix> [optional]
+          services, s   <OSGi filter used to filter some service properties> [optional]
+          top   <Max number of top components to display (0=all)> This command displays components callbacks (init/start) times> [optional]
+
+Now type "dm" in order to see all dependency manager components:
+
+     g! dm
+    [1] hello.annotations
+     [3] hello.HelloComponent registered
+    [2] hello.api
+     [0] hello.HelloComponent registered
+    [3] hello.lambda
+     [1] hello.HelloComponent registered
+    [10] org.apache.felix.dependencymanager.runtime
+     [2] org.apache.felix.dm.runtime.DependencyManagerRuntime registered
+        active (DependencyManager-Component=*) bundle optional available
+        org.osgi.service.packageadmin.PackageAdmin service required available
+        org.osgi.service.log.LogService service optional unavailable