FELIX-4689: Create a more fluent syntax for the dependency manager builder.


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1727869 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/org.apache.felix.dependencymanager.itest/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.itest/bnd.bnd
index c5c968c..8abc054 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.itest/bnd.bnd
+++ b/dependencymanager/org.apache.felix.dependencymanager.itest/bnd.bnd
@@ -24,7 +24,7 @@
 	biz.aQute.junit;version=3.0.0
 -runee: JavaSE-1.7
 -runvm: -ea
--runfw: org.apache.felix.framework
+-runfw: org.apache.felix.framework;version='[5.2.0,5.2.0]'
 -buildpath:  \
 	osgi.core;version=4.2,\
 	osgi.cmpn;version=4.2,\
@@ -38,3 +38,9 @@
 	*.bnd
 Test-Cases:  \
 	${classes;CONCRETE;EXTENDS;junit.framework.TestCase}
+-runproperties:  \
+	org.apache.felix.dependencymanager.loglevel=2,\
+	org.apache.felix.log.maxSize=100000,\
+	org.apache.felix.log.storeDebug=true,\
+	gosh.args=--noshutdown
+	
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.classpath b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.classpath
new file mode 100644
index 0000000..4f775bc
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="bin" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.gitignore b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.gitignore
new file mode 100644
index 0000000..57b3411
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.gitignore
@@ -0,0 +1,2 @@
+/bin/
+/generated/
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.project b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.project
new file mode 100644
index 0000000..c302837
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.apache.felix.dependencymanager.lambda.itest</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.settings/org.eclipse.jdt.core.prefs b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..144c60c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/bnd.bnd
new file mode 100644
index 0000000..4479394
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/bnd.bnd
@@ -0,0 +1,35 @@
+-buildpath: \
+	org.apache.felix.dependencymanager;version=latest,\
+	org.apache.felix.dependencymanager.shell;version=latest,\
+	org.apache.felix.dependencymanager.lambda;version=latest,\
+	org.apache.felix.gogo.runtime;version=0.12,\
+	${junit},\
+	osgi.core;version=6.0,\
+	osgi.cmpn;version=6.0
+-runbundles: \
+	org.apache.felix.metatype;version=1.0.10,\
+	org.apache.felix.gogo.runtime;version=0.12.1,\
+	org.apache.felix.log;version=1.0.1,\
+	org.apache.felix.dependencymanager;version=latest,\
+	org.apache.felix.dependencymanager.shell;version=latest,\
+	org.apache.felix.configadmin;version=1.8.4,\
+	org.apache.felix.dependencymanager.lambda;version=latest,\
+	biz.aQute.junit;version=1.3.0,\
+	org.apache.felix.gogo.shell;version=0.10.0,\
+	org.apache.felix.gogo.command;version=0.14.0
+-runee: JavaSE-1.8
+-runfw: org.apache.felix.framework;version='[5.2.0,5.2.0]'
+-runvm: -ea
+Bundle-Version: 0.0.0.${tstamp}
+Private-Package:  \
+	org.apache.felix.dm.lambda.itest
+Test-Cases:  \
+	${classes;CONCRETE;EXTENDS;junit.framework.TestCase}
+javac.source:          1.8
+javac.target:          1.8
+-tester: biz.aQute.junit
+-runproperties:  \
+	org.apache.felix.dependencymanager.loglevel=2,\
+	org.apache.felix.log.maxSize=100000,\
+	org.apache.felix.log.storeDebug=true,\
+	gosh.args=--noshutdown
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/build.gradle b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/build.gradle
new file mode 100644
index 0000000..339f1ca
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/build.gradle
@@ -0,0 +1,3 @@
+ tasks.withType(JavaCompile) {
+  options.compilerArgs << "-parameters" << "-Xdiags:verbose" 
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AbstractServiceDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AbstractServiceDependencyTest.java
new file mode 100644
index 0000000..daa1e22
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AbstractServiceDependencyTest.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AbstractServiceDependencyTest extends TestBase {
+   public void testAbstractClassDependency() {
+       DependencyManager m = getDM();
+       // helper class that ensures certain steps get executed in sequence
+       Ensure e = new Ensure();
+       // create a service provider and consumer
+       
+       Component sp = 
+           component(m).provides(ServiceAbstract.class).impl(new ServiceProvider(e)).build();
+       Component sc = 
+           component(m).impl(new ServiceConsumer(e)).withSrv(ServiceAbstract.class, srv -> srv.cb(ServiceConsumer::bind, ServiceConsumer::unbind)).build();
+           
+       m.add(sp);
+       m.add(sc);
+       m.remove(sp);
+       // ensure we executed all steps inside the component instance
+       e.step(8);
+       m.clear();
+   }
+
+   static abstract class ServiceAbstract {
+       public abstract void invoke();
+   }
+
+   static class ServiceProvider extends ServiceAbstract {
+       private final Ensure m_ensure;
+       public ServiceProvider(Ensure e) {
+           m_ensure = e;
+       }
+
+       public void start() {
+           m_ensure.step(1);
+       }
+
+       public void invoke() {
+           m_ensure.step(4);
+       }
+
+       public void stop() {
+           m_ensure.step(7);
+       }
+   }
+
+   static class ServiceConsumer {
+       private volatile ServiceAbstract m_service;
+       private final Ensure m_ensure;
+
+       public ServiceConsumer(Ensure e) {
+           m_ensure = e;
+       }
+
+       public void bind(ServiceAbstract service) {
+           m_ensure.step(2);
+           m_service = service;
+       }
+
+       public void start() {
+           m_ensure.step(3);
+           m_service.invoke();
+       }
+
+       public void stop() {
+           m_ensure.step(5);
+       }
+
+       public void unbind(ServiceAbstract service) {
+           System.out.println("UNBINDDDDDDDDDDDDDDDDDDDDDDDDDDD");
+           Assert.assertEquals(m_service, service);
+           m_ensure.step(6);
+       }
+   }
+}
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterAndConsumerTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterAndConsumerTest.java
new file mode 100644
index 0000000..eea9782
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterAndConsumerTest.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.adapter;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AdapterAndConsumerTest extends TestBase {
+    
+    public void testServiceWithAdapterAndConsumer() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+
+        Component provider = component(m).provides(OriginalService.class).impl(new ServiceProvider(e)).build();
+        Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(AdaptedService.class).build();
+        Component adapter = adapter(m, OriginalService.class).provides(AdaptedService.class).impl(ServiceAdapter.class).build();
+        		        
+        // add the provider and the adapter
+        m.add(provider);
+        m.add(adapter);
+        // add a consumer that will invoke the adapter
+        // which will in turn invoke the original provider
+        m.add(consumer);
+        // now validate that both have been invoked in the right order
+        e.waitForStep(2, 5000);
+        // remove the provider again
+        m.remove(provider);
+        // ensure that the consumer is stopped
+        e.waitForStep(3, 5000);
+        // remove adapter and consumer
+        m.remove(adapter);
+        m.remove(consumer);
+    }
+
+    static interface OriginalService {
+        public void invoke();
+    }
+    
+    static interface AdaptedService {
+        public void invoke();
+    }
+    
+    static class ServiceProvider implements OriginalService {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke() {
+            m_ensure.step(2);
+        }
+    }
+    
+    public static class ServiceAdapter implements AdaptedService {
+        private volatile OriginalService m_originalService;
+        
+        public void start() { System.out.println("start"); }
+        public void stop() { System.out.println("stop"); }
+        public void invoke() {
+            m_originalService.invoke();
+        }
+    }
+
+    static class ServiceConsumer {
+        private volatile AdaptedService m_service;
+        private final Ensure m_ensure;
+        
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        public void start() {
+            m_ensure.step(1);
+            m_service.invoke();
+        }
+        public void stop() {
+            m_ensure.step(3);
+        }
+    }
+}
+
+
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterNoAutoConfigIfInstanceCallbackIsUsed.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterNoAutoConfigIfInstanceCallbackIsUsed.java
new file mode 100644
index 0000000..32d30df
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterNoAutoConfigIfInstanceCallbackIsUsed.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.adapter;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+
+/**
+ * This tests validates that autoconfiguration of adapted service on adapter class field(s) is not
+ * enabled when an instance callback is used when injected adapted service.
+ */
+public class AdapterNoAutoConfigIfInstanceCallbackIsUsed extends TestBase {
+    static Ensure m_e;
+
+    public void testNoAutoConfigIfInstanceCallbackIsUsed() {
+        m_e = new Ensure();
+        DependencyManager m = getDM();
+        
+        // Declare S1 service
+        component(m, c -> c.impl(S1Impl.class).provides(S1.class));
+        
+        // Declare S1 adapter
+        S1AdapterCallback s1AdapterCB = new S1AdapterCallback();
+        adapter(m, S1.class, a -> a.impl(S1Adapter.class).cbi(s1AdapterCB, "set"));
+        
+        // At this point, the s1AdapterCB.set(S1 s1) method should be called, and s1Adapter.start() method should then be called.
+        // but s1 should not be injected on s1Adapter class fields.
+        
+        m_e.waitForStep(3, 5000);
+        m.clear();
+    }
+    
+    public void testNoAutoConfigIfInstanceCallbackIsUsedRef() {
+        m_e = new Ensure();
+        DependencyManager m = getDM();
+        
+        // Declare S1 service
+        component(m, c -> c.impl(S1Impl.class).provides(S1.class));
+        
+        // Declare S1 adapter
+        S1AdapterCallback s1AdapterCB = new S1AdapterCallback();
+        adapter(m, S1.class, a -> a.impl(S1Adapter.class).cbi(s1AdapterCB::set));
+        
+        // At this point, the s1AdapterCB.set(S1 s1) method should be called, and s1Adapter.start() method should then be called.
+        // but s1 should not be injected on s1Adapter class fields.
+        
+        m_e.waitForStep(3, 5000);
+        m.clear();
+    }
+    
+    public interface S1 {        
+    }
+    
+    public static class S1Impl implements S1 {        
+    }
+    
+    public static class S1Adapter {
+        volatile S1 m_s1; // should not be injected by reflection
+        
+        void start() {
+            m_e.step(2);
+            Assert.assertNull(m_s1);
+            m_e.step(3);
+        }
+    }
+    
+    public static class S1AdapterCallback {
+        void set(S1 s1) {
+            Assert.assertNotNull(s1);
+            m_e.step(1);
+        }
+    }
+    
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithCallbackInstanceTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithCallbackInstanceTest.java
new file mode 100644
index 0000000..f6bcbe2
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithCallbackInstanceTest.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.adapter;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AdapterWithCallbackInstanceTest extends TestBase {
+    
+    public void testServiceWithAdapterAndConsumer() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+
+        ServiceProvider serviceProvider = new ServiceProvider(e);
+        Component provider = component(m).provides(OriginalService.class).impl(serviceProvider).build();
+        Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(AdaptedService.class).build();
+        
+        ServiceAdapterCallbackInstance callbackInstance = new ServiceAdapterCallbackInstance(e);
+        Component adapter = adapter(m, OriginalService.class)
+            .provides(AdaptedService.class).impl(new ServiceAdapter(e)).propagate(true)
+            .autoConfig("m_originalService")
+            .cbi(callbackInstance, "set", "changed", "unset")
+            .build();
+       
+        // add the provider and the adapter
+        m.add(provider);
+        m.add(adapter);
+        // Checks if the callbackInstances is called, and if the adapter start method is called
+        e.waitForStep(2, 5000);
+        
+        // add a consumer that will invoke the adapter
+        // which will in turn invoke the original provider
+        m.add(consumer);
+        // now validate that both have been invoked in the right order
+        e.waitForStep(4, 5000);
+        
+        // change the service properties of the provider, and check that the adapter callback instance is changed.
+        serviceProvider.changeServiceProperties();
+        e.waitForStep(5, 5000);
+        
+        // remove the provider
+        m.remove(provider);
+        // ensure that the consumer is stopped, the adapter callback is called in its unset method, and the adapter is stopped.
+        e.waitForStep(8, 5000);
+        // remove adapter and consumer
+        m.remove(adapter);
+        m.remove(consumer);
+    }
+
+    public void testServiceWithAdapterAndConsumerRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+
+        ServiceProvider serviceProvider = new ServiceProvider(e);
+        Component provider = component(m).provides(OriginalService.class).impl(serviceProvider).build();
+        Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(AdaptedService.class).build();
+        
+        ServiceAdapterCallbackInstance callbackInstance = new ServiceAdapterCallbackInstance(e);
+        Component adapter = adapter(m, OriginalService.class, adp -> adp
+            .provides(AdaptedService.class).impl(new ServiceAdapter(e))
+            .autoAdd(false).propagate(true)
+            .autoConfig("m_originalService")
+            .cbi(callbackInstance::set, callbackInstance::changed, callbackInstance::unset));
+       
+        // add the provider and the adapter
+        m.add(provider);
+        m.add(adapter);
+        // Checks if the callbackInstances is called, and if the adapter start method is called
+        e.waitForStep(2, 5000);
+        
+        // add a consumer that will invoke the adapter
+        // which will in turn invoke the original provider
+        m.add(consumer);
+        // now validate that both have been invoked in the right order
+        e.waitForStep(4, 5000);
+        
+        // change the service properties of the provider, and check that the adapter callback instance is changed.
+        serviceProvider.changeServiceProperties();
+        e.waitForStep(5, 5000);
+        
+        // remove the provider
+        m.remove(provider);
+        // ensure that the consumer is stopped, the adapter callback is called in its unset method, and the adapter is stopped.
+        e.waitForStep(8, 5000);
+        // remove adapter and consumer
+        m.remove(adapter);
+        m.remove(consumer);
+    }
+
+    static interface OriginalService {
+        public void invoke();
+    }
+    
+    static interface AdaptedService {
+        public void invoke();
+    }
+    
+    static class ServiceProvider implements OriginalService {
+        private final Ensure m_ensure;
+        private volatile ServiceRegistration m_registration; // auto injected when started.
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void changeServiceProperties() {
+            Hashtable<String, String> props = new Hashtable<>();
+            props.put("foo", "bar");
+            m_registration.setProperties(props);
+        }
+        public void invoke() {
+            m_ensure.step(4);
+        }
+    }
+    
+    public static class ServiceAdapter implements AdaptedService {
+        private volatile OriginalService m_originalService;
+        private final Ensure m_ensure;
+        
+        public ServiceAdapter(Ensure e) {
+            m_ensure = e;
+        }
+
+        public void start() { m_ensure.step(2); }
+        public void stop() { m_ensure.step(7); }
+        public void invoke() {
+            m_originalService.invoke();
+        }
+    }
+
+    public static class ServiceAdapterCallbackInstance {
+        private final Ensure m_ensure;
+        public ServiceAdapterCallbackInstance(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void set(OriginalService m_originalService, Map<String, Object> props) {
+            m_ensure.step(1);
+        }
+        
+        public void changed(OriginalService m_originalService, Map<String, Object> props) {   
+            Assert.assertEquals("bar", props.get("foo"));
+            m_ensure.step(5);
+        }
+        
+        public void unset(OriginalService m_originalService, Map<String, Object> props) {            
+            m_ensure.step(8);
+        }
+    }
+
+    static class ServiceConsumer {
+        private volatile AdaptedService m_service;
+        private final Ensure m_ensure;
+        
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        public void start() {
+            m_ensure.step(3);
+            m_service.invoke();
+        }
+        public void stop() {
+            m_ensure.step(6);
+        }
+    }
+}
+
+
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithExtraDependenciesTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithExtraDependenciesTest.java
new file mode 100644
index 0000000..c514b2d
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithExtraDependenciesTest.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.adapter;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AdapterWithExtraDependenciesTest extends TestBase {
+    
+    public void testAdapterWithExtraDependenciesAndCallbacks() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service adapter that adapts to services S1 and has an optional dependency on services S2
+        Component sa = adapter(m, S1.class).impl(SA.class).withSrv(S2.class, s2 -> s2.cb("add", "remove")).build();
+        m.add(sa);
+        
+        // create a service S1, which triggers the creation of the first adapter instance (A1)
+        Component s1 = component(m).provides(S1.class).impl(new S1Impl()).build();
+        m.add(s1);
+        
+        // create a service S2, which will be added to A1
+        Component s2 = component(m).provides(S2.class).impl(new S2Impl(e)).build();
+        m.add(s2);
+        
+        // create a second service S1, which triggers the creation of the second adapter instance (A2)
+        Component s1b = component(m).provides(S1.class).impl(new S1Impl()).build();
+        m.add(s1b);
+        
+        // observe that S2 is also added to A2
+        e.waitForStep(2, 5000);
+        
+        // remove S2 again
+        m.remove(s2);
+        
+        // make sure both adapters have their "remove" callbacks invoked
+        e.waitForStep(4, 5000);
+        
+        m.remove(s1);
+        m.remove(sa);
+        m.clear();
+    }
+    
+    public void testAdapterWithExtraDependenciesAndCallbacksRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service adapter that adapts to services S1 and has an optional dependency on services S2
+        Component sa = adapter(m, S1.class).impl(SA.class).withSrv(S2.class, s2 -> s2.cb(SA::add, SA::remove)).build();
+        m.add(sa);
+        
+        // create a service S1, which triggers the creation of the first adapter instance (A1)
+        Component s1 = component(m).provides(S1.class).impl(new S1Impl()).build();
+        m.add(s1);
+        
+        // create a service S2, which will be added to A1
+        Component s2 = component(m).provides(S2.class).impl(new S2Impl(e)).build();
+        m.add(s2);
+        
+        // create a second service S1, which triggers the creation of the second adapter instance (A2)
+        Component s1b = component(m).provides(S1.class).impl(new S1Impl()).build();
+        m.add(s1b);
+        
+        // observe that S2 is also added to A2
+        e.waitForStep(2, 5000);
+        
+        // remove S2 again
+        m.remove(s2);
+        
+        // make sure both adapters have their "remove" callbacks invoked
+        e.waitForStep(4, 5000);
+        
+        m.remove(s1);
+        m.remove(sa);
+        m.clear();
+    }
+
+    static interface S1 {
+    }
+    static interface S2 {
+        public void invoke();
+    }
+    static class S1Impl implements S1 {
+    }
+    static class S2Impl implements S2 {
+
+        private final Ensure m_e;
+
+        public S2Impl(Ensure e) {
+            m_e = e;
+        }
+
+        public void invoke() {
+            m_e.step();
+        }
+    }
+    
+    public static class SA {
+        volatile S2 s2;
+        
+        public SA() {
+            System.out.println("Adapter created");
+        }
+        public void init() {
+            System.out.println("Adapter init " + s2);
+        }
+        public void add(S2 s) {
+            System.out.println("adding " + s);
+            s.invoke();
+        }
+        public void remove(S2 s) {
+            System.out.println("removing " + s);
+            s.invoke();
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithInstanceBoundDependencyParallelTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithInstanceBoundDependencyParallelTest.java
new file mode 100644
index 0000000..c332654
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithInstanceBoundDependencyParallelTest.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AdapterWithInstanceBoundDependencyParallelTest extends AdapterWithInstanceBoundDependencyTest {
+    public AdapterWithInstanceBoundDependencyParallelTest() {
+        setParallel();
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithInstanceBoundDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithInstanceBoundDependencyTest.java
new file mode 100644
index 0000000..4d436fb
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithInstanceBoundDependencyTest.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.adapter;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AdapterWithInstanceBoundDependencyTest extends TestBase {
+    
+    public void testInstanceBoundDependency() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        
+        Component sp = component(m).provides(ServiceInterface.class).impl(new ServiceProvider(e)).build();
+        Component sp2 = component(m).provides(ServiceInterface2.class).impl(new ServiceProvider2(e)).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).autoAdd(false).withSrv(ServiceInterface3.class).build();
+        Component sa = adapter(m, ServiceInterface.class).provides(ServiceInterface3.class).impl(new ServiceAdapter(e)).build();
+        m.add(sc);
+        m.add(sp);
+        m.add(sp2);
+        m.add(sa);
+        e.waitForStep(5, 15000);
+        // cleanup
+        m.remove(sa);
+        m.remove(sp2);
+        m.remove(sp);
+        m.remove(sc);
+        m.clear();
+        e.waitForStep(9, 5000); // make sure all components are stopped
+    }       
+    
+    static interface ServiceInterface {
+        public void invoke();
+    }
+    
+    static interface ServiceInterface2 {
+        public void invoke();
+    }
+    
+    static interface ServiceInterface3 {
+        public void invoke();
+    }
+    
+    static class ServiceProvider2 implements ServiceInterface2 {
+        private final Ensure m_ensure;
+
+        public ServiceProvider2(Ensure ensure) {
+            m_ensure = ensure;
+        }
+
+        public void invoke() {
+            m_ensure.step(4);
+        }
+        
+        public void stop() {
+            m_ensure.step();
+        }
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke() {
+            m_ensure.step(5);
+        }
+        public void stop() {
+            m_ensure.step();
+        }
+    }
+    
+    static class ServiceAdapter implements ServiceInterface3 {
+        private Ensure m_ensure;
+        private volatile ServiceInterface m_originalService;
+        private volatile ServiceInterface2 m_injectedService;
+        private volatile Component m_component;
+        private volatile DependencyManager m_manager;
+        
+        public ServiceAdapter(Ensure e) {
+            m_ensure = e;
+        }
+        public void init() {
+            m_ensure.step(1);
+            component(m_component, c->c.withSrv(ServiceInterface2.class));
+        }
+        public void start() {
+            m_ensure.step(2);
+        }
+        public void invoke() {
+            m_ensure.step(3);
+            m_injectedService.invoke();
+            m_originalService.invoke();
+        }
+        
+        public void stop() {
+            m_ensure.step();
+        }
+    }
+
+    static class ServiceConsumer implements Runnable {
+        volatile ServiceInterface3 m_service;
+        final Ensure m_ensure;
+        
+        ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            Thread t = new Thread(this);
+            t.start();
+        }
+        
+        public void run() {
+            m_service.invoke();
+        }
+        public void stop() {
+            m_ensure.step();
+        }
+    }
+}
+
+
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithModifiedInstanceBoundDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithModifiedInstanceBoundDependencyTest.java
new file mode 100644
index 0000000..93fe8b6
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithModifiedInstanceBoundDependencyTest.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.adapter;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+
+/**
+ * Test for FELIX-4334 issue.
+ * 
+ * Three components: A, B and C
+ * 
+ * - A provided with property foo=bar
+ * - B adapts A, B has no filters on A, and B.init() method adds an instance bound required dependency to C.
+ * - C depends on A(foo=bar)
+ * - Now someone modifies the service properties of A: foo=bar2
+ * - As a result of that, C becomes unavailable and is unbound from B.
+ * - Since B has an instance bound required dependency to C: B should not be destroyed: it should be called in B.stop(), B.remove(C), B.change(A, "foo=bar2))
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AdapterWithModifiedInstanceBoundDependencyTest extends TestBase {
+    public static interface A {
+    }
+    
+    static class AImpl implements A {
+        final Ensure m_e;
+        AImpl(Ensure e) {
+            m_e = e;
+        }        
+    }
+    
+    public static interface C {
+    }
+
+    static class CImpl implements C {
+        volatile A m_a;
+    }
+    
+    public static interface B {
+    }
+    
+    public static class BImpl implements B {
+        final Ensure m_e;
+        volatile A m_a;
+        volatile C m_c;
+        
+        BImpl(Ensure e) {
+            m_e = e;
+        }
+        
+        void init(Component comp) {
+            m_e.step(2);
+            component(comp, c->c.withSrv(C.class, s->s.cb("addC", "removeC")));
+        }      
+        
+        void addA(A a, Map<String, Object> properties) {
+            m_e.step(1);
+        }
+
+        public void addC(C c) {
+            m_e.step(3);
+        }
+        
+        public void start() {
+            m_e.step(4);            
+        }
+        
+        public void stop() { // C becomes unsatisfied when A properties are changed to foo=bar2
+            m_e.step(5);
+        }
+
+        public void removeC(C c) {
+            m_e.step(6);
+        }
+
+        public void changeA(A a, Map<String, Object> properties) {
+            Assert.assertEquals("bar2", properties.get("foo"));
+            m_e.step(7);
+        }
+        
+        public void destroy() {
+            m_e.step(8);
+        }
+
+        public void removeA(A a, Map<String, Object> properties) {   
+            m_e.step(9);
+        }                    
+    }
+    
+    public void testAdapterWithChangedInstanceBoundDependency() {
+        DependencyManager m = getDM();
+        Ensure e = new Ensure();
+
+        Component a = component(m).impl(new AImpl(e)).provides(A.class).properties(foo -> "bar").build();
+        Component b = adapter(m, A.class).provides(B.class).impl(new BImpl(e)).cb("addA", "changeA", "removeA").build();
+        Component c = component(m).impl(new CImpl()).provides(C.class).withSrv(A.class, "(foo=bar)").build();
+                      
+        m.add(a);
+        m.add(c);
+        m.add(b);
+        
+        e.waitForStep(4, 5000);
+        
+        System.out.println("changing A props ...");
+        Properties props = new Properties();
+        props.put("foo", "bar2");
+        a.setServiceProperties(props);
+        
+        e.waitForStep(7, 5000);                
+        
+        m.remove(c);
+        m.remove(a);
+        m.remove(b);
+        
+        e.waitForStep(9, 5000);                
+    }
+    
+    public void testAdapterWithChangedInstanceBoundDependencyRef() {
+        DependencyManager m = getDM();
+        Ensure e = new Ensure();
+
+        Component a = component(m).impl(new AImpl(e)).provides(A.class).properties(foo -> "bar").build();        
+        Component b = adapter(m, A.class).impl(new BImpl(e)).provides(B.class).cb(BImpl::addA, BImpl::changeA, BImpl::removeA).build();        
+        Component c = component(m).impl(new CImpl()).provides(C.class).withSrv(A.class, s -> s.filter("(foo=bar)")).build();
+                      
+        m.add(a);
+        m.add(c);
+        m.add(b);
+        
+        e.waitForStep(4, 5000);
+        
+        System.out.println("changing A props ...");
+        Properties props = new Properties();
+        props.put("foo", "bar2");
+        a.setServiceProperties(props);
+        
+        e.waitForStep(7, 5000);                
+        
+        m.remove(c);
+        m.remove(a);
+        m.remove(b);
+        
+        e.waitForStep(9, 5000);                
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithPropagationTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithPropagationTest.java
new file mode 100644
index 0000000..e56bd44
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithPropagationTest.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.adapter;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+
+/**
+ * Checks if a service adapter propagates its service properties, if 
+ * the adapted service properties are changed:
+ * 
+ * S1Impl provides S
+ * S1Adapter adapts S1Impl(S) to S2
+ * S3 depends on S2
+ * 
+ * So, when S1Impl service properties are changed, S1Adapter shall propagate the changed properties to S3.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class AdapterWithPropagationTest extends TestBase {
+    public static interface S1 {}
+    
+    static class S1Impl implements S1 {
+        private Ensure m_ensure;
+        public S1Impl(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void start() {
+            m_ensure.step(1);
+        }
+    }
+    
+    public static interface S2 {}
+
+    static class S1Adapter implements S2 {
+        private Ensure m_ensure;
+        public S1Adapter(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void add(Map properties, S1 s1) {
+            Assert.assertTrue("v1".equals(properties.get("p1")));
+            Assert.assertTrue("v2overriden".equals(properties.get("p2")));
+            m_ensure.step(2);
+        }
+        
+        public void change(Map properties, S1 s1) {   
+            Assert.assertTrue("v1modified".equals(properties.get("p1")));
+            Assert.assertTrue("v2overriden".equals(properties.get("p2")));
+            m_ensure.step(4);
+        }
+    }
+
+    static class S3 {
+        private final Ensure m_ensure;
+
+        public S3(Ensure e) {
+            m_ensure = e;
+        }
+                        
+        public void add(Map properties, S2 s2) {
+            Assert.assertTrue("v1".equals(properties.get("p1")));
+            Assert.assertTrue("v2".equals(properties.get("p2"))); // s1 should not override adapter service properties
+            m_ensure.step(3);
+        }
+        
+        public void change(Map properties, S2 s2) {
+            Assert.assertTrue("v1modified".equals(properties.get("p1")));
+            Assert.assertTrue("v2".equals(properties.get("p2"))); // s1 should not override adapter service properties
+            m_ensure.step(5);
+        }
+    }
+    
+    public void testAdapterWithPropagation() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure(); 
+        
+        Component s1 = component(m).impl(new S1Impl(e)).provides(S1.class).properties(p1 -> "v1", p2 -> "v2overriden").build();
+        Component s1Adapter = adapter(m, S1.class).cb("add", "change", null).impl(new S1Adapter(e)).provides(S2.class).properties(p2 -> "v2").build();   
+        Component s3 = component(m).impl(new S3(e)).withSrv(S2.class, s -> s.cb("add", "change", null)).build();
+                                          
+        m.add(s1);
+        m.add(s1Adapter);
+        m.add(s3);
+        
+        e.waitForStep(3, 5000);
+        
+        Hashtable s1Properties = new Hashtable();
+        s1Properties.put("p1", "v1modified");
+        s1Properties.put("p2", "v2overriden");
+        s1.setServiceProperties(s1Properties);
+        
+        e.waitForStep(5, 5000);
+
+        m.clear();
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithoutPropagationTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithoutPropagationTest.java
new file mode 100644
index 0000000..41c4ad9
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithoutPropagationTest.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.adapter;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AdapterWithoutPropagationTest extends TestBase {
+    
+    public void testAdapterNoPropagate() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+
+        // The provider has a "foo=bar" property
+        ServiceProvider serviceProvider = new ServiceProvider(e);
+        Component provider = component(m).provides(OriginalService.class).properties(foo -> "bar").impl(serviceProvider).build();
+
+        // The Adapter will see the "foo=bar" property from the adaptee
+        Component adapter = adapter(m, OriginalService.class)
+            .propagate(false).cb("set", "change", null).provides(AdaptedService.class).impl(new ServiceAdapter(e)).build();
+
+        // The consumer depends on the AdaptedService, but won't see foo=bar property from the adaptee 
+        Component consumer = component(m) 
+            .impl(new ServiceConsumer(e)).withSrv(AdaptedService.class, b -> b.cb("set", "change", null)).build();
+        
+        // add the provider and the adapter
+        m.add(provider);
+        m.add(adapter);
+        // Checks if the adapter has been started and has seen the adaptee properties
+        e.waitForStep(1, 5000);
+        
+        // add a consumer that must not see the adaptee service properties
+        m.add(consumer);
+        e.waitForStep(2, 5000);
+        
+        // change the service properties of the provider, and check that the adapter callback instance is caled.
+        serviceProvider.changeServiceProperties();
+        e.waitForStep(3, 5000);
+        
+        // cleanup
+        m.clear();
+    }
+
+    public void testAdapterNoPropagateRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+
+        // The provider has a "foo=bar" property
+        ServiceProvider serviceProvider = new ServiceProvider(e);
+        Component provider = component(m).provides(OriginalService.class).properties(foo -> "bar").impl(serviceProvider).build();
+
+        // The Adapter will see the "foo=bar" property from the adaptee
+        ServiceAdapter saimpl = new ServiceAdapter(e);
+        Component adapter = adapter(m, OriginalService.class).propagate(false).impl(saimpl).provides(AdaptedService.class).cbi(saimpl::set, saimpl::change, null).build();           
+
+        // The consumer depends on the AdaptedService, but won't see foo=bar property from the adaptee 
+        ServiceConsumer scimpl = new ServiceConsumer(e);
+        Component consumer = component(m).impl(scimpl).withSrv(AdaptedService.class, s -> s.cbi(scimpl::set, scimpl::change, null)).build();
+        
+        // add the provider and the adapter
+        m.add(provider);
+        m.add(adapter);
+        // Checks if the adapter has been started and has seen the adaptee properties
+        e.waitForStep(1, 5000);
+        
+        // add a consumer that must not see the adaptee service properties
+        m.add(consumer);
+        e.waitForStep(2, 5000);
+        
+        // change the service properties of the provider, and check that the adapter callback instance is caled.
+        serviceProvider.changeServiceProperties();
+        e.waitForStep(3, 5000);
+        
+        // cleanup
+        m.clear();
+    }
+
+    static interface OriginalService {
+    }
+    
+    static interface AdaptedService {
+    }
+    
+    static class ServiceProvider implements OriginalService {
+        private volatile ServiceRegistration m_registration; // auto injected when started.
+        public ServiceProvider(Ensure e) {
+        }
+        public void changeServiceProperties() {
+            Hashtable<String, String> props = new Hashtable<>();
+            props.put("foo", "bar2");
+            m_registration.setProperties(props);
+        }
+    }
+    
+    public static class ServiceAdapter implements AdaptedService {
+        private final Ensure m_ensure;
+        
+        public ServiceAdapter(Ensure e) {
+            m_ensure = e;
+        }
+
+        public void set(OriginalService adaptee, Dictionary<String, Object> props) {
+            Assert.assertEquals("bar", props.get("foo"));
+            m_ensure.step(1);
+        }
+        
+        void change(OriginalService adapted, Dictionary<String, Object> props) {
+            Assert.assertEquals("bar2", props.get("foo"));
+            m_ensure.step(3);
+        }
+    }
+
+    static class ServiceConsumer {
+        @SuppressWarnings("unused")
+		private volatile AdaptedService m_service;
+        private final Ensure m_ensure;
+        
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        void set(AdaptedService adapted, Dictionary<String, Object> props) {
+            Assert.assertNull(props.get("foo"));
+            m_ensure.step(2);
+        }
+        
+        void change(AdaptedService adapted, Dictionary<String, Object> props) {
+            Assert.assertNull(props.get("foo"));
+            Assert.fail("Change callback should not be called");
+        }
+    }
+}
+
+
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectBaseTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectBaseTest.java
new file mode 100644
index 0000000..e207545
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectBaseTest.java
@@ -0,0 +1,337 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectBaseTest extends TestBase {    
+
+	public void testSingleAspect() {
+	    DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service provider and consumer
+        ServiceProvider p = new ServiceProvider(e, "a");
+        ServiceConsumer c = new ServiceConsumer(e);
+        
+        Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();
+        Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cb("add", "remove").autoConfig("m_service")).build();
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+            
+        m.add(sc);
+        m.add(sp);
+        // after the provider was added, the consumer's add should have been invoked once
+        e.waitForStep(1, 2000);
+        Assert.assertEquals("a", c.invoke());
+        m.add(sa);
+        // after the aspect was added, the consumer should get and add for the aspect and a remove
+        // for the original service
+        e.waitForStep(3, 2000);
+        Assert.assertEquals("aa", c.invoke());
+        m.remove(sa);
+        // removing the aspect again should give a remove and add
+        e.waitForStep(5, 2000);
+        Assert.assertEquals("a", c.invoke());
+        m.remove(sp);
+        // finally removing the original service should give a remove
+        e.waitForStep(6, 2000);
+        m.remove(sc);
+        e.step(7);
+        clearComponents();
+    }
+    
+    public void testSingleAspectRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service provider and consumer
+        ServiceProvider p = new ServiceProvider(e, "a");
+        ServiceConsumer c = new ServiceConsumer(e);
+        
+        Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();        
+        Component sc = component(m)
+            .impl(c).withSrv(ServiceInterface.class, srv -> srv.cbi(c::add, c::remove).autoConfig("m_service")).build();
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+        
+        m.add(sc);
+        m.add(sp);
+        // after the provider was added, the consumer's add should have been invoked once
+        e.waitForStep(1, 2000);
+        Assert.assertEquals("a", c.invoke());
+        m.add(sa);
+        // after the aspect was added, the consumer should get and add for the aspect and a remove
+        // for the original service
+        e.waitForStep(3, 2000);
+        Assert.assertEquals("aa", c.invoke());
+        m.remove(sa);
+        // removing the aspect again should give a remove and add
+        e.waitForStep(5, 2000);
+        Assert.assertEquals("a", c.invoke());
+        m.remove(sp);
+        // finally removing the original service should give a remove
+        e.waitForStep(6, 2000);
+        m.remove(sc);
+        e.step(7);
+        clearComponents();
+    }
+    
+    @SuppressWarnings("serial")
+    public void testSingleAspectThatAlreadyExisted() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service provider and consumer
+        ServiceProvider p = new ServiceProvider(e, "a");
+        ServiceConsumer c = new ServiceConsumer(e);
+        Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();            
+        Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cb("add", "remove").autoConfig("m_service")).build();
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+
+        // we first add the aspect
+        m.add(sa);
+        // then the service provider
+        m.add(sp);
+        // finally the consumer
+        m.add(sc);
+
+        Assert.assertEquals("aa", c.invoke());
+        
+        // now the consumer's added should be invoked once, as the aspect is already available and should
+        // directly hide the original service
+        e.waitForStep(1, 2000);
+        e.step(2);
+
+        m.remove(sa);
+        // after removing the aspect, the consumer should get the original service back, so
+        // remove and add will be invoked
+        e.waitForStep(4, 2000);
+        
+        Assert.assertEquals("a", c.invoke());
+        
+        m.remove(sp);
+        // after removing the original service, the consumer's remove should be called once
+        e.waitForStep(5, 2000);
+        
+        m.remove(sc);
+        e.step(6);
+    }
+
+    public void testSingleAspectThatAlreadyExistedRef() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service provider and consumer
+        ServiceProvider p = new ServiceProvider(e, "a");
+        ServiceConsumer c = new ServiceConsumer(e);
+        
+        Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();
+        Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cbi(c::add, c::remove).autoConfig("m_service")).build();
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+
+        // we first add the aspect
+        m.add(sa);
+        // then the service provider
+        m.add(sp);
+        // finally the consumer
+        m.add(sc);
+
+        Assert.assertEquals("aa", c.invoke());
+        
+        // now the consumer's added should be invoked once, as the aspect is already available and should
+        // directly hide the original service
+        e.waitForStep(1, 2000);
+        e.step(2);
+
+        m.remove(sa);
+        // after removing the aspect, the consumer should get the original service back, so
+        // remove and add will be invoked
+        e.waitForStep(4, 2000);
+        
+        Assert.assertEquals("a", c.invoke());
+        
+        m.remove(sp);
+        // after removing the original service, the consumer's remove should be called once
+        e.waitForStep(5, 2000);
+        
+        m.remove(sc);
+        e.step(6);
+    }
+
+    public void testMultipleAspects() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create service providers and consumers
+        ServiceConsumer c = new ServiceConsumer(e);
+        Component sp = component(m).impl(new ServiceProvider(e, "a")).provides(ServiceInterface.class).properties(name -> "a").build();
+        Component sp2 = component(m).impl(new ServiceProvider(e, "b")).provides(ServiceInterface.class).properties(name -> "b").build();
+        Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cb("add", "remove")).build();
+
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+        Component sa2 = aspect(m, ServiceInterface.class).rank(10).impl(ServiceAspect.class).build();
+
+        m.add(sp);
+        m.add(sp2);
+        m.add(sa);
+        m.add(sa2);
+        m.add(sc);
+        // the consumer will monitor progress, it should get it's add invoked twice, once for every
+        // (highest) aspect
+        e.waitForStep(2, 2000);
+        e.step(3);
+        
+        // now invoke all services the consumer collected
+        List<String> list = c.invokeAll();
+        // and make sure both of them are correctly invoked
+        Assert.assertTrue(list.size() == 2);
+        Assert.assertTrue(list.contains("aaa"));
+        Assert.assertTrue(list.contains("bbb"));
+        
+        m.remove(sc);
+        // removing the consumer now should get its removed method invoked twice
+        e.waitForStep(5, 2000);
+        e.step(6);
+        m.remove(sa2);
+        m.remove(sa);
+        m.remove(sp2);
+        m.remove(sp);
+        e.step(7);
+    }
+    
+    public void testMultipleAspectsRef() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create service providers and consumers
+        ServiceConsumer c = new ServiceConsumer(e);
+        Component sp = component(m).impl(new ServiceProvider(e, "a")).provides(ServiceInterface.class).properties(name -> "a").build();
+        Component sp2 = component(m).impl(new ServiceProvider(e, "b")).provides(ServiceInterface.class).properties(name -> "b").build();
+        Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cbi(c::add, c::remove)).build();
+
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+        Component sa2 = aspect(m, ServiceInterface.class).rank(10).impl(ServiceAspect.class).build();
+
+        m.add(sp);
+        m.add(sp2);
+        m.add(sa);
+        m.add(sa2);
+        m.add(sc);
+        // the consumer will monitor progress, it should get it's add invoked twice, once for every
+        // (highest) aspect
+        e.waitForStep(2, 2000);
+        e.step(3);
+        
+        // now invoke all services the consumer collected
+        List<String> list = c.invokeAll();
+        // and make sure both of them are correctly invoked
+        Assert.assertTrue(list.size() == 2);
+        Assert.assertTrue(list.contains("aaa"));
+        Assert.assertTrue(list.contains("bbb"));
+        
+        m.remove(sc);
+        // removing the consumer now should get its removed method invoked twice
+        e.waitForStep(5, 2000);
+        e.step(6);
+        m.remove(sa2);
+        m.remove(sa);
+        m.remove(sp2);
+        m.remove(sp);
+        e.step(7);
+    }
+    
+    public static interface ServiceInterface {
+        public String invoke(String input);
+    }
+    
+    public static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        private final String m_name;
+        public ServiceProvider(Ensure e, String name) {
+            m_ensure = e;
+            m_name = name;
+        }
+        public String invoke(String input) {
+            return input + m_name;
+        }
+    }
+    
+    public static class ServiceAspect implements ServiceInterface {
+        private volatile ServiceInterface m_originalService;
+        private volatile ServiceRegistration m_registration;
+        
+        public String invoke(String input) {
+            String result = m_originalService.invoke(input);
+            String property = (String) m_registration.getReference().getProperty("name");
+            return result + property;
+        }
+    }
+    
+    public static class ServiceConsumer {
+        private final Ensure m_ensure;
+        private volatile ServiceInterface m_service;
+        private List<ServiceInterface> m_services = new ArrayList<ServiceInterface>();
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void add(ServiceReference<ServiceInterface> ref, ServiceInterface si) {
+            System.out.println("add: " + ServiceUtil.toString(ref));
+            m_services.add(si);
+            m_ensure.step();
+        }
+        
+        public void remove(ServiceReference<ServiceInterface> ref, ServiceInterface si) {
+            System.out.println("rem: " + ServiceUtil.toString(ref));
+            m_services.remove(si);
+            m_ensure.step();
+        }
+        
+        public String invoke() {
+            return m_service.invoke("");
+        }
+        
+        public List<String> invokeAll() {
+            List<String> results = new ArrayList<String>();
+            for (ServiceInterface si : m_services) {
+                results.add(si.invoke(""));
+            }
+            return results;
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectChainTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectChainTest.java
new file mode 100644
index 0000000..81bfa7e
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectChainTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectChainTest extends TestBase {
+
+	public void testBuildAspectChain() {
+	    DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class).build();
+        Component sa2 = aspect(m, ServiceInterface.class).rank(20).impl(new ServiceAspect(e, 3)).build();
+        Component sa3 = aspect(m, ServiceInterface.class).rank(30).impl(new ServiceAspect(e, 2)).build();
+        Component sa1 = aspect(m, ServiceInterface.class).rank(10).impl(new ServiceAspect(e, 4)).build();
+        m.add(sc);
+
+        m.add(sp);
+        m.add(sa2);
+        m.add(sa3);
+        m.add(sa1);
+        e.step();
+        e.waitForStep(5,  5000);
+        
+        m.remove(sa3);
+        m.remove(sa2);
+        m.remove(sa1);
+        m.remove(sp);
+        
+        m.remove(sc);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(Runnable run);
+    }
+    
+    static class ServiceProvider implements ServiceInterface {
+        @SuppressWarnings("unused")
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(Runnable run) {
+            run.run();
+        }
+    }
+    
+    static class ServiceAspect implements ServiceInterface {
+        private final Ensure m_ensure;
+        private volatile ServiceInterface m_parentService;
+        private final int m_step;
+        
+        public ServiceAspect(Ensure e, int step) {
+            m_ensure = e;
+            m_step = step;
+        }
+        public void start() {
+        }
+        
+        public void invoke(Runnable run) {
+            m_ensure.step(m_step);
+            m_parentService.invoke(run);
+        }
+        
+        public void stop() {
+        }
+    }
+
+    static class ServiceConsumer implements Runnable {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            Thread t = new Thread(this);
+            t.start();
+        }
+        
+        public void run() {
+            m_ensure.waitForStep(1, 2000);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 5));
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectDynamicsTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectDynamicsTest.java
new file mode 100644
index 0000000..b89ef9a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectDynamicsTest.java
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectDynamicsTest extends TestBase {
+
+	public void testDynamicallyAddAndRemoveAspect() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        Ensure aspectStopEnsure = new Ensure();
+        // create a service provider and consumer
+        Component provider = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component provider2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class.getName()).build();
+        Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", null, null, "swap")).build();
+        Component aspect = aspect(m, ServiceInterface.class).autoAdd(false).rank(1).impl(new ServiceAspect(e, aspectStopEnsure)).build();
+        
+        m.add(consumer);
+        m.add(provider);
+        // the consumer should invoke the provider here, and when done, arrive at step 3
+        // finally wait for step 6 before continuing
+        e.waitForStep(3, 15000);
+        
+        m.add(aspect);
+        // after adding the aspect, we wait for its init to be invoked, arriving at
+        // step 4 after an instance bound dependency was added (on a service provided by
+        // provider 2)
+        e.waitForStep(4, 15000);
+        
+        m.add(provider2);
+        
+        // after adding provider 2, we should now see the client being swapped, so
+        // we wait for step 5 to happen
+        e.waitForStep(5, 15000);
+        
+        // now we continue with step 6, which will trigger the next part of the consumer's
+        // run method to be executed
+        e.step(6);
+        
+        // invoking step 7, 8 and 9 when invoking the aspect which in turn invokes the
+        // dependency and the original service, so we wait for that to finish here, which
+        // is after step 10 has been reached (the client will now wait for step 12)
+        e.waitForStep(10, 15000);
+        
+        m.remove(aspect);
+        aspectStopEnsure.waitForStep(1, 15000);
+        // removing the aspect should trigger step 11 (in the swap method of the consumer)
+        e.waitForStep(11, 15000);
+        
+        // step 12 triggers the client to continue
+        e.step(12);
+        
+        // wait for step 13, the final invocation of the provided service (without aspect)
+        e.waitForStep(13, 15000);
+        
+        // clean up
+        m.remove(provider2);
+        m.remove(provider);
+        m.remove(consumer);
+        e.waitForStep(16, 15000);
+        m.clear();
+    }
+    
+    public void testDynamicallyAddAndRemoveAspectRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        Ensure aspectStopEnsure = new Ensure();
+        // create a service provider and consumer
+        Component provider = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component provider2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class.getName()).build();
+        Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb(ServiceConsumer::add).sw(ServiceConsumer::swap)).build();
+        Component aspect = aspect(m, ServiceInterface.class).autoAdd(false).rank(1).impl(new ServiceAspect(e, aspectStopEnsure)).build();
+        
+        m.add(consumer);
+        m.add(provider);
+        // the consumer should invoke the provider here, and when done, arrive at step 3
+        // finally wait for step 6 before continuing
+        e.waitForStep(3, 15000);
+        
+        m.add(aspect);
+        // after adding the aspect, we wait for its init to be invoked, arriving at
+        // step 4 after an instance bound dependency was added (on a service provided by
+        // provider 2)
+        e.waitForStep(4, 15000);
+        
+        m.add(provider2);
+        
+        // after adding provider 2, we should now see the client being swapped, so
+        // we wait for step 5 to happen
+        e.waitForStep(5, 15000);
+        
+        // now we continue with step 6, which will trigger the next part of the consumer's
+        // run method to be executed
+        e.step(6);
+        
+        // invoking step 7, 8 and 9 when invoking the aspect which in turn invokes the
+        // dependency and the original service, so we wait for that to finish here, which
+        // is after step 10 has been reached (the client will now wait for step 12)
+        e.waitForStep(10, 15000);
+        
+        m.remove(aspect);
+        aspectStopEnsure.waitForStep(1, 15000);
+        // removing the aspect should trigger step 11 (in the swap method of the consumer)
+        e.waitForStep(11, 15000);
+        
+        // step 12 triggers the client to continue
+        e.step(12);
+        
+        // wait for step 13, the final invocation of the provided service (without aspect)
+        e.waitForStep(13, 15000);
+        
+        // clean up
+        m.remove(provider2);
+        m.remove(provider);
+        m.remove(consumer);
+        e.waitForStep(16, 15000);
+        m.clear();
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(Runnable run);
+    }
+    
+    static interface ServiceInterface2 {
+        public void invoke();
+    }
+    
+    static class ServiceProvider2 implements ServiceInterface2 {
+        private final Ensure m_ensure;
+
+        public ServiceProvider2(Ensure ensure) {
+            m_ensure = ensure;
+        }
+
+        public void invoke() {
+            m_ensure.step(9);
+        }
+        public void stop() {
+            m_ensure.step();
+        }
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(Runnable run) {
+            run.run();
+        }
+        public void stop() {
+            m_ensure.step();
+        }
+    }
+    
+    static class ServiceAspect implements ServiceInterface {
+        private final Ensure m_ensure;
+        private volatile ServiceInterface m_originalService;
+        private volatile ServiceInterface2 m_injectedService;
+        private volatile Component m_service;
+        private volatile DependencyManager m_manager;
+        private final Ensure m_stopEnsure;
+        
+        public ServiceAspect(Ensure e, Ensure stopEnsure) {
+            m_ensure = e;
+            m_stopEnsure = stopEnsure;
+        }
+        public void init() {
+            m_service.add(m_manager.createServiceDependency()
+                .setService(ServiceInterface2.class)
+                .setRequired(true)
+            );
+            m_ensure.step(4);
+        }
+
+        public void invoke(Runnable run) {
+            m_ensure.step(7);
+            m_originalService.invoke(run);
+            m_injectedService.invoke();
+        }
+        
+        public void stop() {
+            m_stopEnsure.step(1);
+        }
+    }
+
+    static class ServiceConsumer implements Runnable {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+        private final Ensure.Steps m_swapSteps = new Ensure.Steps(5, 11);
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        void add(ServiceInterface service) {
+            m_service = service;
+        }
+        
+        void swap(ServiceInterface oldService, ServiceInterface newService) {
+            System.out.println("swap: old=" + oldService + ", new=" + newService);
+            m_ensure.steps(m_swapSteps);
+            m_service = newService;
+        }
+        
+        public void init() {
+            Thread t = new Thread(this);
+            t.start();
+        }
+        
+        public void run() {
+            m_ensure.step(1);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 2));
+            m_ensure.step(3);
+            m_ensure.waitForStep(6, 15000);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 8));
+            m_ensure.step(10);
+            m_ensure.waitForStep(12, 15000);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 13));
+        }
+        
+        public void stop() {
+            m_ensure.step();
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyTest.java
new file mode 100644
index 0000000..145cc8c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectServiceDependencyTest extends TestBase {
+    public void testServiceRegistrationAndConsumption() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", "remove")).build();
+        Component asp = aspect(m, ServiceInterface.class).rank(100).impl(ServiceProviderAspect.class).build();
+        		
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(8);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(String caller);
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(String caller) {
+        	if (caller.equals("consumer.init")) {
+        		m_ensure.step(3);
+        	} else if (caller.equals("aspect.consumer.add")) {
+        		m_ensure.step(5);
+        	}
+        }
+    }
+    
+    static class ServiceProviderAspect implements ServiceInterface {
+    	private volatile ServiceInterface m_service;
+    	
+    	public ServiceProviderAspect() {
+		}
+
+		@Override
+		public void invoke(String caller) {
+			m_service.invoke("aspect." + caller);
+		}
+    }
+
+    static class ServiceConsumer {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+        private int addCount = 0;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            m_ensure.step(2);
+            m_service.invoke("consumer.init");
+        }
+        
+        public void destroy() {
+            m_ensure.step(7);
+        }
+        
+        public void add(ServiceInterface service) {
+        	m_service = service;
+        	switch (addCount) {
+        		case 0: m_ensure.step(1);
+        				break;
+        		case 1: m_ensure.step(4);
+        				// aspect had been added
+        				m_service.invoke("consumer.add");
+        				break;
+        		case 2: m_ensure.step(6);
+        				break;
+        		default:
+        	}
+        	addCount ++;
+        }
+        public void remove(ServiceInterface service) {
+        	m_service = null;
+        }    
+    }
+
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java
new file mode 100644
index 0000000..6140f8e
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectServiceDependencyWithSwapCallbackTest extends TestBase {
+    public void testServiceRegistrationAndConsumption() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", null, "remove", "swap")).build();
+        Component asp = aspect(m, ServiceInterface.class).rank(100).impl(ServiceProviderAspect.class).build();
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(7);
+    }
+    
+    public void testServiceRegistrationAndConsumptionRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        ServiceConsumer scimpl = new ServiceConsumer(e);
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sc = component(m).impl(scimpl).withSrv(ServiceInterface.class, s->s.cbi(scimpl::add, scimpl::remove).swi(scimpl::swap)).build();
+        Component asp = aspect(m, ServiceInterface.class).rank(100).impl(ServiceProviderAspect.class).build();
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(7);
+    }
+
+    static interface ServiceInterface {
+        public void invoke(String caller);
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(String caller) {
+        	if (caller.equals("consumer.init")) {
+        		m_ensure.step(3);
+        	} else if (caller.equals("aspect.consumer.add")) {
+        		m_ensure.step(5);
+        	}
+        }
+    }
+    
+    static class ServiceProviderAspect implements ServiceInterface {
+    	private volatile ServiceInterface m_service;
+    	
+    	public ServiceProviderAspect() {
+		}
+
+		@Override
+		public void invoke(String caller) {
+			m_service.invoke("aspect." + caller);
+		}
+    }
+
+    static class ServiceConsumer {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+        private int swapCount = 0;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            m_ensure.step(2);
+            m_service.invoke("consumer.init");
+        }
+        
+        public void destroy() {
+            m_ensure.step(6);
+        }
+        
+        public void add(ServiceInterface service) {
+        	m_service = service;
+        	m_ensure.step(1);
+        }
+        
+        public void remove(ServiceInterface service) {
+        	m_service = null;
+        }
+        
+        public void swap(ServiceInterface previous, ServiceInterface current) {
+        	switch (swapCount) {
+        		case 0: m_ensure.step(4);
+        				break;
+        		case 1: m_ensure.step(5);
+        				break;
+        		default:
+        	}
+        	m_service = current;
+        	swapCount ++;
+        }
+    }
+
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWhiteboardTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWhiteboardTest.java
new file mode 100644
index 0000000..ae45b3c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWhiteboardTest.java
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"rawtypes", "unchecked", "unused"})
+public class AspectWhiteboardTest extends TestBase {
+
+	public void testWhiteboardConsumer() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create service providers and consumer
+        Component sp1 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component sp2 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        ServiceConsumer sci = new ServiceConsumer(e);
+        Component sc = component(m).impl(sci).withSrv(ServiceInterface.class, srv->srv.required(false).cb("add", "remove")).build();
+        Component sa2 = aspect(m, ServiceInterface.class).rank(20).autoAdd(false).impl(new ServiceAspect(e, 3)).build();
+        Component sa1 = aspect(m, ServiceInterface.class).rank(10).autoAdd(false).impl(new ServiceAspect(e, 4)).build();
+        
+        // start with a service consumer
+        System.out.println("Adding consumer");
+        m.add(sc);
+        
+        // then add two providers, so the consumer will see two services
+        System.out.println("Adding 2 providers");
+        m.add(sp1);
+        m.add(sp2);
+        
+        // make sure consumer sees both services
+        Assert.assertEquals(2, sci.services());
+        
+        // add an aspect with ranking 20
+        System.out.println("Adding aspect with rank 20");
+        m.add(sa2);
+        
+        // make sure the consumer sees the two new aspects and no longer sees the two original services
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(20, sci.highestRanking());
+        Assert.assertEquals(20, sci.lowestRanking());
+        
+        // add an aspect with ranking 10
+        System.out.println("Adding aspect with rank 10");
+        m.add(sa1);
+        
+        // make sure the consumer still sees the two aspects with ranking 20
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(20, sci.highestRanking());
+        Assert.assertEquals(20, sci.lowestRanking());
+        
+        // remove the aspect with ranking 20
+        System.out.println("Removing aspect with rank 20");
+        m.remove(sa2);
+        
+        // make sure the consumer now sees the aspects with ranking 10
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(10, sci.highestRanking());
+        Assert.assertEquals(10, sci.lowestRanking());
+        
+        // remove one of the original services
+        System.out.println("Removing 1 service");
+        m.remove(sp1);
+        
+        // make sure the aspect of that service goes away
+        Assert.assertEquals(1, sci.services());
+        Assert.assertEquals(10, sci.highestRanking());
+        Assert.assertEquals(10, sci.lowestRanking());
+        
+        // remove the aspect with ranking 10
+        System.out.println("Removing aspect with rank 10");
+        m.remove(sa1);
+        
+        // make sure only the original service remains
+        Assert.assertEquals(1, sci.services());
+        Assert.assertEquals(0, sci.highestRanking());
+        Assert.assertEquals(0, sci.lowestRanking());
+
+        System.out.println("Done with test");
+
+        // end of test
+        m.remove(sa2);
+        m.remove(sp2);
+        m.remove(sc);
+    }
+    
+    public void testWhiteboardConsumerRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create service providers and consumer
+        Component sp1 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component sp2 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        ServiceConsumer sci = new ServiceConsumer(e);
+        Component sc = component(m).impl(sci).withSrv(ServiceInterface.class, srv->srv.required(false).cbi(sci::add, sci::remove)).build();
+        Component sa2 = aspect(m, ServiceInterface.class).rank(20).autoAdd(false).impl(new ServiceAspect(e, 3)).build();
+        Component sa1 = aspect(m, ServiceInterface.class).rank(10).autoAdd(false).impl(new ServiceAspect(e, 4)).build();
+        
+        // start with a service consumer
+        System.out.println("Adding consumer");
+        m.add(sc);
+        
+        // then add two providers, so the consumer will see two services
+        System.out.println("Adding 2 providers");
+        m.add(sp1);
+        m.add(sp2);
+        
+        // make sure consumer sees both services
+        Assert.assertEquals(2, sci.services());
+        
+        // add an aspect with ranking 20
+        System.out.println("Adding aspect with rank 20");
+        m.add(sa2);
+        
+        // make sure the consumer sees the two new aspects and no longer sees the two original services
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(20, sci.highestRanking());
+        Assert.assertEquals(20, sci.lowestRanking());
+        
+        // add an aspect with ranking 10
+        System.out.println("Adding aspect with rank 10");
+        m.add(sa1);
+        
+        // make sure the consumer still sees the two aspects with ranking 20
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(20, sci.highestRanking());
+        Assert.assertEquals(20, sci.lowestRanking());
+        
+        // remove the aspect with ranking 20
+        System.out.println("Removing aspect with rank 20");
+        m.remove(sa2);
+        
+        // make sure the consumer now sees the aspects with ranking 10
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(10, sci.highestRanking());
+        Assert.assertEquals(10, sci.lowestRanking());
+        
+        // remove one of the original services
+        System.out.println("Removing 1 service");
+        m.remove(sp1);
+        
+        // make sure the aspect of that service goes away
+        Assert.assertEquals(1, sci.services());
+        Assert.assertEquals(10, sci.highestRanking());
+        Assert.assertEquals(10, sci.lowestRanking());
+        
+        // remove the aspect with ranking 10
+        System.out.println("Removing aspect with rank 10");
+        m.remove(sa1);
+        
+        // make sure only the original service remains
+        Assert.assertEquals(1, sci.services());
+        Assert.assertEquals(0, sci.highestRanking());
+        Assert.assertEquals(0, sci.lowestRanking());
+
+        System.out.println("Done with test");
+
+        // end of test
+        m.remove(sa2);
+        m.remove(sp2);
+        m.remove(sc);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(Runnable run);
+    }
+    
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(Runnable run) {
+            run.run();
+        }
+    }
+    
+    static class ServiceAspect implements ServiceInterface {
+        private final Ensure m_ensure;
+        private volatile ServiceInterface m_parentService;
+        private final int m_step;
+        
+        public ServiceAspect(Ensure e, int step) {
+            m_ensure = e;
+            m_step = step;
+        }
+        public void start() {
+        }
+        
+        public void invoke(Runnable run) {
+            m_ensure.step(m_step);
+            m_parentService.invoke(run);
+        }
+        
+        public void stop() {
+        }
+    }
+
+    static class ServiceConsumer implements Runnable {
+        private List m_services = new ArrayList();
+        private final Ensure m_ensure;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            Thread t = new Thread(this);
+            t.start();
+        }
+        
+        public void run() {
+        }
+        
+        public int services() {
+            return m_services.size();
+        }
+        
+        public int highestRanking() {
+            int ranking = Integer.MIN_VALUE;
+            for (int i = 0; i < m_services.size(); i++) {
+                ServiceReference ref = (ServiceReference) m_services.get(i);
+                Integer r = (Integer) ref.getProperty(Constants.SERVICE_RANKING);
+                int rank = r == null ? 0 : r.intValue();
+                ranking = Math.max(ranking, rank);
+            }
+            return ranking;
+        }
+        public int lowestRanking() {
+            int ranking = Integer.MAX_VALUE;
+            for (int i = 0; i < m_services.size(); i++) {
+                ServiceReference ref = (ServiceReference) m_services.get(i);
+                Integer r = (Integer) ref.getProperty(Constants.SERVICE_RANKING);
+                int rank = r == null ? 0 : r.intValue();
+                ranking = Math.min(ranking, rank);
+            }
+            return ranking;
+        }
+        
+        public void add(ServiceReference ref, ServiceInterface svc) {
+            System.out.println("Added: " + ServiceUtil.toString(ref));
+            m_services.add(ref);
+        }
+        public void remove(ServiceReference ref, ServiceInterface svc) {
+            System.out.println("Removed: " + ServiceUtil.toString(ref));
+            m_services.remove(ref);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithCallbacksServiceDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithCallbacksServiceDependencyTest.java
new file mode 100644
index 0000000..4cffad6
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithCallbacksServiceDependencyTest.java
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectWithCallbacksServiceDependencyTest extends TestBase {
+    public void testServiceRegistrationAndConsumption() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", "remove")).build();
+        Component asp = aspect(m, ServiceInterface.class).rank(100).cb("add", null, "remove", "swap").impl(ServiceProviderAspect.class).build();
+            
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(8);
+    }
+    
+    public void testServiceRegistrationAndConsumptionRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb(ServiceConsumer::add, ServiceConsumer::remove)).build();            
+        Component asp = aspect(m, ServiceInterface.class)
+            .impl(ServiceProviderAspect.class).rank(100)
+            .cb(ServiceProviderAspect::add, ServiceProviderAspect::remove).sw(ServiceProviderAspect::swap)
+            .build();
+                
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(8);
+    }
+    
+    public void testServiceRegistrationAndConsumptionWithAspectCallbackInstance() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", "remove")).build();
+                
+        ServiceProviderAspect providerAspect = new ServiceProviderAspect();
+        ServiceProviderAspectCallbackInstance aspectCb = new ServiceProviderAspectCallbackInstance(providerAspect);
+        Component asp = aspect(m, ServiceInterface.class).rank(100).impl(providerAspect).cbi(aspectCb::add, aspectCb::remove).swi(aspectCb::swap).build();
+            
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(8);
+    }
+    
+   static interface ServiceInterface {
+        public void invoke(String caller);
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(String caller) {
+        	if (caller.equals("consumer.init")) {
+        		m_ensure.step(3);
+        	} else if (caller.equals("aspect.consumer.add")) {
+        		m_ensure.step(5);
+        	}
+        }
+    }
+    
+    public static class ServiceProviderAspectCallbackInstance {
+        private final ServiceProviderAspect m_aspect;
+        
+        ServiceProviderAspectCallbackInstance(ServiceProviderAspect aspect) {
+            m_aspect = aspect;
+        }
+        
+        public void add(ServiceInterface service) {
+            m_aspect.add(service);
+        }
+        
+        public void remove(ServiceInterface service) {
+            m_aspect.remove(service);
+        }
+        
+        public void swap(ServiceInterface previous, ServiceInterface current) {
+            m_aspect.swap(previous, current);
+        }
+    }
+
+    static class ServiceProviderAspect implements ServiceInterface {
+    	private volatile ServiceInterface m_service;
+    	
+    	public ServiceProviderAspect() {
+		}
+
+		@Override
+		public void invoke(String caller) {
+			m_service.invoke("aspect." + caller);
+		}
+		
+		public void add(ServiceInterface service) {
+			m_service = service;
+		}
+		
+		public void remove(ServiceInterface service) {
+			m_service = null;
+		}
+		
+		public void swap(ServiceInterface previous, ServiceInterface current) {
+			m_service = current;
+		}
+    }
+
+    static class ServiceConsumer {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+        private int addCount = 0;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            m_ensure.step(2);
+            m_service.invoke("consumer.init");
+        }
+        
+        public void destroy() {
+            m_ensure.step(7);
+        }
+        
+        public void add(ServiceInterface service) {
+        	m_service = service;
+        	switch (addCount) {
+        		case 0: m_ensure.step(1);
+        				break;
+        		case 1: m_ensure.step(4);
+        				// aspect had been added
+        				m_service.invoke("consumer.add");
+        				break;
+        		case 2: m_ensure.step(6);
+        				break;
+        		default:
+        	}
+        	addCount ++;
+        }
+        public void remove(ServiceInterface service) {
+        	m_service = null;
+        }    
+    }
+
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithPropagationTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithPropagationTest.java
new file mode 100644
index 0000000..0a6b336
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithPropagationTest.java
@@ -0,0 +1,716 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.adapter;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+
+/**
+ * Test for aspects with service properties propagations.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"rawtypes", "unchecked", "unused"})
+public class AspectWithPropagationTest extends TestBase {
+    private final static int ASPECTS = 3;
+    private final Set<Integer> _randoms = new HashSet<Integer>();
+    private final Random _rnd = new Random();
+    private static Ensure m_invokeStep;
+    private static Ensure m_changeStep;
+    
+    /**
+     * This test does the following:
+     * 
+     * - Create S service with property "p=s"
+     * - Create SA (aspect of S) with property "p=aspect"
+     * - Create Client, depending on S (actually, on SA).
+     * - Client should see SA with properties p=aspect
+     * - Change S service property with "p=smodified": the Client should be changed with SA(p=aspect)
+     * - Change aspect service property with "p=aspectmodified": The client should be changed with SA(p=aspectmodified)
+     */
+    public void testAspectsWithPropagationNotOverriding() {
+        System.out.println("----------- Running testAspectsWithPropagationNotOverriding ...");
+        DependencyManager m = getDM();
+        m_invokeStep = new Ensure(); 
+        
+        // Create our original "S" service.
+        S s = new S() {
+			public void invoke() {
+			}
+        };
+		Component sComp = component(m).impl(s).provides(S.class, p -> "s").build();
+
+        // Create SA (aspect of S)
+        S sa = new S() {
+        	volatile S m_s;
+			public void invoke() {
+			}
+        };
+        Component saComp = aspect(m, S.class).rank(1).impl(sa).properties(p -> "aspect").build();
+                
+        // Create client depending on S
+        Object client = new Object() {
+        	int m_changeCount;
+        	void add(Map props, S s) {
+        		Assert.assertEquals("aspect", props.get("p"));
+        		m_invokeStep.step(1);
+        	}
+        	
+            void change(Map props, S s) {
+        		switch (++m_changeCount) {
+        		case 1:
+        			Assert.assertEquals("aspect", props.get("p"));
+            		m_invokeStep.step(2);
+            		break;
+        		case 2:
+        			Assert.assertEquals("aspectmodified", props.get("p"));
+            		m_invokeStep.step(3);
+        		}
+        	}
+        };
+        Component clientComp = component(m).impl(client).withSrv(S.class, srv->srv.cb("add", "change", null)).build();
+        
+        // Add components in dependency manager
+        m.add(sComp);
+        m.add(saComp);
+        m.add(clientComp);
+        
+        // client should have been added with SA aspect
+        m_invokeStep.waitForStep(1, 5000);
+        
+        // now change s "p=s" to "p=smodified": client should not see it
+        Hashtable props = new Hashtable();
+        props.put("p", "smodified");
+        sComp.setServiceProperties(props);
+        m_invokeStep.waitForStep(2, 5000);
+        
+        // now change sa aspect "p=aspect" to "p=aspectmodified": client should see it
+        props = new Hashtable();
+        props.put("p", "aspectmodified");
+        saComp.setServiceProperties(props);
+        m_invokeStep.waitForStep(3, 5000);    
+        
+        // remove components
+        m.remove(clientComp);
+        m.remove(saComp);
+        m.remove(sComp);
+    }
+            
+    /**
+     * This test does the following:
+     * 
+     * - Create S service
+     * - Create some S Aspects
+     * - Create a Client, depending on S (actually, on the top-level S aspect)
+     * - Client has a "change" callback in order to track S service properties modifications.
+     * - First, invoke Client.invoke(): all S aspects, and finally original S service must be invoked orderly.
+     * - Modify S original service properties, and check if all aspects, and the client has been orderly called in their "change" callback.
+     * - Modify the First lowest ranked aspect (rank=1), and check if all aspects, and client have been orderly called in their "change" callback.
+     */
+    public void testAspectsWithPropagation() {
+        System.out.println("----------- Running testAspectsWithPropagation ...");
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        m_invokeStep = new Ensure(); 
+        
+        // Create our original "S" service.
+        Dictionary props = new Hashtable();
+        props.put("foo", "bar");
+        Component s = component(m).impl(new SImpl()).provides(S.class, props).build();
+                
+        // Create an aspect aware client, depending on "S" service.
+        Client clientImpl;
+        Component client = component(m).impl((clientImpl = new Client())).withSrv(S.class, srv -> srv.cb("add", "change", "remove", "swap")).build();     
+
+        // Create some "S" aspects
+        Component[] aspects = new Component[ASPECTS];
+        for (int rank = 1; rank <= ASPECTS; rank ++) {
+            aspects[rank-1] = aspect(m, S.class).rank(rank).impl(new A("A" + rank, rank)).cb("add", "change", "remove", "swap").build();
+            props = new Hashtable();
+            props.put("a" + rank, "v" + rank);
+            aspects[rank-1].setServiceProperties(props);
+        }                                    
+              
+        // Register client
+        m.add(client);
+        
+        // Randomly register aspects and original service
+        boolean originalServiceAdded = false;
+        for (int i = 0; i < ASPECTS; i ++) {
+            int index = getRandomAspect();
+            m.add(aspects[index]);
+            if (! originalServiceAdded && _rnd.nextBoolean()) {
+                m.add(s);
+                originalServiceAdded = true;
+            }
+        }
+        if (! originalServiceAdded) {
+            m.add(s);
+        }
+              
+        // All set, check if client has inherited from top level aspect properties + original service properties
+        Map check = new HashMap();
+        check.put("foo", "bar");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS);
+        checkServiceProperties(check, clientImpl.getServiceProperties());
+
+        // Now invoke client, which orderly calls all aspects in the chain, and finally the original service "S".
+        System.out.println("-------------------------- Invoking client.");
+        clientImpl.invoke();
+        m_invokeStep.waitForStep(ASPECTS+1, 5000);
+        
+        // Now, change original service "S" properties: this will orderly trigger "change" callbacks on aspects, and on client. 
+        System.out.println("-------------------------- Modifying original service properties.");
+        m_changeStep = new Ensure();
+        props = new Hashtable();
+        props.put("foo", "barModified");
+        s.setServiceProperties(props);
+        
+        // Check if aspects and client have been orderly called in their "changed" callback
+        m_changeStep.waitForStep(ASPECTS+1, 5000);
+        
+        // Check if modified "foo" original service property has been propagated
+        check = new HashMap();
+        check.put("foo", "barModified");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS); // we only see top-level aspect service properties
+        checkServiceProperties(check, clientImpl.getServiceProperties());
+        
+        // Now, change the top-level ranked aspect: it must propagate to all upper aspects, as well as to the client
+        System.out.println("-------------------------- Modifying top-level aspect service properties.");
+
+        m_changeStep = new Ensure();
+        for (int i = 1; i <= ASPECTS; i ++) {
+            m_changeStep.step(i); // only client has to be changed.
+        }
+        props = new Hashtable();
+        props.put("a" + ASPECTS, "v" + ASPECTS + "-Modified");
+        aspects[ASPECTS-1].setServiceProperties(props); // That triggers change callbacks for upper aspects (with rank >= 2)
+        m_changeStep.waitForStep(ASPECTS+1, 5000); // check if client have been changed.
+        
+        // Check if top level aspect service properties have been propagated up to the client.
+        check = new HashMap();
+        check.put("foo", "barModified");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS + "-Modified");
+        checkServiceProperties(check, clientImpl.getServiceProperties());
+
+        // Clear all components.
+        m_changeStep = null;
+        m.clear();
+    }    
+    
+    /**
+     * This test does the following:
+     * 
+     * - Create S service
+     * - Create some S Aspects without any callbacks (add/change/remove/swap)
+     * - Create a Client, depending on S (actually, on the top-level S aspect)
+     * - Client has a "change" callack in order to track S service properties modifications.
+     * - First, invoke Client.invoke(): all S aspects, and finally original S service must be invoked orderly.
+     * - Modify S original service properties, and check if the client has been called in its "change" callback.
+     */
+    public void testAspectsWithPropagationAndNoCallbacks() {
+        System.out.println("----------- Running testAspectsWithPropagation ...");
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        m_invokeStep = new Ensure(); 
+        
+        // Create our original "S" service.
+        Dictionary props = new Hashtable();
+        props.put("foo", "bar");
+        Component s = component(m).impl(new SImpl()).provides(S.class, props).build();
+        
+        // Create an aspect aware client, depending on "S" service.
+        Client clientImpl;
+        Component client = component(m).impl((clientImpl = new Client())).withSrv(S.class, srv->srv.cb("add", "change", "remove")).build();            
+
+        // Create some "S" aspects
+        Component[] aspects = new Component[ASPECTS];
+        for (int rank = 1; rank <= ASPECTS; rank ++) {
+            aspects[rank-1] = aspect(m, S.class).rank(rank).impl(new A("A" + rank, rank)).build();
+            props = new Hashtable();
+            props.put("a" + rank, "v" + rank);
+            aspects[rank-1].setServiceProperties(props);
+        }                                    
+              
+        // Register client
+        m.add(client);
+        
+        // Randomly register aspects and original service
+        boolean originalServiceAdded = false;
+        for (int i = 0; i < ASPECTS; i ++) {
+            int index = getRandomAspect();
+            m.add(aspects[index]);
+            if (! originalServiceAdded && _rnd.nextBoolean()) {
+                m.add(s);
+                originalServiceAdded = true;
+            }
+        }
+        if (! originalServiceAdded) {
+            m.add(s);
+        }
+              
+        // All set, check if client has inherited from top level aspect properties + original service properties
+        Map check = new HashMap();
+        check.put("foo", "bar");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS);
+        checkServiceProperties(check, clientImpl.getServiceProperties());
+
+        // Now invoke client, which orderly calls all aspects in the chain, and finally the original service "S".
+        System.out.println("-------------------------- Invoking client.");
+        clientImpl.invoke();
+        m_invokeStep.waitForStep(ASPECTS+1, 5000);
+        
+        // Now, change original service "S" properties: this will orderly trigger "change" callbacks on aspects, and on client. 
+        System.out.println("-------------------------- Modifying original service properties.");
+        m_changeStep = new Ensure();
+        for (int i = 1; i <= ASPECTS; i ++) {
+            m_changeStep.step(i); // skip aspects, which have no "change" callbacks.
+        }
+        props = new Hashtable();
+        props.put("foo", "barModified");
+        s.setServiceProperties(props);
+        
+        // Check if aspects and client have been orderly called in their "changed" callback
+        m_changeStep.waitForStep(ASPECTS+1, 5000);
+        
+        // Check if modified "foo" original service property has been propagated
+        check = new HashMap();
+        check.put("foo", "barModified");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS); // we only see top-level aspect service properties
+        checkServiceProperties(check, clientImpl.getServiceProperties());
+        
+        // Clear all components.
+        m_changeStep = null;
+        m.clear();
+    }    
+    
+    /**
+     * This test does the following:
+     * 
+     * - Create S service
+     * - Create some S Aspects
+     * - Create S2 Adapter, which adapts S to S2
+     * - Create Client2, which depends on S2. Client2 listens to S2 property change events.
+     * - Now, invoke Client2.invoke(): all S aspects, and finally original S service must be invoked orderly.
+     * - Modify S original service properties, and check if all aspects, S2 Adapter, and Client2 have been orderly called in their "change" callback.
+     */
+    public void testAdapterWithAspectsAndPropagation() {
+        System.out.println("----------- Running testAdapterWithAspectsAndPropagation ...");
+
+        DependencyManager m = getDM();
+        m_invokeStep = new Ensure(); 
+        
+        // Create our original "S" service.
+        Dictionary props = new Hashtable();
+        props.put("foo", "bar");
+        Component s = component(m).impl(new SImpl()).provides(S.class, props).build();
+        
+        // Create some "S" aspects
+        Component[] aspects = new Component[ASPECTS];
+        for (int rank = 1; rank <= ASPECTS; rank ++) {
+            aspects[rank-1] = aspect(m, S.class).rank(rank).impl(new A("A" + rank, rank)).cb("add", "change", "remove", "swap").build();
+            props = new Hashtable();
+            props.put("a" + rank, "v" + rank);
+            aspects[rank-1].setServiceProperties(props);
+        } 
+        
+        // Create S2 adapter (which adapts S1 to S2 interface)
+        Component adapter = adapter(m, S.class).cb("add", "change", "remove", "swap").provides(S2.class).impl(new S2Impl()).build();
+        
+        // Create Client2, which depends on "S2" service.
+        Client2 client2Impl;
+        Component client2 = component(m).impl((client2Impl = new Client2())).withSrv(S2.class, srv -> srv.cb("add", "change", null)).build();
+              
+        // Register client2
+        m.add(client2);
+        
+        // Register S2 adapter
+        m.add(adapter);
+        
+        // Randomly register aspects, original service
+        boolean originalServiceAdded = false;
+        for (int i = 0; i < ASPECTS; i ++) {
+            int index = getRandomAspect();
+            m.add(aspects[index]);
+            if (! originalServiceAdded && _rnd.nextBoolean()) {
+                m.add(s);
+                originalServiceAdded = true;
+            }
+        }
+        if (! originalServiceAdded) {
+            m.add(s);
+        }
+             
+        // Now invoke client2, which orderly calls all S1 aspects, then S1Impl, and finally S2 service
+        System.out.println("-------------------------- Invoking client2.");
+        client2Impl.invoke2();
+        m_invokeStep.waitForStep(ASPECTS+2, 5000);
+        
+        // Now, change original service "S" properties: this will orderly trigger "change" callbacks on aspects, S2Impl, and Client2.
+        System.out.println("-------------------------- Modifying original service properties.");
+        m_changeStep = new Ensure();
+        props = new Hashtable();
+        props.put("foo", "barModified");
+        s.setServiceProperties(props);
+        
+        // Check if aspects and Client2 have been orderly called in their "changed" callback
+        m_changeStep.waitForStep(ASPECTS+2, 5000);
+        
+        // Check if modified "foo" original service property has been propagated to Client2
+        Map check = new HashMap();
+        check.put("foo", "barModified");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS);
+        checkServiceProperties(check, client2Impl.getServiceProperties());
+        
+        // Clear all components.
+        m_changeStep = null;
+        m.clear();
+    }    
+    
+    /**
+     * This test does the following:
+     * 
+     * - Create S service
+     * - Create some S Aspects without any callbacks (add/change/remove)
+     * - Create S2 Adapter, which adapts S to S2 (but does not have any add/change/remove callbacks)
+     * - Create Client2, which depends on S2. Client2 listens to S2 property change events.
+     * - Now, invoke Client2.invoke(): all S aspects, and finally original S service must be invoked orderly.
+     * - Modify S original service properties, and check if all aspects, S2 Adapter, and Client2 have been orderly called in their "change" callback.
+     */
+    public void testAdapterWithAspectsAndPropagationNoCallbacks() {
+        System.out.println("----------- Running testAdapterWithAspectsAndPropagationNoCallbacks ...");
+
+        DependencyManager m = getDM();
+        m_invokeStep = new Ensure(); 
+        
+        // Create our original "S" service.
+        Dictionary props = new Hashtable();
+        props.put("foo", "bar");
+        Component s = component(m).impl(new SImpl()).provides(S.class, props).build();
+        
+        // Create some "S" aspects
+        Component[] aspects = new Component[ASPECTS];
+        for (int rank = 1; rank <= ASPECTS; rank ++) {
+            aspects[rank-1] = aspect(m, S.class).rank(rank).impl(new A("A" + rank, rank)).build();
+            props = new Hashtable();
+            props.put("a" + rank, "v" + rank);
+            aspects[rank-1].setServiceProperties(props);
+        } 
+        
+        // Create S2 adapter (which adapts S1 to S2 interface)
+        Component adapter = adapter(m, S.class).provides(S2.class).impl(new S2Impl()).build();                                
+        
+        // Create Client2, which depends on "S2" service.
+        Client2 client2Impl;
+        Component client2 = component(m).impl((client2Impl = new Client2())).withSrv(S2.class, srv->srv.cb("add", "change", null)).build();
+              
+        // Register client2
+        m.add(client2);
+        
+        // Register S2 adapter
+        m.add(adapter);
+        
+        // Randomly register aspects, original service
+        boolean originalServiceAdded = false;
+        for (int i = 0; i < ASPECTS; i ++) {
+            int index = getRandomAspect();
+            m.add(aspects[index]);
+            if (! originalServiceAdded && _rnd.nextBoolean()) {
+                m.add(s);
+                originalServiceAdded = true;
+            }
+        }
+        if (! originalServiceAdded) {
+            m.add(s);
+        }
+             
+        // Now invoke client2, which orderly calls all S1 aspects, then S1Impl, and finally S2 service
+        System.out.println("-------------------------- Invoking client2.");
+        client2Impl.invoke2();
+        m_invokeStep.waitForStep(ASPECTS+2, 5000);
+        
+        // Now, change original service "S" properties: this will orderly trigger "change" callbacks on aspects, S2Impl, and Client2.
+        System.out.println("-------------------------- Modifying original service properties.");
+        m_changeStep = new Ensure();
+        for (int i = 1; i <= ASPECTS+1; i ++) {
+            m_changeStep.step(i); // skip all aspects and the adapter
+        }
+        props = new Hashtable();
+        props.put("foo", "barModified");
+        s.setServiceProperties(props);
+        
+        // Check if Client2 has been called in its "changed" callback
+        m_changeStep.waitForStep(ASPECTS+2, 5000);
+        
+        // Check if modified "foo" original service property has been propagated to Client2
+        Map check = new HashMap();
+        check.put("foo", "barModified");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS);
+        checkServiceProperties(check, client2Impl.getServiceProperties());
+        
+        // Clear all components.
+        m_changeStep = null;
+        m.clear();
+    }    
+    
+   private void checkServiceProperties(Map<?, ?> check, Dictionary properties) {
+        for (Object key : check.keySet()) {
+            Object val = check.get(key);   
+            if (val == null) {
+                Assert.assertNull(properties.get(key));
+            } else {
+                Assert.assertEquals(val, properties.get(key));
+            }
+        }
+    }
+    
+    private int getRandomAspect() {
+        int index = 0;  
+        do {
+            index = _rnd.nextInt(ASPECTS);            
+        } while (_randoms.contains(new Integer(index)));
+        _randoms.add(new Integer(index));
+        return index;
+    }
+
+    // S Service
+    public static interface S {
+        public void invoke();
+    }
+    
+    // S ServiceImpl
+    static class SImpl implements S {
+        public SImpl() {
+        }
+        
+        public String toString() {
+            return "S";
+        }
+        
+        public void invoke() {
+             m_invokeStep.step(ASPECTS+1);
+        }
+    }
+    
+    // S Aspect
+    static class A implements S {
+        private final String m_name;
+        private volatile ServiceRegistration m_registration;
+        private volatile S m_next;
+        private final int m_rank;
+
+        public A(String name, int rank) {
+            m_name = name;
+            m_rank = rank;
+        }
+        
+        public String toString() {
+            return m_name;
+        }
+        
+        public void invoke() {
+            int rank = ServiceUtil.getRanking(m_registration.getReference());
+            m_invokeStep.step(ASPECTS - rank + 1);
+            m_next.invoke();
+        }
+               
+        public void add(ServiceReference ref, S s) {
+            System.out.println("+++ A" + m_rank + ".add:" + s + "/" + ServiceUtil.toString(ref));   
+            m_next = s;
+        }
+
+        public void swap(ServiceReference oldSRef, S oldS, ServiceReference newSRef, S newS) {
+            System.out.println("+++ A" + m_rank + ".swap: new=" + newS + ", props=" + ServiceUtil.toString(newSRef));
+            Assert.assertTrue(m_next == oldS);
+            m_next = newS;
+        }
+
+        public void change(ServiceReference props, S s) {   
+            System.out.println("+++ A" + m_rank + ".change: s=" + s + ", props=" + ServiceUtil.toString(props));
+            if (m_changeStep != null) {
+                int rank = ServiceUtil.getRanking(m_registration.getReference());
+                m_changeStep.step(rank);
+            }
+        }
+        
+        public void remove(ServiceReference props, S s) {
+            System.out.println("+++ A" + m_rank + ".remove: " + s + ", props=" + ServiceUtil.toString(props));
+        }
+    }
+    
+    // Aspect aware client, depending of "S" service aspects.
+    static class Client {
+        private volatile S m_s;
+        private volatile ServiceReference m_sRef;
+
+        public Client() {
+        }
+        
+        public Dictionary getServiceProperties() {
+            Dictionary props = new Hashtable();
+            for (String key : m_sRef.getPropertyKeys()) {
+                props.put(key, m_sRef.getProperty(key));
+            }
+            return props;
+        }
+
+        public void invoke() {
+            m_s.invoke();           
+        }
+
+        public String toString() {
+            return "Client";
+        }
+        
+        public void add(ServiceReference ref, S s) {
+            System.out.println("+++ Client.add: " + s + "/" + ServiceUtil.toString(ref));
+            m_s = s;
+            m_sRef = ref;
+        }
+              
+        public void swap(ServiceReference oldSRef, S oldS, ServiceReference newSRef, S newS) {
+            System.out.println("+++ Client.swap: m_s = " + m_s + ", old=" + oldS + ", oldProps=" + ServiceUtil.toString(oldSRef) + ", new=" + newS + ", props=" + ServiceUtil.toString(newSRef));
+            Assert.assertTrue(m_s == oldS);
+            m_s = newS;
+            m_sRef = newSRef;
+        }
+
+        public void change(ServiceReference properties, S s) {
+            System.out.println("+++ Client.change: s=" + s + ", props=" + ServiceUtil.toString(properties));
+            if (m_changeStep != null) {
+                m_changeStep.step(ASPECTS+1);
+            }
+        }
+        
+        public void remove(ServiceReference props, S s) {
+            System.out.println("+++ Client.remove: " + s + ", props=" + ServiceUtil.toString(props));
+        }
+    }
+    
+    // S2 Service
+    public static interface S2 {
+        public void invoke2();
+    }
+
+    // S2 impl, which adapts S1 interface to S2 interface
+    static class S2Impl implements S2 {
+        private volatile S m_s; // we shall see top-level aspect on S service
+        
+        public void add(ServiceReference ref, S s) {
+            System.out.println("+++ S2Impl.add: " + s + "/" + ServiceUtil.toString(ref));
+            m_s = s;
+        }
+              
+        public void swap(ServiceReference oldSRef, S oldS, ServiceReference newSRef, S newS) {
+            System.out.println("+++ S2Impl.swap: new=" + newS + ", props=" + ServiceUtil.toString(newSRef));
+            m_s = newS;
+        }
+
+        public void change(ServiceReference properties, S s) {
+            System.out.println("+++ S2Impl.change: s=" + s + ", props=" + ServiceUtil.toString(properties));
+            if (m_changeStep != null) {
+                m_changeStep.step(ASPECTS+1);
+            }
+        }
+        
+        public void remove(ServiceReference props, S s) {
+            System.out.println("+++ S2Impl.remove: " + s + ", props=" + ServiceUtil.toString(props));
+        }
+        
+        public void invoke2() {
+            m_s.invoke();
+            m_invokeStep.step(ASPECTS + 2); // All aspects, and S1Impl have been invoked
+        }
+
+        public String toString() {
+            return "S2";
+        }        
+    }
+    
+    // Client2 depending on S2.
+    static class Client2 {
+        private volatile S2 m_s2;
+        private volatile ServiceReference m_s2Ref;
+
+        public Dictionary getServiceProperties() {
+            Dictionary props = new Hashtable();
+            for (String key : m_s2Ref.getPropertyKeys()) {
+                props.put(key, m_s2Ref.getProperty(key));
+            }
+            return props;
+        }
+
+        public void invoke2() {
+            m_s2.invoke2();           
+        }
+
+        public String toString() {
+            return "Client2";
+        }  
+                
+        public void add(ServiceReference ref, S2 s2) {
+            System.out.println("+++ Client2.add: " + s2 + "/" + ServiceUtil.toString(ref));
+            m_s2 = s2;
+            m_s2Ref = ref;
+        }
+
+        public void change(ServiceReference props, S2 s2) {   
+            System.out.println("+++ Client2.change: s2=" + s2 + ", props=" + ServiceUtil.toString(props));
+            if (m_changeStep != null) {
+                m_changeStep.step(ASPECTS + 2); // S1Impl, all aspects, and S2 adapters have been changed before us.
+            }
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AutoConfigTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AutoConfigTest.java
new file mode 100644
index 0000000..3f9839c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AutoConfigTest.java
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.Constants;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class AutoConfigTest extends TestBase {
+    private final Ensure m_ensure = new Ensure();
+
+    public void testField() throws Exception {
+        final DependencyManager dm = getDM();
+        // Create a consumer, depending on some providers (autoconfig field).
+        ConsumeWithProviderField consumer = new ConsumeWithProviderField();
+        Component c = createConsumer(dm, consumer);
+        // Create two providers
+        Component p1 = createProvider(dm, 10, new Provider() {
+            public String toString() { return "provider1"; }
+            public void run() { m_ensure.step(); }
+        });
+        Component p2 = createProvider(dm, 20, new Provider() {
+            public String toString() { return "provider2"; }
+            public void run() { m_ensure.step(); }
+        });
+
+        // add the two providers
+        dm.add(p2);
+        dm.add(p1);
+        // add the consumer, which should have been injected with provider2 (highest rank)
+        dm.add(c);
+        m_ensure.waitForStep(1, 5000);
+        // remove the provider2, the consumer should now be injected with provider1
+        dm.remove(p2);
+        Assert.assertNotNull(consumer.getProvider());
+        Assert.assertEquals("provider1", consumer.getProvider().toString());
+        // remove the provider1, the consumer should have been stopped
+        dm.remove(p1);
+        m_ensure.waitForStep(2, 5000);
+        dm.clear();
+    }
+    
+    public void testIterableField() throws Exception {
+        final DependencyManager dm = getDM();
+        ConsumerWithIterableField consumer = new ConsumerWithIterableField();
+        Component c = createConsumer(dm, consumer);
+        Component p1 = createProvider(dm, 10, new Provider() {
+            public void run() { m_ensure.step(); }
+            public String toString() { return "provider1"; }
+        });
+        Component p2 = createProvider(dm, 20, new Provider() {
+            public void run() { m_ensure.step();}
+            public String toString() { return "provider2"; }
+        });
+
+        dm.add(p2);
+        dm.add(p1);
+        dm.add(c);
+        // the consumer should have been injected with all providers.
+        m_ensure.waitForStep(3, 5000);
+        
+        // check if all providers are there
+        Assert.assertNotNull(consumer.getProvider("provider1"));
+        Assert.assertNotNull(consumer.getProvider("provider2"));
+        
+        // remove provider1
+        dm.remove(p1);
+        
+        // check if provider1 has been removed and if provider2 is still there
+        Assert.assertNull(consumer.getProvider("provider1"));
+        Assert.assertNotNull(consumer.getProvider("provider2"));
+
+        // remove provider2, the consumer should be stopped
+        dm.remove(p2);
+        m_ensure.waitForStep(4, 5000);
+        dm.clear();
+    }   
+    
+    public void testMapField() throws Exception {
+        final DependencyManager dm = getDM();
+        ConsumerWithMapField consumer = new ConsumerWithMapField();
+        Component c = createConsumer(dm, consumer);
+        Component p1 = createProvider(dm, 10, new Provider() {
+            public void run() { m_ensure.step(); }
+            public String toString() { return "provider1"; }
+        });
+        Component p2 = createProvider(dm, 20, new Provider() {
+            public void run() { m_ensure.step();}
+            public String toString() { return "provider2"; }
+        });
+
+        dm.add(p2);
+        dm.add(p1);
+        dm.add(c);
+        // the consumer should have been injected with all providers.
+        m_ensure.waitForStep(3, 5000);
+        
+        // check if all providers are there
+        Assert.assertNotNull(consumer.getProvider("provider1"));
+        Assert.assertNotNull(consumer.getProvider("provider2"));
+        
+        // remove provider1
+        dm.remove(p1);
+        
+        // check if provider1 has been removed and if provider2 is still there
+        Assert.assertNull(consumer.getProvider("provider1"));
+        Assert.assertNotNull(consumer.getProvider("provider2"));
+
+        // remove provider2, the consumer should be stopped
+        dm.remove(p2);
+        m_ensure.waitForStep(4, 5000);
+        dm.clear();
+    }
+
+    private Component createProvider(DependencyManager dm, int rank, Provider provider) {
+        return component(dm).impl(provider).provides(Provider.class, Constants.SERVICE_RANKING, new Integer(rank)).build();
+    }
+
+    private Component createConsumer(DependencyManager dm, Object consumer) {
+        return component(dm).impl(consumer).withSrv(Provider.class).build();
+    }
+
+    public static interface Provider extends Runnable {      
+    }
+    
+    public class ConsumeWithProviderField {
+        volatile Provider m_provider;
+        
+        void start() {
+            Assert.assertNotNull(m_provider);
+            Assert.assertEquals("provider2", m_provider.toString());
+            m_ensure.step(1);
+        }
+        
+        public Provider getProvider() {
+            return m_provider;
+        }
+
+        void stop() {
+            m_ensure.step(2);
+        }
+    }
+    
+    public class ConsumerWithIterableField {
+        final Iterable<Provider> m_providers = new ConcurrentLinkedQueue<>();
+        final List m_notInjectMe = new ArrayList();
+        
+        void start() {
+            Assert.assertNotNull(m_providers);
+            int found = 0;
+            for (Provider provider : m_providers) {
+                provider.run();
+                found ++;
+            }
+            Assert.assertTrue(found == 2);
+            // The "m_notInjectMe" should not be injected with anything
+            Assert.assertEquals(m_notInjectMe.size(), 0);
+            m_ensure.step(3);
+        }
+        
+        public Provider getProvider(String name) {
+            System.out.println("getProvider(" + name + ") : proviers=" + m_providers);
+            for (Provider provider : m_providers) {
+                if (provider.toString().equals(name)) {
+                    return provider;
+                }
+            }
+            return null;
+        }
+        
+        void stop() {
+            m_ensure.step(4);
+        }
+    }    
+    
+    public class ConsumerWithMapField {
+        final Map<Provider, Dictionary> m_providers = new ConcurrentHashMap<>();
+        final Map m_notInjectMe = new HashMap<>();
+        
+        void start() {
+            Assert.assertNotNull(m_providers);
+            System.out.println("ConsumerMap.start: injected providers=" + m_providers);
+            Assert.assertTrue(m_providers.size() == 2);
+            Assert.assertEquals(0, m_notInjectMe.size());
+            for (Map.Entry<Provider, Dictionary> e : m_providers.entrySet()) {
+                Provider provider = e.getKey();
+                Dictionary props = e.getValue();
+                
+                provider.run();
+                if (provider.toString().equals("provider1")) {
+                    Assert.assertEquals(props.get(Constants.SERVICE_RANKING), 10);
+                } else if (provider.toString().equals("provider2")) {
+                    Assert.assertEquals(props.get(Constants.SERVICE_RANKING), 20);
+                } else {
+                    Assert.fail("Did not find any properties for provider " + provider);
+                }
+            }
+            
+            m_ensure.step(3);
+        }
+        
+        public Provider getProvider(String name) {
+            System.out.println("getProvider(" + name + ") : providers=" + m_providers);
+            for (Provider provider : m_providers.keySet()) {
+                if (provider.toString().equals(name)) {
+                    return provider;
+                }
+            }
+            return null;
+        }
+
+        Map<Provider, Dictionary> getProviders() {
+            return m_providers;
+        }
+        
+        void stop() {
+            m_ensure.step(4);
+        }
+    }    
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/BundleAdapterTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/BundleAdapterTest.java
new file mode 100644
index 0000000..f91c1ff
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/BundleAdapterTest.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.bundleAdapter;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.Bundle;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class BundleAdapterTest extends TestBase {    
+    public void testBundleAdapter() {
+        DependencyManager m = getDM();
+        // create a bundle adapter service (one is created for each bundle)
+        Component adapter = bundleAdapter(m)
+            .mask(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE)
+            .impl(BundleAdapter.class)
+            .provides(BundleAdapter.class)
+            .build();
+
+        // create a service provider and consumer
+        Consumer c = new Consumer();
+        Component consumer = m.createComponent().setImplementation(c)
+            .add(m.createServiceDependency().setService(BundleAdapter.class).setCallbacks("add", "remove"));
+        
+        // add the bundle adapter
+        m.add(adapter);
+        // add the service consumer
+        m.add(consumer);
+        // check if at least one bundle was found
+        c.check();
+        // remove the consumer again
+        m.remove(consumer);
+        // check if all bundles were removed correctly
+        c.doubleCheck();
+        // remove the bundle adapter
+        m.remove(adapter);
+    }
+    
+    public void testBundleAdapterWithCallbackInstance() {
+        DependencyManager m = getDM();
+        // create a bundle adapter service (one is created for each bundle)
+        BundleAdapterWithCallback baWithCb = new BundleAdapterWithCallback();
+        BundleAdapterCallbackInstance cbInstance = new BundleAdapterCallbackInstance(baWithCb);
+        
+        Component adapter = bundleAdapter(m)
+            .mask(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE)
+            .cbi(cbInstance, "add", "remove")
+            .impl(baWithCb)
+            .provides(BundleAdapter.class.getName())
+            .build();
+
+        // create a service provider and consumer
+        Consumer c = new Consumer();
+        Component consumer = component(m)
+            .impl(c)
+            .withSrv(BundleAdapter.class, s->s.cb("add", "remove"))
+            .build();
+        
+        // add the bundle adapter
+        m.add(adapter);
+        // add the service consumer
+        m.add(consumer);
+        // check if at least one bundle was found
+        c.check();
+        // remove the consumer again
+        m.remove(consumer);
+        // check if all bundles were removed correctly
+        c.doubleCheck();
+        // remove the bundle adapter
+        m.remove(adapter);
+    }
+        
+    public void testBundleAdapterWithCallbackInstanceRef() {
+        DependencyManager m = getDM();
+        // create a bundle adapter service (one is created for each bundle)
+        BundleAdapterWithCallback baWithCb = new BundleAdapterWithCallback();
+        BundleAdapterCallbackInstance cbInstance = new BundleAdapterCallbackInstance(baWithCb);
+        
+        Component adapter = bundleAdapter(m)
+            .mask(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE)
+            .cbi(cbInstance::add, cbInstance::remove)
+            .impl(baWithCb)
+            .provides(BundleAdapter.class.getName())
+            .build();
+
+        // create a service provider and consumer
+        Consumer c = new Consumer();
+        Component consumer = component(m)
+            .impl(c)
+            .withSrv(BundleAdapter.class, s->s.cb("add", "remove"))
+            .build();
+        
+        // add the bundle adapter
+        m.add(adapter);
+        // add the service consumer
+        m.add(consumer);
+        // check if at least one bundle was found
+        c.check();
+        // remove the consumer again
+        m.remove(consumer);
+        // check if all bundles were removed correctly
+        c.doubleCheck();
+        // remove the bundle adapter
+        m.remove(adapter);
+    }
+        
+    public static class BundleAdapter {
+        volatile Bundle m_bundle;
+        
+        Bundle getBundle() {
+            return m_bundle;
+        }
+    }
+    
+    public static class BundleAdapterWithCallback extends BundleAdapter {
+        void add(Bundle b) {
+        	m_bundle = b;        	
+        }
+        
+        void remove(Bundle b) {
+        	m_bundle = null;
+        }
+    }
+    
+    public static class BundleAdapterCallbackInstance {
+    	final BundleAdapterWithCallback m_ba;
+    	
+    	BundleAdapterCallbackInstance(BundleAdapterWithCallback ba) {
+    		m_ba = ba;
+    	}
+    	
+        void add(Component c, Bundle b) {
+        	m_ba.add(b);	
+        }
+        
+        void remove(Component c, Bundle b) {
+        	m_ba.remove(b);
+        }
+    }
+    
+    static class Consumer {
+        private volatile int m_count = 0;
+
+        public void add(BundleAdapter ba) {
+            Bundle b = ba.getBundle();
+            System.out.println("Consumer.add(" + b.getSymbolicName() + ")");
+            Assert.assertNotNull("bundle instance must not be null", b);
+            m_count++;
+        }
+        
+        public void check() {
+            Assert.assertTrue("we should have found at least one bundle", m_count > 0);
+        }
+        
+        public void remove(BundleAdapter ba) {
+            Bundle b = ba.getBundle();
+            System.out.println("Consumer.remove(" + b.getSymbolicName() + ")");
+            m_count--;
+        }
+        
+        public void doubleCheck() {
+            Assert.assertEquals("all bundles we found should have been removed again", 0, m_count);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/BundleAdapterWithCallbacksNotAutoConfiguredTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/BundleAdapterWithCallbacksNotAutoConfiguredTest.java
new file mode 100644
index 0000000..76b6eb8
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/BundleAdapterWithCallbacksNotAutoConfiguredTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.bundleAdapter;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.Bundle;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class BundleAdapterWithCallbacksNotAutoConfiguredTest extends TestBase {  
+    final Ensure m_e = new Ensure();
+    
+    public void testBundleAdapterWithCallbacksNotAutoConfigured() {
+        DependencyManager m = getDM();
+        // create a bundle adapter service (one is created for each bundle)
+        BundleAdapterWithCallback baWithCb = new BundleAdapterWithCallback();
+        String bsn = "org.apache.felix.dependencymanager";
+        String filter = "(Bundle-SymbolicName=" + bsn + ")";
+
+        Component adapter = bundleAdapter(m).mask(Bundle.ACTIVE).filter(filter).cb("add").impl(baWithCb).build();
+                    												 
+        // add the bundle adapter
+        m.add(adapter);
+        
+        // Check if adapter has not been auto configured (because it has callbacks defined).
+        m_e.waitForStep(1, 3000);
+        Assert.assertNull("bundle adapter must not be auto configured", baWithCb.getBundle());
+        
+        // remove the bundle adapters
+        m.remove(adapter);
+    }
+                
+    class BundleAdapterWithCallback {
+        volatile Bundle m_bundle; // must not be auto configured because we are using callbacks.
+        
+        Bundle getBundle() {
+            return m_bundle;
+        }
+        
+        void add(Bundle b) {
+            Assert.assertNotNull(b);
+            Assert.assertEquals("org.apache.felix.dependencymanager", b.getSymbolicName());
+            m_e.step(1);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/BundleDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/BundleDependencyTest.java
new file mode 100644
index 0000000..b9d1937
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/BundleDependencyTest.java
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.Bundle;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class BundleDependencyTest extends TestBase {
+    private final static String BSN = "org.apache.felix.metatype";
+    
+    public void testBundleDependencies() {
+        DependencyManager m = getDM();
+        // create a service provider and consumer
+        MyConsumer c = new MyConsumer();        
+        Component consumer = component(m, comp -> comp.impl(c).withBundle(bundle -> bundle.cb("add", "remove")));
+        
+        // check if at least one bundle was found
+        c.check();
+        // remove the consumer again
+        m.remove(consumer);
+        // check if all bundles were removed correctly
+        c.doubleCheck();
+        
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        String filter = "(Bundle-SymbolicName=" + BSN + ")";
+        Component consumerWithFilter = component(m, comp -> comp.impl(new FilteredConsumer(e))
+            .withBundle(bundle-> bundle.filter(filter).cb("add", "remove")));
+        e.step(2);
+        // remove the consumer again
+        m.remove(consumerWithFilter);
+        e.step(4);
+    }
+
+    public void testBundleDependenciesRef() {
+        DependencyManager m = getDM();
+        // create a service provider and consumer
+        MyConsumer c = new MyConsumer();        
+        Component consumer = component(m, comp -> comp.impl(c).withBundle(bundle -> bundle.cb(MyConsumer::add, MyConsumer::remove)));
+        
+        // check if at least one bundle was found
+        c.check();
+        // remove the consumer again
+        m.remove(consumer);
+        // check if all bundles were removed correctly
+        c.doubleCheck();
+        
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        String filter = "(Bundle-SymbolicName=" + BSN + ")";
+        Component consumerWithFilter = component(m, comp -> comp.impl(new FilteredConsumer(e))
+            .withBundle(bundle-> bundle.filter(filter).cb(FilteredConsumer::add, FilteredConsumer::remove)));
+        e.step(2);
+        // remove the consumer again
+        m.remove(consumerWithFilter);
+        e.step(4);
+    }
+    
+    public void testRequiredBundleDependency() {
+        DependencyManager m = getDM();
+        
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        Component consumerWithFilter = component(m, c -> c.impl(new FilteredConsumerRequired(e))
+            .withBundle(b -> b.filter("(Bundle-SymbolicName=" + BSN + ")").cb("add", "remove")));
+        e.waitForStep(1, 5000);
+        // remove the consumer again
+        m.remove(consumerWithFilter);
+        e.waitForStep(2, 5000);
+    }
+    
+    public void testRequiredBundleDependencyRef() {
+        DependencyManager m = getDM();
+        
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        FilteredConsumerRequired impl = new FilteredConsumerRequired(e);
+        Component consumerWithFilter = component(m, c -> c.impl(impl)
+            .withBundle(b -> b.filter("(Bundle-SymbolicName=" + BSN + ")").cbi(impl::add, impl::remove)));
+        e.waitForStep(1, 5000);
+        // remove the consumer again
+        m.remove(consumerWithFilter);
+        e.waitForStep(2, 5000);
+    }
+        
+    public void testRequiredBundleDependencyWithComponentArgInCallbackMethod() {
+        DependencyManager m = getDM();
+        
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // add a consumer with a filter
+        FilteredConsumerRequiredWithComponentArg impl = new FilteredConsumerRequiredWithComponentArg(e);
+        Component consumerWithFilter = component(m, c -> c.impl(impl)
+            .withBundle(b -> b.filter("(Bundle-SymbolicName=" + BSN + ")").cb("add", "remove")));
+        e.waitForStep(1, 5000);
+        // remove the consumer again
+        m.remove(consumerWithFilter);
+        e.waitForStep(2, 5000);
+    }
+    
+    public void testRequiredBundleDependencyWithComponentArgInCallbackMethodRef() {
+        DependencyManager m = getDM();
+        
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        FilteredConsumerRequiredWithComponentArg impl = new FilteredConsumerRequiredWithComponentArg(e);
+        Component consumerWithFilter = component(m).impl(impl)
+        		.withBundle(b -> b.filter("(Bundle-SymbolicName=" + BSN + ")").cbi(impl::add, impl::remove)).build();
+        // add a consumer with a filter
+        m.add(consumerWithFilter);
+        e.waitForStep(1, 5000);
+        // remove the consumer again
+        m.remove(consumerWithFilter);
+        e.waitForStep(2, 5000);
+    }
+    
+    static class MyConsumer {
+        private volatile int m_count = 0;
+
+        public void add(Bundle b) {
+            System.out.println("Consumer.add(" + b.getSymbolicName() + ")");
+            Assert.assertNotNull("bundle instance must not be null", b);
+            m_count++;
+        }
+        
+        public void check() {
+            Assert.assertTrue("we should have found at least one bundle", m_count > 0);
+        }
+        
+        public void remove(Bundle b) {
+            System.out.println("Consumer.remove(" + b.getSymbolicName() + ")");
+            m_count--;
+        }
+        
+        public void doubleCheck() {
+            Assert.assertEquals("all bundles we found should have been removed again", 0, m_count);
+        }
+    }
+    
+    static class FilteredConsumer {
+        private final Ensure m_ensure;
+
+        public FilteredConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void add(Bundle b) {
+            m_ensure.step(1);
+        }
+        
+        public void remove(Bundle b) {
+            m_ensure.step(3);
+        }
+    }
+    
+    static class FilteredConsumerRequired {
+        private final Ensure m_ensure;
+
+        public FilteredConsumerRequired(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void add(Bundle b) {
+            System.out.println("Bundle is " + b);
+//            Assert.assertNotNull(b);
+            if (b.getSymbolicName().equals(BSN)) {
+                m_ensure.step(1);
+            }
+        }
+        
+        public void remove(Bundle b) {
+            Assert.assertNotNull(b);
+            if (b.getSymbolicName().equals(BSN)) {
+                m_ensure.step(2);
+            }
+        }
+    }
+
+    static class FilteredConsumerRequiredWithComponentArg {
+        private final Ensure m_ensure;
+
+        public FilteredConsumerRequiredWithComponentArg(Ensure e) {
+            m_ensure = e;
+        }
+                
+        public void add(Component component, Bundle b) {
+        	Assert.assertNotNull(component);
+            if (b.getSymbolicName().equals(BSN)) {
+                m_ensure.step(1);
+            }
+        }
+        
+        public void remove(Component component, Bundle b) {
+        	Assert.assertNotNull(component);
+            Assert.assertNotNull(b);
+            if (b.getSymbolicName().equals(BSN)) {
+                m_ensure.step(2);
+            }
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ComponentTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ComponentTest.java
new file mode 100644
index 0000000..9b90cea
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ComponentTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.Dictionary;
+
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ComponentTest extends TestBase {
+    private final Ensure m_ensure = new Ensure();
+    
+    public void testSimple() throws Exception {
+        final DependencyManager dm = getDM();
+
+        // Create consumer (dependency is required by default using builder api).
+        component(dm, comp -> comp
+        		.factory(Consumer::new)
+        		.withSrv(Provider.class, srv -> srv.filter("(name=provider2)").cb(Consumer::add, Consumer::remove))
+        		.withSrv(Provider.class, srv -> srv.filter("(name=provider1)").autoConfig("m_autoConfiguredProvider")));
+                
+        // Create providers (auto added to dependency manager)
+        component(dm, comp -> comp
+        		.impl(new Provider() { public String toString() { return "provider1";}})
+        		.provides(Provider.class).properties("name", "provider1"));
+        		
+        component(dm, comp -> comp
+        		.impl(new Provider() { public String toString() { return "provider2";}})
+        		.provides(Provider.class).properties("name", "provider2"));
+        		
+        m_ensure.waitForStep(2, 5000);
+        dm.clear();
+        m_ensure.waitForStep(5, 5000);
+    }
+    
+    public static interface Provider {    	
+    }
+    
+    public class Consumer {
+        Provider m_provider;
+        Provider m_autoConfiguredProvider;
+                
+		void add(Provider provider, Dictionary<String, Object> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("provider2", props.get("name"));
+            m_provider = provider;
+            m_ensure.step(1);
+        }
+        
+        void start() {
+            Assert.assertNotNull(m_autoConfiguredProvider);
+            Assert.assertEquals("provider1", m_autoConfiguredProvider.toString());
+            m_ensure.step(2);
+        }
+        
+        void stop() {
+            m_ensure.step(3);
+        }
+        
+        void destroy() {
+            m_ensure.step(4);
+        }
+        
+        void remove(Provider provider, Dictionary<String, Object> props) {
+            Assert.assertEquals(m_provider, provider);
+            m_ensure.step(5);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/CompositionTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/CompositionTest.java
new file mode 100644
index 0000000..20fc990
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/CompositionTest.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class CompositionTest extends TestBase {
+    public void testComposition() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).composition("getComposition")
+            .withSrv(ServiceInterface.class, sb->sb.cb("add")).build();
+        m.add(sp);
+        m.add(sc);
+        // ensure we executed all steps inside the component instance
+        e.step(6);
+        m.clear();
+    }
+    
+    public void testCompositionRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        ServiceConsumer scimpl = new ServiceConsumer(e);
+        Component sc = component(m).impl(scimpl).composition(scimpl::getComposition)
+            .withSrv(ServiceInterface.class, sb->sb.cb("add")).build();
+        m.add(sp);
+        m.add(sc);
+        // ensure we executed all steps inside the component instance
+        e.step(6);
+        m.clear();
+    }
+    
+    static interface ServiceInterface {
+        public void invoke();
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke() {
+            m_ensure.step(4);
+        }
+    }
+
+    static class ServiceConsumer {
+        private final Ensure m_ensure;
+        private ServiceConsumerComposite m_composite;
+        @SuppressWarnings("unused")
+        private ServiceInterface m_service;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+            m_composite = new ServiceConsumerComposite(m_ensure);
+        }
+        
+        public Object[] getComposition() {
+            return new Object[] { this, m_composite };
+        }
+        
+        void add(ServiceInterface service) {
+            m_ensure.step(1);
+            m_service = service; // This method seems to not being called anymore 
+        }
+        
+        void start() {
+            m_composite.invoke();
+            m_ensure.step(5); 
+        }
+    }
+    
+    static class ServiceConsumerComposite {
+        ServiceInterface m_service;
+        private Ensure m_ensure;
+        
+        ServiceConsumerComposite(Ensure ensure)
+        {
+            m_ensure = ensure;
+        }
+
+        void add(ServiceInterface service) {
+
+            m_ensure.step(2);
+            m_service = service;
+        }
+
+        void invoke()
+        {
+            m_ensure.step(3);
+            m_service.invoke();
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/DynamicProxyAspectTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/DynamicProxyAspectTest.java
new file mode 100644
index 0000000..16a0f4b
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/DynamicProxyAspectTest.java
@@ -0,0 +1,254 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"rawtypes"})
+public class DynamicProxyAspectTest extends TestBase {
+    public void testImplementGenericAspectWithDynamicProxyAndFactory() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        DynamicProxyHandler.resetCounter();
+        
+        // create two service providers, each providing a different service interface
+        Component sp1 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sp2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class).build();
+        
+        // create a dynamic proxy based aspect and hook it up to both services
+        Component a1 = aspect(m, ServiceInterface.class)
+            .rank(10)
+            .autoConfig("m_service")
+            .factory(new Factory(e, ServiceInterface.class, "ServiceInterfaceProxy"), "create")
+            .build();
+        
+        Component a2 = aspect(m, ServiceInterface2.class)
+            .rank(10)
+            .autoConfig("m_service")
+            .factory(new Factory(e, ServiceInterface2.class, "ServiceInterfaceProxy2"), "create")
+            .build();
+
+        // create a client that invokes a method on boths services, validate that it goes
+        // through the proxy twice
+        Component sc = component(m)
+            .impl(new ServiceConsumer(e))
+            .withSrv(ServiceInterface.class, ServiceInterface2.class).build();
+        
+        // register both producers, validate that both services are started
+        m.add(sp1);
+        e.waitForStep(1, 2000);
+        m.add(sp2);
+        e.waitForStep(2, 2000);
+        
+        // add both aspects, and validate that both instances have been created
+        m.add(a1);
+        m.add(a2);
+        e.waitForStep(4, 4000);
+        
+        // add the client, which will automatically invoke both services
+        m.add(sc);
+        
+        // wait until both services have been invoked
+        e.waitForStep(6, 4000);
+        
+        // make sure the proxy has been called twice
+        Assert.assertEquals("Proxy should have been invoked this many times.", 2, DynamicProxyHandler.getCounter());
+        
+        m.remove(sc);
+        m.remove(a2);
+        m.remove(a1);
+        m.remove(sp2);
+        m.remove(sp1);
+        m.remove(a2);
+        m.remove(a1);
+    }
+
+    public void testImplementGenericAspectWithDynamicProxyAndFactoryRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        DynamicProxyHandler.resetCounter();
+
+        // create two service providers, each providing a different service interface
+        Component sp1 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sp2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class).build();
+        
+        // create a dynamic proxy based aspect and hook it up to both services
+        Component a1 = aspect(m, ServiceInterface.class).rank(10).autoConfig("m_service")
+            .factory(() -> new Factory(e, ServiceInterface.class, "ServiceInterfaceProxy"), Factory::create).build();
+        Component a2 = aspect(m, ServiceInterface2.class).rank(10).autoConfig("m_service")
+            .factory(() -> new Factory(e, ServiceInterface2.class, "ServiceInterfaceProxy2"), Factory::create).build();
+
+        // create a client that invokes a method on boths services, validate that it goes
+        // through the proxy twice
+        Component sc = component(m)
+            .impl(new ServiceConsumer(e))
+            .withSrv(ServiceInterface.class, ServiceInterface2.class).build();
+        
+        // register both producers, validate that both services are started
+        m.add(sp1);
+        e.waitForStep(1, 2000);
+        m.add(sp2);
+        e.waitForStep(2, 2000);
+        
+        // add both aspects, and validate that both instances have been created
+        m.add(a1);
+        m.add(a2);
+        e.waitForStep(4, 4000);
+        
+        // add the client, which will automatically invoke both services
+        m.add(sc);
+        
+        // wait until both services have been invoked
+        e.waitForStep(6, 4000);
+        
+        // make sure the proxy has been called twice
+        Assert.assertEquals("Proxy should have been invoked this many times.", 2, DynamicProxyHandler.getCounter());
+        
+        m.remove(sc);
+        m.remove(a2);
+        m.remove(a1);
+        m.remove(sp2);
+        m.remove(sp1);
+        m.remove(a2);
+        m.remove(a1);        
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(Runnable run);
+    }
+    
+    static interface ServiceInterface2 {
+        public void invoke(Runnable run);
+    }
+    
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void start() {
+            m_ensure.step(1);
+        }
+        public void invoke(Runnable run) {
+            run.run();
+        }
+    }
+    
+    static class ServiceProvider2 implements ServiceInterface2 {
+        private final Ensure m_ensure;
+        public ServiceProvider2(Ensure ensure) {
+            m_ensure = ensure;
+        }
+        public void start() {
+            m_ensure.step(2);
+        }
+        public void invoke(Runnable run) {
+            run.run();
+        }
+    }
+    
+    static class ServiceConsumer implements Runnable {
+        private volatile ServiceInterface m_service;
+        private volatile ServiceInterface2 m_service2;
+        private final Ensure m_ensure;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            Thread t = new Thread(this);
+            t.start();
+        }
+        
+        public void run() {
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 5));
+            m_service2.invoke(Ensure.createRunnableStep(m_ensure, 6));
+        }
+    }
+    
+    static class DynamicProxyHandler implements InvocationHandler {
+        public volatile Object m_service; // ISSUE, we cannot inject into "Object" at the moment
+        private final String m_label;
+        private static volatile int m_counter = 0;
+
+        public DynamicProxyHandler(String label) {
+            m_label = label;
+        }
+
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            System.out.println("IIIIIIINVOKE--------------------------" + method.getName());
+            if (m_service == null) {
+                Assert.fail("No service was injected into dynamic proxy handler " + m_label);
+            }
+            Method m = m_service.getClass().getMethod(method.getName(), method.getParameterTypes());
+            if (m == null) {
+                Assert.fail("No method " + method.getName() + " was found in instance " + m_service + " in dynamic proxy handler " + m_label);
+            }
+            if (method.getName().equals("invoke")) {
+                // only count methods called 'invoke' because those are actually the ones
+                // both interfaces implement (and the dynamic proxy might be invoked for
+                // other methods, such as toString() as well)
+                m_counter++;
+            }
+            return m.invoke(m_service, args);
+        }
+        
+        public static int getCounter() {
+            return m_counter;
+        }
+        
+        public static void resetCounter() {
+            m_counter = 0;
+        }
+    }
+    
+    static class Factory {
+        private final String m_label;
+        private Class m_class;
+        private final Ensure m_ensure;
+        
+        public Factory(Ensure ensure, Class clazz, String label) {
+            m_ensure = ensure;
+            m_class = clazz;
+            m_label = label;
+        }
+        
+        public Object create() {
+            m_ensure.step();
+            return Proxy.newProxyInstance(m_class.getClassLoader(), new Class[] { m_class }, new DynamicProxyHandler(m_label));
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/Ensure.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/Ensure.java
new file mode 100644
index 0000000..20040d2
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/Ensure.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import java.io.PrintStream;
+
+import org.junit.Assert;
+
+/**
+ * Helper class to make sure that steps in a test happen in the correct order. Instantiate
+ * this class and subsequently invoke <code>step(nr)</code> with steps starting at 1. You
+ * can also have threads wait until you arrive at a certain step.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Ensure {
+    private final boolean DEBUG;
+    private static long INSTANCE = 0;
+    private static final int RESOLUTION = 100;
+    private static PrintStream STREAM = System.out;
+    int step = 0;
+    private Throwable m_throwable;
+    
+    public Ensure() {
+        this(true);
+    }
+    
+    public Ensure(boolean debug) {
+        DEBUG = debug;
+        if (DEBUG) {
+            INSTANCE++;
+        }
+    }
+
+    public void setStream(PrintStream output) {
+        STREAM = output;
+    }
+    
+    /**
+     * Mark this point as step <code>nr</code>.
+     * 
+     * @param nr the step we are in
+     */
+    public synchronized void step(int nr) {
+        step++;
+        Assert.assertEquals(nr, step);
+        if (DEBUG) {
+            String info = getLineInfo(3);
+            STREAM.println("[Ensure " + INSTANCE + "] step " + step + " [" + currentThread() + "] " + info);
+        }
+        notifyAll();
+    }
+
+    private String getLineInfo(int depth) {
+        StackTraceElement[] trace = Thread.currentThread().getStackTrace();
+        String info = trace[depth].getClassName() + "." + trace[depth].getMethodName() + ":" + trace[depth].getLineNumber();
+        return info;
+    }
+    
+    /**
+     * Mark this point as the next step.
+     */
+    public synchronized void step() {
+        step++;
+        if (DEBUG) {
+            String info = getLineInfo(3);
+            STREAM.println("[Ensure " + INSTANCE + "] next step " + step + " [" + currentThread() + "] " + info);
+        }
+        notifyAll();
+    }
+
+    /**
+     * Wait until we arrive at least at step <code>nr</code> in the process, or fail if that
+     * takes more than <code>timeout</code> milliseconds. If you invoke wait on a thread,
+     * you are effectively assuming some other thread will invoke the <code>step(nr)</code>
+     * method.
+     * 
+     * @param nr the step to wait for
+     * @param timeout the number of milliseconds to wait
+     */
+    public synchronized void waitForStep(int nr, int timeout) {
+        final int initialTimeout = timeout;
+        if (DEBUG) {
+            String info = getLineInfo(3);
+            STREAM.println("[Ensure " + INSTANCE + "] waiting for step " + nr + " [" + currentThread() + "] " + info);
+        }
+        while (step < nr && timeout > 0) {
+            try {
+                wait(RESOLUTION);
+                timeout -= RESOLUTION;
+            }
+            catch (InterruptedException e) {}
+        }
+        if (step < nr) {
+            throw new IllegalStateException("Timed out waiting for " + initialTimeout + " ms for step " + nr + ", we are still at step " + step);
+        }
+        if (DEBUG) {
+            String info = getLineInfo(3);
+            STREAM.println("[Ensure " + INSTANCE + "] arrived at step " + nr + " [" + currentThread() + "] " + info);
+        }
+    }
+    
+    private String currentThread() {
+        Thread thread = Thread.currentThread();
+        return thread.getId() + " " + thread.getName();
+    }
+    
+    public static Runnable createRunnableStep(final Ensure ensure, final int nr) {
+        return new Runnable() { public void run() { ensure.step(nr); }};
+    }
+    
+    public synchronized void steps(Steps steps) {
+        steps.next(this);
+    }
+    
+    /** 
+     * Helper class for naming a list of step numbers. If used with the steps(Steps) method
+     * you can define at which steps in time this point should be passed. That means you can
+     * check methods that will get invoked multiple times during a test.
+     */
+    public static class Steps {
+        private final int[] m_steps;
+        private int m_stepIndex;
+
+        /** 
+         * Create a list of steps and initialize the step counter to zero.
+         */
+        public Steps(int... steps) {
+            m_steps = steps;
+            m_stepIndex = 0;
+        }
+
+        /**
+         * Ensure we're at the right step. Will throw an index out of bounds exception if we enter this step more often than defined.
+         */
+        public void next(Ensure ensure) {
+            ensure.step(m_steps[m_stepIndex++]);
+        }
+    }
+
+    /**
+     * Saves a thrown exception that occurred in a different thread. You can only save one exception
+     * at a time this way.
+     */
+    public synchronized void throwable(Throwable throwable) {
+        m_throwable = throwable;
+    }
+
+    /**
+     * Throws a <code>Throwable</code> if one occurred in a different thread and that thread saved it
+     * using the <code>throwable()</code> method.
+     */
+    public synchronized void ensure() throws Throwable {
+        if (m_throwable != null) {
+            throw m_throwable;
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryConfigurationAdapterTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryConfigurationAdapterTest.java
new file mode 100644
index 0000000..e01ac73
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryConfigurationAdapterTest.java
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.factoryPidAdapter;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class FactoryConfigurationAdapterTest extends TestBase
+{
+    private static Ensure m_ensure;
+    
+    public void testFactoryConfigurationAdapter() {
+    	testFactoryConfigurationAdapter(Adapter.class, "updated");
+    }
+    
+    public void testFactoryConfigurationAdapterWithUpdatedCallbackThatTakesComponentAsParameter() {
+    	testFactoryConfigurationAdapter(AdapterWithUpdateMethodThatTakesComponentAsParameter.class, "updatedWithComponent");
+    }
+    
+    public void testFactoryConfigurationAdapter(Class<?> adapterImplClass, String adapterUpdate) {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        m_ensure = new Ensure();
+        
+        // Create a Configuration instance, which will create/update/remove a configuration for factoryPid "MyFactoryPid"
+        ConfigurationCreator configurator = new ConfigurationCreator("MyFactoryPid", "key", "value1");
+        Component s1 = component(m).impl(configurator).withSrv(ConfigurationAdmin.class).build();
+           
+        // Create an Adapter that will be instantiated, once the configuration is created.
+        // This Adapter provides an AdapterService, and depends on an AdapterExtraDependency service.
+        Component s2 = factoryPidAdapter(m)
+            .factoryPid("MyFactoryPid").impl(adapterImplClass).cb(adapterUpdate).propagate().provides(AdapterService.class, "foo", "bar")            
+            .withSrv(AdapterExtraDependency.class)
+            .build();
+                    
+        // Create extra adapter service dependency upon which our adapter depends on.
+        Component s3 = component(m)
+            .impl(new AdapterExtraDependency()).provides(AdapterExtraDependency.class).build();
+        
+        // Create an AdapterService Consumer
+        Component s4 = component(m)
+            .impl(AdapterServiceConsumer.class).withSrv(AdapterService.class, srv -> srv.cb("bind", "change", "remove")).build();
+        
+        // Start services
+        m.add(s1);
+        m.add(s2);
+        m.add(s3);
+        m.add(s4);
+        
+        // Wait for step 8: the AdapterService consumer has been injected with the AdapterService, and has called the doService method.
+        m_ensure.waitForStep(8, 10000);
+        
+        // Modify configuration.
+        configurator.update("key", "value2");
+        
+        // Wait for step 13: the AdapterService has been updated, and the AdapterService consumer has seen the change
+        m_ensure.waitForStep(13, 10000);
+        
+        // Remove the configuration
+        m.remove(s1); // The stop method will remove the configuration
+        m_ensure.waitForStep(16, 10000);
+        m.clear();
+    }
+
+    public static class ConfigurationCreator {
+        private volatile ConfigurationAdmin m_ca;
+        private String m_key;
+        private String m_value;
+        private org.osgi.service.cm.Configuration m_conf;
+        private String m_factoryPid;
+        
+        public ConfigurationCreator(String factoryPid, String key, String value) {
+            m_factoryPid = factoryPid;
+            m_key = key;
+            m_value = value;
+        }
+
+        public void start() {
+            try {
+                m_ensure.step(1);
+                m_conf = m_ca.createFactoryConfiguration(m_factoryPid, null);
+                Hashtable props = new Hashtable();
+                props.put(m_key, m_value);
+                m_conf.update(props);
+            }
+            catch (IOException e) {
+                Assert.fail("Could not create configuration: " + e.getMessage());
+            }
+        }
+        
+        public void update(String key, String val) {
+            Hashtable props = new Hashtable();
+            props.put(key, val);
+            try {
+                m_conf.update(props);
+            }
+            catch (IOException e) {
+                Assert.fail("Could not update configuration: " + e.getMessage());
+            }
+        }
+        
+        public void stop() {
+            try
+            {
+                m_conf.delete();
+            }
+            catch (IOException e)
+            {
+                Assert.fail("Could not remove configuration: " + e.toString());
+            }
+        }
+    }
+    
+    public interface AdapterService {
+        public void doService();
+    }
+    
+    public static class AdapterExtraDependency {
+    }
+
+    public static class Adapter implements AdapterService {
+        volatile AdapterExtraDependency m_extraDependency; // extra dependency.
+        private int updateCount;
+        
+        void updated(Dictionary settings) {
+            updateCount ++;
+            if (updateCount == 1) {
+                m_ensure.step(2);
+                Assert.assertEquals(true, "value1".equals(settings.get("key")));
+                m_ensure.step(3);
+            } else if (updateCount == 2) {
+                m_ensure.step(9);
+                Assert.assertEquals(true, "value2".equals(settings.get("key")));
+                m_ensure.step(10);
+            } else {
+                Assert.fail("wrong call to updated method: count=" + updateCount);
+            }
+        }
+
+        public void doService() {   
+            m_ensure.step(8);
+        }
+        
+        public void start() {
+            m_ensure.step(4);
+            Assert.assertNotNull(m_extraDependency);
+            m_ensure.step(5);
+        }
+        
+        public void stop() {
+            m_ensure.step(16);
+        }
+    }
+    
+    public static class AdapterWithUpdateMethodThatTakesComponentAsParameter extends Adapter {
+        void updatedWithComponent(Component component, Dictionary settings) {
+        	Assert.assertNotNull(component);
+        	Assert.assertEquals(this, component.getInstance());
+        	super.updated(settings);
+        }
+    }
+
+    public static class AdapterServiceConsumer {
+        private AdapterService m_adapterService;
+        private Map m_adapterServiceProperties;
+        
+        void bind(Map serviceProperties, AdapterService adapterService) {
+            m_ensure.step(6);
+            m_adapterService = adapterService;
+            m_adapterServiceProperties = serviceProperties;
+        }
+        
+        void change(Map serviceProperties, AdapterService adapterService) {
+            m_ensure.step(11);
+            Assert.assertEquals(true, "value2".equals(m_adapterServiceProperties.get("key")));
+            m_ensure.step(12);
+            Assert.assertEquals(true, "bar".equals(m_adapterServiceProperties.get("foo")));
+            m_ensure.step(13);
+        }
+        
+        public void start() {
+            m_ensure.step(7);
+            Assert.assertNotNull(m_adapterService);
+            Assert.assertEquals(true, "value1".equals(m_adapterServiceProperties.get("key")));
+            Assert.assertEquals(true, "bar".equals(m_adapterServiceProperties.get("foo")));
+            m_adapterService.doService();
+        }
+        
+        public void stop() {
+            m_ensure.step(14);
+        }
+        
+        void remove(AdapterService adapterService) {
+            m_ensure.step(15);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java
new file mode 100644
index 0000000..f1ac3a9
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+
+/**
+ * Use case: one component is instantiated using another factory object, and the 
+ * factory object needs the configuration before the factory.create method is called.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class FactoryInjectedWithConfigurationBeforeTheCreateMethod extends TestBase {
+    Ensure m_e;
+    
+    public void testServiceInjection() {
+        DependencyManager m = getDM();
+        m_e = new Ensure();
+        
+        // Create the component that creates a configuration.
+        Component configurator = component(m).impl(new Configurator("foobar")).withSrv(ConfigurationAdmin.class).build();
+        
+        // Create the object that has to be injected with the configuration before its create method is called.
+        MyFactory factory = new MyFactory();
+        
+        // Create the Component for the MyComponent class that is created using the factory above.
+        Component myComponent = component(m).factory(factory, "create").withCnf(b->b.pid("foobar").cbi(factory, "updated")).build();
+        
+        // provide the configuration
+        m.add(configurator);
+        
+        m.add(myComponent);
+        m_e.waitForStep(4, 10000);
+        m.remove(myComponent);
+        m.remove(configurator);
+    }
+    
+    public void testServiceInjectionRef() {
+        DependencyManager m = getDM();
+        m_e = new Ensure();
+        
+        // Create the component that creates a configuration.
+        Component configurator = component(m).impl(new Configurator("foobar")).withSrv(ConfigurationAdmin.class).build();
+        
+        // Create the object that has to be injected with the configuration before its create method is called.
+        MyFactory factory = new MyFactory();
+        
+        // Create the Component for the MyComponent class that is created using the factory above.
+        Component myComponent = component(m).factory(factory, "create").withCnf(b->b.pid("foobar").cbi(factory::updated)).build();
+        
+        // provide the configuration
+        m.add(configurator);
+        
+        m.add(myComponent);
+        m_e.waitForStep(4, 10000);
+        m.remove(myComponent);
+        m.remove(configurator);
+    }
+
+    class Configurator {
+        private volatile ConfigurationAdmin m_ca;
+        Configuration m_conf;
+        final String m_pid;
+        
+        public Configurator(String pid) {
+            m_pid = pid;
+        }
+
+        public void init() {
+            try {
+                Assert.assertNotNull(m_ca);
+                m_e.step(1);
+                m_conf = m_ca.getConfiguration(m_pid, null);
+                Hashtable<String, Object> props = new Hashtable<>();
+                props.put("testkey", "testvalue");
+                m_conf.update(props);
+            }
+            catch (IOException e) {
+                Assert.fail("Could not create configuration: " + e.getMessage());
+            }
+        }
+        
+        public void destroy() throws IOException {
+            m_conf.delete();  
+        }
+    }
+
+    public class MyFactory {
+        public void updated(Dictionary<String, Object> conf) {
+            Assert.assertNotNull("configuration is null", conf);
+            m_e.step(2);
+        }
+        
+        public MyComponent create() {
+            m_e.step(3);
+            return new MyComponent();
+        }
+    }
+    
+    public class MyComponent {
+        void start() {
+            m_e.step(4);
+        }        
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/InstanceBoundDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/InstanceBoundDependencyTest.java
new file mode 100644
index 0000000..8844a0c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/InstanceBoundDependencyTest.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * This test does some injection tests on components being in INSTANTIATED_AND_WAITING_FOR_REQUIRED state.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class InstanceBoundDependencyTest extends TestBase {
+    Ensure m_e;
+    
+    public void testServiceInjection() {
+        DependencyManager m = getDM();
+        m_e = new Ensure();
+        
+        // Create a "C" component: it depends on some S1 services, and on some S2 instance-bound services (declared from C.init() method)        
+        C cimpl = new C();
+        Component c = component(m).impl(cimpl)
+            .withSrv(S1.class, sb->sb.cb("addS1", "changeS1", "removeS1").autoConfig(true)).build();
+        m.add(c);
+        
+        // Add S1 (s1_1): C.add(S1 s1) is called, then init() is called where a dependency is declared on S2
+        Hashtable s1_1_props = new Hashtable();
+        s1_1_props.put("name", "s1_1");
+        s1_1_props.put(Constants.SERVICE_RANKING, new Integer(10));
+        S1Impl s1_1_impl = new S1Impl();
+        Component s1_1 = component(m).impl(s1_1_impl).provides(S1.class.getName(), s1_1_props).build();
+        m.add(s1_1);
+        m_e.waitForStep(1, 5000); // wait until C.init called
+        ServiceReference ref = cimpl.getS1("s1_1");
+        Assert.assertNotNull(ref);
+        Assert.assertNotNull(cimpl.getS1());
+        Assert.assertEquals(s1_1_impl, cimpl.getS1());
+        
+        // At this point, MyComponent is in INSTANTIATED_AND_WAITING_FOR_REQUIRED state. 
+        // add now add another higher ranked S1 (s1_2) instance. C.add(s1_2) method should be called (the S1 dependency 
+        // is not instance bound), and m_s1 autoconfig field should be updated.
+        Hashtable s1_2_props = new Hashtable();
+        s1_2_props.put(Constants.SERVICE_RANKING, new Integer(20));
+        s1_2_props.put("name", "s1_2");
+        S1Impl s1_2_impl = new S1Impl();
+        Component s1_2 = component(m).impl(s1_2_impl).provides(S1.class.getName(), s1_2_props).build();
+        m.add(s1_2);
+        ref = cimpl.getS1("s1_2");
+        Assert.assertNotNull(ref);
+        Assert.assertNotNull(cimpl.getS1()); 
+        Assert.assertEquals(s1_2_impl, cimpl.getS1()); // must return s1_2 with ranking = 20
+
+        // Now, change the s1_1 service properties: C.changed(s1_1) should be called, and C.m_s1AutoConfig should be updated
+        s1_1_props.put(Constants.SERVICE_RANKING, new Integer(30));
+        s1_1.setServiceProperties(s1_1_props);
+        ref = cimpl.getS1("s1_1");
+        Assert.assertNotNull(ref);
+        Assert.assertEquals(new Integer(30), ref.getProperty(Constants.SERVICE_RANKING));
+        Assert.assertNotNull(cimpl.getS1());
+        Assert.assertEquals(s1_1_impl, cimpl.getS1());
+        
+        // Now, remove the s1_1: C.remove(s1_1) should be called, and C.m_s1AutoConfig should be updated
+        m.remove(s1_1);
+        ref = cimpl.getS1("s1_1");
+        Assert.assertNull(cimpl.getS1("s1_1"));
+        Assert.assertNotNull(cimpl.getS1());
+        Assert.assertEquals(s1_2_impl, cimpl.getS1());
+        m.clear();
+    }
+    
+    // C component depends on some S1 required services
+    public interface S1 {
+    }
+    
+    public class S1Impl implements S1 {
+    }
+    
+    public interface S2 {        
+    }
+    
+    public class S2Impl implements S2 {        
+    }
+    
+    // Our "C" component: it depends on S1 (required) and S2 (required/instance bound)
+    class C {        
+        final Map<String, ServiceReference> m_s1Map = new HashMap();
+        final Map<String, ServiceReference> m_s2Map = new HashMap();
+        volatile S1 m_s1; // auto configured
+        
+        S1 getS1() {
+            return m_s1;
+        }
+
+        void addS1(ServiceReference s1) {
+            m_s1Map.put((String) s1.getProperty("name"), s1);
+        }
+        
+        void changeS1(ServiceReference s1) {
+            m_s1Map.put((String) s1.getProperty("name"), s1);
+        }
+        
+        void removeS1(ServiceReference s1) {
+            m_s1Map.remove((String) s1.getProperty("name"));
+        }
+        
+        void addS2(ServiceReference s2) {
+            m_s2Map.put((String) s2.getProperty("name"), s2);
+        }
+        
+        void changeS2(ServiceReference s2) {
+            m_s2Map.put((String) s2.getProperty("name"), s2);
+        }
+        
+        void removeS2(ServiceReference s2) {
+            m_s2Map.remove((String) s2.getProperty("name"));
+        }
+        
+        ServiceReference getS1(String name) {
+            return m_s1Map.get(name);
+        }
+        
+        ServiceReference getS2(String name) {
+            return m_s2Map.get(name);
+        }
+        
+        void init(Component c) {
+            component(c, comp->comp.withSrv(S2.class, srv -> srv.cb(C::addS2, C::changeS2, C::removeS2)));
+            m_e.step(1);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ModifiedBundleDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ModifiedBundleDependencyTest.java
new file mode 100644
index 0000000..ade9bff
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ModifiedBundleDependencyTest.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+
+/**
+ * Test for FELIX-4334 issue.
+ * 
+ * Two components: A, B
+ * 
+ * - A provided.
+ * - B has a bundle dependency on the dependency manager shell bundle, which is currently stopped.
+ * - B has an instance bound dependency on A.
+ * - Now unregister A.
+ * - As a result of that, B becomes unavailable and is unbound from A. But B is not destroyed, because A dependency 
+ *   is "instance bound". So B is still bound to the bundle dependency.
+ * - Now, someone starts the dependency manager shell bundle: B then shall be called in its "changed" callback.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ModifiedBundleDependencyTest extends TestBase {
+    public static interface A {
+    }
+    
+    static class AImpl implements A {
+    }
+        
+    public static interface B {
+    }
+    
+    static class BImpl implements B {
+        final Ensure m_e;
+        
+        BImpl(Ensure e) {
+            m_e = e;
+        }
+        
+        public void add(Bundle dmTest) {
+            m_e.step(1);
+        }
+
+        void init(Component c) {
+            m_e.step(2);
+            component(c, comp -> comp.withSrv(A.class, srv -> srv.cb("add", "remove")));
+        }
+        
+        public void add(A a) {
+            m_e.step(3);
+        }
+        
+        public void start() {
+            m_e.step(4);            
+        }
+        
+        public void stop() {
+            m_e.step(5);
+        }
+
+        public void remove(A a) {
+            m_e.step(6);
+        }
+
+        public void change(Bundle dmTest) { // called two times: one for STARTING, one for STARTED
+            m_e.step(); 
+        }
+        
+        public void destroy() {
+            m_e.step(9);
+        }
+
+        public void remove(Bundle dmTest) {   
+            m_e.step(10);
+        }                    
+    }
+    
+    public void testAdapterWithChangedInstanceBoundDependencyAndCallbacks() {
+        DependencyManager m = getDM();
+        Ensure e = new Ensure();
+
+        Component a = component(m).impl(new AImpl()).provides(A.class).build();
+        
+        String filter = "(Bundle-SymbolicName=org.apache.felix.metatype)";
+        int mask = Bundle.INSTALLED|Bundle.ACTIVE|Bundle.RESOLVED|Bundle.STARTING;
+        Component b = component(m)
+            .provides(B.class).impl(new BImpl(e)).withBundle(bd -> bd.filter(filter).mask(mask).cb("add", "change", "remove")).build();     	
+        						                    
+        Bundle dmtest = getBundle("org.apache.felix.metatype");
+        try {
+            dmtest.stop();
+        } catch (BundleException e1) {
+            Assert.fail("could not find metatype bundle");
+        }
+        
+        m.add(a);
+        m.add(b);
+        
+        e.waitForStep(4, 5000);        
+        m.remove(a); // B will loose A and will enter into "waiting for required (instantiated)" state.
+        System.out.println("Starting metatype bundle ...");        
+        try {
+            dmtest.start();
+        } catch (BundleException e1) {
+            Assert.fail("could not start metatype bundle");
+        }
+        e.waitForStep(7, 5000);     
+        m.remove(b);        
+        e.waitForStep(10, 5000);                
+    }
+
+    public void testAdapterWithChangedInstanceBoundDependencyRef() {
+        DependencyManager m = getDM();
+        Ensure e = new Ensure();
+
+        Component a = 
+        	component(m, comp -> comp.impl(new AImpl()).provides(A.class).autoAdd(false));
+        
+        BImpl impl = new BImpl(e);
+        String filter = "(Bundle-SymbolicName=org.apache.felix.metatype)";
+        int mask = Bundle.INSTALLED|Bundle.ACTIVE|Bundle.RESOLVED|Bundle.STARTING;
+        Component b = component(m).provides(B.class).impl(impl)
+            .withBundle(bd -> bd.filter(filter).mask(mask).cbi(impl::add, impl::change, impl::remove)).build();        	
+        
+        Bundle dmtest = getBundle("org.apache.felix.metatype");
+        try {
+            dmtest.stop();
+        } catch (BundleException e1) {
+            Assert.fail("could not find metatype bundle");
+        }
+        
+        m.add(a);
+        m.add(b);
+        
+        e.waitForStep(4, 5000);        
+        m.remove(a); // B will loose A and will enter into "waiting for required (instantiated)" state.
+        System.out.println("Starting metatype bundle ...");        
+        try {
+            dmtest.start();
+        } catch (BundleException e1) {
+            Assert.fail("could not start metatype bundle");
+        }
+        e.waitForStep(7, 5000);     
+        m.remove(b);        
+        e.waitForStep(10, 5000);                
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependenciesTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependenciesTest.java
new file mode 100644
index 0000000..b48d5ee
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependenciesTest.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class MultipleExtraDependenciesTest extends TestBase {
+    /**
+     * Check that list of extra dependencies (defined from init method) are handled properly.
+     * The extra dependencies are added using a List object (Component.add(List)).
+     * A component c1 will define two extra dependencies over *available* c4/c5 services.
+     */
+     public void testWithTwoAvailableExtraDependency() {   
+         DependencyManager m = getDM();
+         // Helper class that ensures certain steps get executed in sequence
+         Ensure e = new Ensure();
+         Component c1 = component(m).provides(Service1.class).impl(new MyComponent1(e)).withSrv(Service2.class, srv->srv.autoConfig("m_service2")).build();
+         Component c2 = component(m).impl(new MyComponent2(e)).withSrv(Service1.class, srv->srv.required(false).autoConfig(false).cb("added")).build();
+         Component c3 = component(m).provides(Service2.class).impl(Service2Impl.class).build();
+         Component c4 = component(m).impl(Service3Impl1.class).provides(Service3.class, type -> "xx").build();
+         Component c5 = component(m).impl(Service3Impl2.class).provides(Service3.class, type -> "yy").build();
+
+         System.out.println("\n+++ Adding c2 / MyComponent2");
+         m.add(c2);
+         System.out.println("\n+++ Adding c3 / Service2");
+         m.add(c3);
+         System.out.println("\n+++ Adding c4 / Service3(xx)");
+         m.add(c4);
+         System.out.println("\n+++ Adding c5 / Service3(yy)");
+         m.add(c5);
+         System.out.println("\n+++ Adding c1 / MyComponent1");
+         // c1 have declared two extra dependency on Service3 (xx/yy).
+         // both extra dependencies are available, so the c1 component should be started immediately.
+         m.add(c1);
+         e.waitForStep(3, 3000);
+         m.clear();
+     }
+
+    /**
+     * Check that list of extra dependencies (defined from init method) are handled properly.
+     * The extra dependencies are added using a List object (Component.add(List)).
+     * A component c1 will define two extra dependencies over c4/c5. At the point c1.init()
+     * is adding the two extra dependencies from its init method, c4 is available, but not c5.
+     * So, c1 is not yet activated.
+     * Then c5 is added, and it triggers the c1 activation ...
+     */
+    public void testWithOneAvailableExtraDependency() {  
+        DependencyManager m = getDM();
+        // Helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        Component c1 = component(m).provides(Service1.class).impl(new MyComponent1(e)).withSrv(Service2.class, srv->srv.autoConfig("m_service2")).build();
+        Component c2 = component(m).impl(new MyComponent2(e)).withSrv(Service1.class, srv->srv.required(false).autoConfig(false).cb("added")).build();
+        Component c3 = component(m).provides(Service2.class).impl(Service2Impl.class).build();
+        Component c4 = component(m).impl(Service3Impl1.class).provides(Service3.class, type -> "xx").build();
+        Component c5 = component(m).impl(Service3Impl2.class).provides(Service3.class, type -> "yy").build();
+
+        System.out.println("\n+++ Adding c2 / MyComponent2");
+        m.add(c2);
+        System.out.println("\n+++ Adding c3 / Service2");
+        m.add(c3);
+        System.out.println("\n+++ Adding c4 / Service3(xx)");
+        m.add(c4);
+        System.out.println("\n+++ Adding c1 / MyComponent1");
+        m.add(c1);
+
+        // c1 have declared two extra dependency on Service3 (xx/yy).
+        // So, because we have not yet added c5 (yy), c1 should not be started currently.
+        // But, now, we'll add c5 (Service3/yy) and c1 should then be started ...
+        System.out.println("\n+++ Adding c5 / Service3(yy)");
+        m.add(c5);
+        e.waitForStep(3, 3000);
+        m.clear();
+    }
+
+
+    public interface Service1 {}
+    public interface Service2 {}
+    public interface Service3 {}
+
+    public static class Service2Impl implements Service2 {}
+    public static class Service3Impl1 implements Service3 {}
+    public static class Service3Impl2 implements Service3 {}
+
+    public static class MyComponent1 implements Service1 {
+        Service2 m_service2;
+        Service3 m_service3_xx;
+        Service3 m_service3_yy;
+        Ensure m_ensure;
+        
+        public MyComponent1(Ensure e) {
+            m_ensure = e;
+        }
+
+        void init(Component c) {
+            m_ensure.step(1);
+            // Service3/xx currently available
+            // Service3/yy not yet available
+
+            component(c, comp -> comp
+                .withSrv(Service3.class, srv->srv.filter("(type=xx)").autoConfig("m_service3_xx"))
+                .withSrv(Service3.class, srv->srv.filter("(type=yy)").autoConfig("m_service3_yy")));
+        }
+        
+        void start() {
+            System.out.println("MyComponent1.start");
+            Assert.assertNotNull(m_service2);
+            Assert.assertNotNull(m_service3_xx);
+            Assert.assertNotNull(m_service3_yy);
+            m_ensure.step(2);
+        }
+    }
+    
+    public static class MyComponent2 {
+        Ensure m_ensure;
+        
+        public MyComponent2(Ensure e) {
+            m_ensure = e;
+        }
+
+        void added(Service1 s1) {
+            System.out.println("MyComponent2.bind(" + s1 + ")");
+            Assert.assertNotNull(s1);
+            m_ensure.step(3);
+        }
+        
+        void start() {
+            System.out.println("MyComponent2.start");
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest.java
new file mode 100644
index 0000000..301bdf9
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+/**
+ * Test which validates multi-dependencies combination.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes", "serial"})
+public class MultipleExtraDependencyTest extends TestBase {
+    public void testMultipleExtraDependencies()
+    {
+        DependencyManager m = getDM();
+        Ensure e = new Ensure();
+        
+        Component sp2 = component(m)
+              .impl(ServiceProvider2.class).provides(ServiceProvider2.class)
+              .withSrv(Runnable.class, srv->srv.filter("(foo=bar)").required(false).autoConfig("m_runnable"))
+              .withSrv(Sequencer.class, srv->srv.cb("bind"))
+              .composition("getComposition")
+              .build();
+
+        Component sp = component(m)
+              .impl(ServiceProvider.class)
+              .provides(ServiceInterface.class, foo -> "bar")
+              .start("start").stop("stop")
+              .withSrv(Sequencer.class, srv->srv.autoConfig("m_sequencer"))
+              .withSrv(ServiceProvider2.class, srv->srv.cb("bind", "unbind"))
+              .build();
+        
+        Component sc = component(m)
+              .impl(ServiceConsumer.class)
+              .start("start").stop("stop")
+              .withSrv(Sequencer.class, srv->srv.autoConfig("m_sequencer"))
+              .withSrv(ServiceInterface.class, srv->srv.filter("(foo=bar)").autoConfig("m_service"))
+              .build();
+        
+        Component sequencer = component(m)
+           .impl(new SequencerImpl(e))
+           .provides(Sequencer.class.getName())
+           .build();
+           
+        m.add(sp2);
+        m.add(sp);
+        m.add(sc);
+        m.add(sequencer);
+        
+        // Check if ServiceProvider component have been initialized orderly
+        e.waitForStep(7, 5000);
+        
+        // Stop the test.annotation bundle
+        m.remove(sequencer);
+        m.remove(sp);
+        m.remove(sp2);
+        m.remove(sc);
+        
+        // And check if ServiceProvider2 has been deactivated orderly
+        e.waitForStep(11, 5000);
+    }
+    
+    public interface Sequencer
+    {
+        void step();
+        void step(int step);
+        void waitForStep(int step, int timeout);
+    }
+    
+    public static class SequencerImpl implements Sequencer {
+        Ensure m_ensure;
+        
+        public SequencerImpl(Ensure e)
+        {
+            m_ensure = e;
+        }
+        
+        public void step()
+        {
+            m_ensure.step();
+        }
+
+        public void step(int step)
+        {
+            m_ensure.step(step);
+        }
+
+        public void waitForStep(int step, int timeout)
+        {
+            m_ensure.waitForStep(step, timeout);
+        }  
+    }
+    
+    public interface ServiceInterface
+    {
+        public void doService();
+    }
+    
+    public static class ServiceConsumer
+    {
+        volatile Sequencer m_sequencer;
+        volatile ServiceInterface m_service;
+
+        void start()
+        {
+            m_sequencer.step(6);
+            m_service.doService();
+        }
+
+        void stop()
+        {
+            m_sequencer.step(8);
+        }
+    }
+    
+    public static class ServiceProvider implements ServiceInterface
+    {
+        Sequencer m_sequencer;
+        ServiceProvider2 m_serviceProvider2;
+
+        void bind(ServiceProvider2 provider2)
+        {
+            m_serviceProvider2 = provider2;
+        }
+
+        void start()
+        {
+            m_serviceProvider2.step(4);
+            m_sequencer.step(5);
+        }
+
+        void stop()
+        {
+            m_sequencer.step(9);
+        }
+
+        void unbind(ServiceProvider2 provider2)
+        {
+            m_sequencer.step(10);
+        }
+
+        public void doService()
+        {
+            m_sequencer.step(7);
+        }
+    }
+
+    public static class ServiceProvider2
+    {
+        Composite m_composite = new Composite();
+        Sequencer m_sequencer;
+        Runnable m_runnable;
+
+        void bind(Sequencer seq)
+        {
+            m_sequencer = seq;
+            m_sequencer.step(1);
+        }
+
+        void start()
+        {
+            m_sequencer.step(3);
+            m_runnable.run(); // NullObject
+        }
+
+        public void step(int step) // called by ServiceProvider.start() method 
+        { 
+            m_sequencer.step(step);
+        }
+        
+        void stop()
+        {
+            m_sequencer.step(11);
+        }
+
+        Object[] getComposition()
+        {
+            return new Object[] { this, m_composite };
+        }
+    }
+    
+    public static class Composite
+    {
+        void bind(Sequencer seq)
+        {
+            seq.step(2);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest2.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest2.java
new file mode 100644
index 0000000..b0c2c36
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest2.java
@@ -0,0 +1,235 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ServiceDependency;
+
+/**
+ * Tests for extra dependencies which are declared from service's init method.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class MultipleExtraDependencyTest2 extends TestBase {
+    public void testMultipleExtraDependencies() {
+        DependencyManager m = getDM();
+        Ensure e = new Ensure();
+        
+        Component sp2 = component(m)
+            .impl(ServiceProvider2.class)
+            .provides(ServiceProvider2.class)
+            .init("init").start("start").stop("stop")
+            .composition("getComposition").build();
+        
+        Component sp = component(m)
+            .impl(ServiceProvider.class)
+            .provides(ServiceInterface.class, "foo", "bar")                            
+            .init(ServiceProvider::init).start(ServiceProvider::start).stop(ServiceProvider::stop)
+            .build();
+        
+        Component sc = component(m)
+            .impl(ServiceConsumer.class)
+            .init("init").start("start").stop("stop")
+            .build();
+        
+        // Provide the Sequencer service to the MultipleAnnotationsTest class.
+        Component sequencer =  component(m)
+            .impl(new SequencerImpl(e))
+            .provides(Sequencer.class)
+            .build();
+        
+        m.add(sp2);
+        m.add(sp);
+        m.add(sc);
+        m.add(sequencer);
+
+        // Check if the test.annotation components have been initialized orderly
+        e.waitForStep(7, 10000);
+        
+        // Stop the test.annotation bundle
+        m.remove(sequencer);
+        m.remove(sp);
+        m.remove(sp2);
+        m.remove(sc);
+        
+//        m.remove(sp2);
+//        m.remove(sc);
+//        m.remove(sp);
+//        m.remove(sequencer);
+        
+
+        
+        // And check if the test.annotation bundle has been deactivated orderly
+        e.waitForStep(11, 10000);
+        m.clear();
+    }
+    
+    public interface Sequencer
+    {
+        void step();
+        void step(int step);
+        void waitForStep(int step, int timeout);
+    }
+    
+    public static class SequencerImpl implements Sequencer {
+        final Ensure m_ensure;
+        
+        public SequencerImpl(Ensure e)
+        {
+            m_ensure = e;
+        }
+        
+        public void step()
+        {
+            m_ensure.step();
+        }
+
+        public void step(int step)
+        {
+            m_ensure.step(step);
+        }
+
+        public void waitForStep(int step, int timeout)
+        {
+            m_ensure.waitForStep(step, timeout);
+        }  
+    }
+    
+    public interface ServiceInterface
+    {
+        public void doService();
+    }
+    
+    public static class ServiceConsumer {
+        volatile Sequencer m_sequencer;
+        volatile ServiceInterface m_service;
+        volatile Dependency m_d1, m_d2;
+
+        public void init(Component s) {
+            component(s, comp->comp
+                .withSrv(Sequencer.class, srv->srv.autoConfig("m_sequencer"))
+                .withSrv(ServiceInterface.class, srv->srv.filter("(foo=bar)").autoConfig("m_service")));
+        }
+        
+        void start() {
+            m_sequencer.step(6);
+            m_service.doService();
+        }
+
+        void stop() {
+            m_sequencer.step(8);
+        }
+    }
+    
+    public static class ServiceProvider implements ServiceInterface
+    {
+        volatile Sequencer m_sequencer;
+        volatile ServiceProvider2 m_serviceProvider2;
+        volatile ServiceDependency m_d1, m_d2;
+
+        public void init(Component c)
+        {
+            component(c, comp->comp
+                .withSrv(Sequencer.class, srv->srv.autoConfig("m_sequencer"))
+                .withSrv(ServiceProvider2.class, srv->srv.cb("bind", "unbind")));
+        }
+        
+        void bind(ServiceProvider2 provider2)
+        {
+            m_serviceProvider2 = provider2;
+        }
+
+        void start()
+        {
+            m_serviceProvider2.step(4);
+            m_sequencer.step(5);
+        }
+
+        void stop()
+        {
+            m_sequencer.step(9);
+        }
+
+        void unbind(ServiceProvider2 provider2)
+        {
+            m_sequencer.step(10);
+        }
+
+        public void doService()
+        {
+            m_sequencer.step(7);
+        }
+    }
+
+    public static class ServiceProvider2
+    {
+        final Composite m_composite = new Composite();
+        volatile Sequencer m_sequencer;
+        volatile Runnable m_runnable;
+        volatile ServiceDependency m_d1, m_d2;
+
+        public void init(Component c)
+        {
+            component(c, comp->comp
+		      .withSrv(Runnable.class, srv->srv.optional().filter("(foo=bar)"))
+		      .withSrv(Sequencer.class, srv->srv.cb("bind")));
+        }
+        
+        void bind(Sequencer seq)
+        {
+            System.out.println("ServiceProvider2.bind(" + seq + ")");
+            m_sequencer = seq;
+            m_sequencer.step(1);
+        }
+
+        void start()
+        {
+            System.out.println("ServiceProvider2.start: m_runnable=" + m_runnable + ", m_sequencer = " + m_sequencer);
+            m_sequencer.step(3);
+            m_runnable.run(); // NullObject
+        }
+
+        public void step(int step) // called by ServiceProvider.start() method 
+        { 
+            m_sequencer.step(step);
+        }
+        
+        void stop()
+        {
+            m_sequencer.step(11);
+        }
+
+        Object[] getComposition()
+        {
+            return new Object[] { this, m_composite };
+        }
+    }
+    
+    public static class Composite
+    {
+        void bind(Sequencer seq)
+        {
+            seq.step(2);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleServiceDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleServiceDependencyTest.java
new file mode 100644
index 0000000..8a8af42
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleServiceDependencyTest.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Constants;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes", "serial"})
+public class MultipleServiceDependencyTest extends TestBase {
+   public void testMultipleServiceRegistrationAndConsumption() {
+       DependencyManager m = getDM();
+       // helper class that ensures certain steps get executed in sequence
+       Ensure e = new Ensure();
+       // create a service provider and consumer
+       Component provider = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+       Component providerWithHighRank = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface.class.getName(), Constants.SERVICE_RANKING, Integer.valueOf(5)).build();
+       Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class).build();
+       m.add(provider);
+       m.add(providerWithHighRank);
+       m.add(consumer);
+       e.waitForStep(3, 5000);
+       m.remove(providerWithHighRank);
+       e.step(4);
+       e.waitForStep(5, 5000);
+       m.remove(provider);
+       m.remove(consumer);
+       e.waitForStep(6, 5000);
+   }
+
+   public void testReplacementAutoConfig() {
+       DependencyManager m = getDM();
+       // helper class that ensures certain steps get executed in sequence
+       Ensure e = new Ensure();
+       // create a service provider and consumer
+       Component provider = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+       Component provider2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface.class.getName()).build();
+       Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class).build();
+       m.add(provider2);
+       m.add(consumer);
+       e.waitForStep(3, 5000);
+       m.add(provider);
+       m.remove(provider2);
+       e.step(4);
+       e.waitForStep(5, 5000);
+       m.remove(provider);
+       m.remove(consumer);
+       e.waitForStep(6, 5000);
+   }
+
+   public void testReplacementCallbacks() {
+       DependencyManager m = getDM();
+       // helper class that ensures certain steps get executed in sequence
+       Ensure e = new Ensure();
+       // create a service provider and consumer
+       Component provider = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+       Component provider2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface.class.getName()).build();
+       Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, srv->srv.cb("add", "remove")).build();
+       m.add(provider2);
+       m.add(consumer);
+       e.waitForStep(3, 15000);
+       m.add(provider);
+       m.remove(provider2);
+       e.step(4);
+       e.waitForStep(5, 15000);
+       m.remove(provider);
+       m.remove(consumer);
+       e.waitForStep(6, 15000);
+   }
+
+   static interface ServiceInterface {
+       public void invoke();
+   }
+
+   static class ServiceProvider implements ServiceInterface {
+       private final Ensure m_ensure;
+       public ServiceProvider(Ensure e) {
+           m_ensure = e;
+       }
+       public void invoke() {
+           m_ensure.step(5);
+       }
+   }
+
+   static class ServiceProvider2 implements ServiceInterface {
+       private final Ensure m_ensure;
+       public ServiceProvider2(Ensure e) {
+           m_ensure = e;
+       }
+       public void invoke() {
+           m_ensure.step(2);
+       }
+   }
+
+   static class ServiceConsumer implements Runnable {
+       private volatile ServiceInterface m_service;
+       private final Ensure m_ensure;
+
+       @SuppressWarnings("unused")
+       private void add(ServiceInterface service) { m_service = service; }
+       
+       @SuppressWarnings("unused")
+       private void remove(ServiceInterface service) { if (m_service == service) { m_service = null; }}
+       public ServiceConsumer(Ensure e) { m_ensure = e; }
+
+       public void start() {
+           Thread t = new Thread(this);
+           t.start();
+       }
+
+       public void run() {
+           m_ensure.step(1);
+           m_service.invoke();
+           m_ensure.step(3);
+           m_ensure.waitForStep(4, 15000);
+           m_service.invoke();
+       }
+
+       public void stop() {
+           m_ensure.step(6);
+       }
+   }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/RemovedDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/RemovedDependencyTest.java
new file mode 100644
index 0000000..30424d0
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/RemovedDependencyTest.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.serviceDependency;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * One consumer, Three providers. The Consumer has two required dependency on provider1, provider2, and one 
+ * instance-bound required dependency on provider3.
+ * When the three providers are there, the consumer is started.
+ * 
+ * This test asserts the following correct behaviors:
+ *   - when we remove the dependency on provider2, then the consumer is not stopped.
+ *   - when we remove the (instance-bound) dependency on provider3, then the consumer os not stopped.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes", "unused"})
+public class RemovedDependencyTest extends TestBase {
+    public void testRemoveDependencyAndConsumerMustRemainStarted() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // Create two providers
+        Hashtable props = new Hashtable();
+        props.put("name", "provider1");
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class, props).build();
+        props = new Properties();
+        props.put("name", "provider2");
+        Component sp2 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName(), props).build();
+        props = new Properties();
+        props.put("name", "provider3");
+        Component sp3 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName(), props).build();
+
+        // Create the consumer, and start it
+        Dependency d3 = m.createServiceDependency().setService(ServiceInterface.class, "(name=provider3)").setRequired(true).setCallbacks("add", "remove");
+
+        ServiceConsumer consumer = new ServiceConsumer(e, d3);
+        Component sc = component(m).impl(consumer).build();
+        
+        Dependency d1 = serviceDependency(sc, ServiceInterface.class).filter("(name=provider1)").cb("add", "remove").build();
+        Dependency d2 = serviceDependency(sc, ServiceInterface.class).filter("(name=provider2)").cb("add", "remove").build();
+        
+        sc.add(d1, d2);
+            
+        // Add the first two providers and the consumer
+        m.add(sp);
+        m.add(sp2);
+        m.add(sp3);
+        m.add(sc);
+        
+        // Check if consumer has been bound to the three providers
+        e.waitForStep(3,  5000);
+        Assert.assertEquals(3, consumer.getProvidersCount());
+        Assert.assertNotNull(consumer.getProvider("provider1"));
+        Assert.assertNotNull(consumer.getProvider("provider2"));
+        Assert.assertNotNull(consumer.getProvider("provider3"));
+        
+        // Now remove the provider2, and check if the consumer is still alive
+        sc.remove(d2);
+        Assert.assertFalse(consumer.isStopped());
+        Assert.assertEquals(2, consumer.getProvidersCount());
+        Assert.assertNotNull(consumer.getProvider("provider1"));
+        Assert.assertNull(consumer.getProvider("provider2"));
+        Assert.assertNotNull(consumer.getProvider("provider3"));
+
+        // Now remove the provider3 (the consumer has an instance bound dependency on it), and check if the consumer is still alive
+        sc.remove(d3);
+        Assert.assertFalse(consumer.isStopped());
+        Assert.assertEquals(1, consumer.getProvidersCount());
+        Assert.assertNotNull(consumer.getProvider("provider1"));
+        Assert.assertNull(consumer.getProvider("provider2"));
+        Assert.assertNull(consumer.getProvider("provider3"));
+        
+        m.clear();
+    }
+    
+    static interface ServiceInterface {
+        public void invoke();
+    }
+
+    class ServiceProvider implements ServiceInterface {
+        final Ensure m_ensure;
+        
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke() {
+            m_ensure.step();
+        }
+    }
+    
+    class ServiceConsumer {
+        private final Ensure m_ensure;
+        private final List<ServiceReference> m_providers = new ArrayList<>();
+        private BundleContext m_bc;
+        private boolean m_stopped;
+        private final Dependency m_dependency3;
+
+        public ServiceConsumer(Ensure e, Dependency dependency3) {
+            m_ensure = e;
+            m_dependency3 = dependency3;
+        }
+                
+        public void add(ServiceReference ref) {
+            debug("ServiceConsumer.add(%s)", ref);
+            m_providers.add(ref);
+            ServiceInterface s = (ServiceInterface) m_bc.getService(ref);
+            s.invoke();
+        }
+        
+        public void remove(ServiceReference ref) {
+            debug("ServiceConsumer.remove(%s)", ref);
+            m_providers.remove(ref);
+            debug("ServiceConsumer: current providers list=%s", m_providers);
+        }
+        
+        public void init(Component c) {
+            c.add(m_dependency3);
+        }
+        
+        public int getProvidersCount() {
+            return m_providers.size();
+        }
+        
+        public ServiceInterface getProvider(String name) {
+            for (ServiceReference ref : m_providers) {
+                Object n = ref.getProperty("name");
+                if (n.equals(name)) {
+                    return (ServiceInterface) m_bc.getService(ref);
+                }
+            }
+            return null;
+        }
+        
+        public void stop() {
+            m_stopped = true;
+        }
+        
+        public boolean isStopped() {
+            return m_stopped;
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ResourceProvider.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ResourceProvider.java
new file mode 100644
index 0000000..260fa59
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ResourceProvider.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.felix.dm.ResourceHandler;
+import org.apache.felix.dm.ResourceUtil;
+import org.junit.Assert;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+class ResourceProvider {
+	final URL[] m_resources;
+    final BundleContext m_context;
+    final Map<ResourceHandler, Filter> m_handlers = new HashMap<>();
+
+	ResourceProvider(BundleContext ctx, URL ... resources) {
+		m_context = ctx;
+		m_resources = resources;
+	}
+	
+    public void change() {
+        for (int i = 0; i < m_resources.length; i++) {
+        	change(i);
+        }    	
+    }
+    
+    @SuppressWarnings({ "deprecation", "unchecked" })
+	public void change(int resourceIndex) {
+        Map<ResourceHandler, Filter> handlers = new HashMap<>();
+        synchronized (m_handlers) {
+            handlers.putAll(m_handlers);
+        }
+        for (Map.Entry<ResourceHandler, Filter> e : handlers.entrySet()) {
+        	ResourceHandler handler = e.getKey();
+        	Filter filter = e.getValue();
+        	if (filter == null || filter.match((Dictionary<String, ? >)ResourceUtil.createProperties(m_resources[resourceIndex]))) {
+        		handler.changed(m_resources[resourceIndex]);
+            }
+        }
+    }
+
+    @SuppressWarnings({ "deprecation", "unchecked" })
+	public void add(ServiceReference<ResourceHandler> ref, ResourceHandler handler) {
+        String filterString = (String) ref.getProperty("filter");
+        Filter filter = null;
+        if (filterString != null) {
+            try {
+                filter = m_context.createFilter(filterString);
+            }
+            catch (InvalidSyntaxException e) {
+                Assert.fail("Could not create filter for resource handler: " + e);
+                return;
+            }
+        }
+        for (int i = 0; i < m_resources.length; i++) {
+            if (filter == null || filter.match((Dictionary<String, ? >) ResourceUtil.createProperties(m_resources[i]))) {
+                synchronized (m_handlers) {
+                    m_handlers.put(handler, filter);
+                }
+                handler.added(m_resources[i]);
+            }
+        }
+    }
+
+    public void remove(ServiceReference<ResourceHandler> ref, ResourceHandler handler) {
+        Filter filter;
+        synchronized (m_handlers) {
+            filter = (Filter) m_handlers.remove(handler);
+        }
+        if (filter != null) {
+        	removeResources(handler, filter);
+        }
+    }
+
+    @SuppressWarnings({ "deprecation", "unchecked" })
+	private void removeResources(ResourceHandler handler, Filter filter) {
+            for (int i = 0; i < m_resources.length; i++) {
+                if (filter == null || filter.match((Dictionary<String, ? >)ResourceUtil.createProperties(m_resources[i]))) {
+                    handler.removed(m_resources[i]);
+                }
+            }
+        }
+
+    public void destroy() {
+        Map<ResourceHandler, Filter> handlers = new HashMap<>();
+        synchronized (m_handlers) {
+            handlers.putAll(m_handlers);
+        }
+
+        for (Map.Entry<ResourceHandler, Filter> e : handlers.entrySet()) {
+            ResourceHandler handler = e.getKey();
+            Filter filter = e.getValue();
+            removeResources(handler, filter);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyCallbackSignaturesTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyCallbackSignaturesTest.java
new file mode 100644
index 0000000..609cca1
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyCallbackSignaturesTest.java
@@ -0,0 +1,297 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class ServiceDependencyCallbackSignaturesTest extends TestBase {
+    volatile Ensure m_ensure;
+    
+    /**
+     * Tests if all possible dependency callbacks signatures supported by ServiceDependency.
+     */
+    public void testDependencyCallbackSignatures() {
+        DependencyManager m = getDM();
+        m_ensure = new Ensure();    
+        Hashtable<String, String> props = new Hashtable<>();
+        props.put("foo", "bar");
+        Component provider = component(m)
+            .impl(new ProviderImpl()).provides(Provider.class.getName(), props).build();
+        
+        component(m, c->c.impl(new Consumer1()).withSrv(Provider.class, srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer2()).withSrv(Provider.class, srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer3()).withSrv(Provider.class, srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer4()).withSrv(Provider.class, srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer5()).withSrv(Provider.class, srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer6()).withSrv(Provider.class, srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer7()).withSrv(Provider.class, srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer8()).withSrv(Provider.class, srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer9()).withSrv(Provider.class, srv->srv.cb("bind", "change", "remove")));
+
+        m.add(provider);
+        m_ensure.waitForStep(9, 5000);
+        
+        props = new Hashtable<>();
+        props.put("foo", "zoo");
+        provider.setServiceProperties(props);
+        m_ensure.waitForStep(18, 5000);
+        
+        m.remove(provider);
+        m_ensure.waitForStep(26, 5000);
+    }
+    
+    /**
+     * Tests if all possible dependency callbacks signatures supported by ServiceDependency.
+     */
+    public void testDependencyCallbackSignaturesRef() {
+        DependencyManager m = getDM();
+        m_ensure = new Ensure();    
+        Hashtable<String, String> props = new Hashtable<>();
+        props.put("foo", "bar");
+        Component provider = component(m)
+            .impl(new ProviderImpl()).provides(Provider.class.getName(), props).build();
+        
+        component(m, c->c.impl(new Consumer1()).withSrv(Provider.class, srv->srv.cb(Consumer1::bind, Consumer1::change, Consumer1::remove)));
+        component(m, c->c.impl(new Consumer2()).withSrv(Provider.class, srv->srv.cb(Consumer2::bind, Consumer2::change, Consumer2::remove)));
+        component(m, c->c.impl(new Consumer3()).withSrv(Provider.class, srv->srv.cb(Consumer3::bind, Consumer3::change, Consumer3::remove)));
+        component(m, c->c.impl(new Consumer4()).withSrv(Provider.class, srv->srv.cb(Consumer4::bind, Consumer4::change, Consumer4::remove)));
+        component(m, c->c.impl(new Consumer5()).withSrv(Provider.class, srv->srv.cb(Consumer5::bind, Consumer5::change, Consumer5::remove)));
+        component(m, c->c.impl(new Consumer6()).withSrv(Provider.class, srv->srv.cb(Consumer6::bind, Consumer6::change, Consumer6::remove)));
+        component(m, c->c.impl(new Consumer7()).withSrv(Provider.class, srv->srv.cb(Consumer7::bind, Consumer7::change, Consumer7::remove)));
+        component(m, c->c.impl(new Consumer8()).withSrv(Provider.class, srv->srv.cb(Consumer8::bind, Consumer8::change, Consumer8::remove)));
+        component(m, c->c.impl(new Consumer9()).withSrv(Provider.class, srv->srv.cb(Consumer9::bind, Consumer9::change, Consumer9::remove)));
+
+        m.add(provider);
+        m_ensure.waitForStep(9, 5000);
+        
+        props = new Hashtable<>();
+        props.put("foo", "zoo");
+        provider.setServiceProperties(props);
+        m_ensure.waitForStep(18, 5000);
+        
+        m.remove(provider);
+        m_ensure.waitForStep(26, 5000);
+    }
+    
+    private void declareConsumer(DependencyManager m, Object consumerImpl) {
+        Component consumer = component(m)
+            .impl(consumerImpl)
+            .withSrv(Provider.class, srv->srv.cb("bind", "change", "change"))
+            .build();
+        m.add(consumer);
+    }
+
+    public static interface Provider {        
+    }
+    
+    public static class ProviderImpl implements Provider {        
+    }
+    
+    class Consumer1 {        
+        void bind(Provider provider) {
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+        void change(Provider provider) {
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+        
+        void remove(Provider provider) {
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+    }
+    
+    class Consumer2 {        
+        void bind(Provider provider, Map<String, Object> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("bar", props.get("foo"));
+            m_ensure.step();
+        }
+        void change(Provider provider, Map<String, Object> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", props.get("foo"));
+            m_ensure.step();
+        }
+        void remove(Provider provider, Map<String, Object> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", props.get("foo"));
+            m_ensure.step();
+        }
+    }
+    
+    class Consumer3 {        
+        void bind(Provider provider, Dictionary<?, ?> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("bar", props.get("foo"));
+            m_ensure.step();
+        }
+        void change(Provider provider, Dictionary<?, ?> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", props.get("foo"));
+            m_ensure.step();
+        }
+        void remove(Provider provider, Dictionary<?, ?> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", props.get("foo"));
+            m_ensure.step();
+        }
+    }
+
+    class Consumer4 {        
+        void bind(ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("bar", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+        void change(ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+        void remove(ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+    }
+        
+    class Consumer5 {        
+        void bind(ServiceReference ref) {
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("bar", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+        void change(ServiceReference ref) {
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+        void remove(ServiceReference ref) {
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+    }
+
+    class Consumer6 {        
+        void bind(Component c) {
+            Assert.assertNotNull(c);
+            m_ensure.step();
+        }
+        void change(Component c) {
+            Assert.assertNotNull(c);
+            m_ensure.step();
+        }
+        void remove(Component c) {
+            Assert.assertNotNull(c);
+            m_ensure.step();
+        }
+    }
+        
+    class Consumer7 {
+        void bind(Component c, ServiceReference ref) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("bar", ref.getProperty("foo"));
+            Assert.assertNotNull(context.getService(ref));
+            Assert.assertEquals(context.getService(ref).getClass(), ProviderImpl.class);
+            m_ensure.step();
+        }
+        void change(Component c, ServiceReference ref) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            Assert.assertNotNull(context.getService(ref));
+            Assert.assertEquals(context.getService(ref).getClass(), ProviderImpl.class);
+            m_ensure.step();
+        }
+        void remove(Component c, ServiceReference ref) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            Assert.assertNotNull(context.getService(ref));
+            Assert.assertEquals(context.getService(ref).getClass(), ProviderImpl.class);
+            m_ensure.step();
+        }
+    }
+        
+    class Consumer8 {
+        void bind(Component c, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+        void change(Component c, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+        void remove(Component c, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+    }
+    
+    class Consumer9 {
+        void bind(Component c, ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("bar", ref.getProperty("foo"));
+            Assert.assertEquals(context.getService(ref), provider);
+            m_ensure.step();
+        }
+        void change(Component c, ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            Assert.assertEquals(context.getService(ref), provider);
+            m_ensure.step();
+        }
+        void remove(Component c, ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            Assert.assertEquals(context.getService(ref), provider);
+            m_ensure.step();
+        }
+    }
+        
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyInjectionTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyInjectionTest.java
new file mode 100644
index 0000000..1dff100
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyInjectionTest.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceDependencyInjectionTest extends TestBase {
+    public void testServiceInjection() {
+        DependencyManager m = getDM();
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        ServiceProvider provider = new ServiceProvider(e);
+        Component sp = component(m).impl(provider).provides(ServiceInterface2.class.getName()).build();
+        Component sc = component(m).impl(new ServiceConsumer()).withSrv(ServiceInterface2.class).build();
+           
+        Component sc2 = component(m) // all dependencies are optional
+            .impl(new ServiceConsumerNamedInjection(false, false)) 
+            .withSrv(ServiceInterface2.class, s->s.optional().autoConfig("m_service"))
+            .withSrv(ServiceInterface2.class, s->s.optional().autoConfig("m_service2"))
+            .withSrv(ServiceInterface2.class, s->s.optional().autoConfig("m_service3"))
+            .build();
+        
+        Component sc3 = component(m) // second dependency is required, first and third are optional
+            .impl(new ServiceConsumerNamedInjection(false, false))
+            .withSrv(ServiceInterface2.class, s->s.optional().autoConfig("m_service"))
+            .withSrv(ServiceInterface2.class, s->s.required().autoConfig("m_service2"))
+            .withSrv(ServiceInterface2.class, s->s.optional().autoConfig("m_service3"))
+            .build();
+        
+        Component sc4 = component(m)
+            .impl(new ServiceConsumerNamedInjection(true, false)).build();
+        Component sc5 = component(m)
+            .impl(new ServiceConsumerNamedInjection(true, true)).build();
+        m.add(sp);
+        m.add(sc);
+        m.remove(sc);
+        m.add(sc2);
+        m.remove(sc2);
+        m.add(sc3);
+        m.remove(sc4);
+        m.add(sc4);
+        m.remove(sc4);
+        m.add(sc5);
+        m.remove(sc5);
+        m.remove(sp);
+        e.waitForStep(11, 5000);
+        m.clear();
+    }
+    
+    static interface ServiceInterface {
+        public void invoke();
+    }
+    
+    static interface ServiceInterface2 extends ServiceInterface {
+        public void invoke2();
+    }
+
+    static class ServiceProvider implements ServiceInterface2 {
+        private final Ensure m_ensure;
+        private Ensure.Steps m_invokeSteps = new Ensure.Steps(4, 5, 7, 8, 10, 11, 13, 14);
+        private Ensure.Steps m_invoke2Steps = new Ensure.Steps(1, 2, 3, 6, 9, 12);
+        
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+
+        public void invoke() {
+            System.out.println("invoke");
+            m_ensure.steps(m_invokeSteps);
+        }
+        
+        public void invoke2() {
+            System.out.println("invoke2");
+            m_ensure.steps(m_invoke2Steps);
+        }
+    }
+
+    static class ServiceConsumer {
+        private volatile ServiceInterface2 m_service;
+        private volatile ServiceInterface2 m_service2;
+        
+        public void init() {
+            // invoke the second method of the interface via both injected members, to ensure
+            // neither of them is a null object (or null)
+            m_service.invoke2();
+            m_service2.invoke2();
+            Assert.assertEquals("Both members should have been injected with the same service.", m_service, m_service2);
+        }
+    }
+
+    class ServiceConsumerNamedInjection {
+        private volatile ServiceInterface2 m_service;
+        private volatile ServiceInterface m_service2;
+        private volatile Object m_service3;
+        private final boolean m_secondDependencyRequired;
+        private final boolean m_instanceBound;
+        
+        ServiceConsumerNamedInjection(boolean instanceBound, boolean withSecondRequired) {
+            m_secondDependencyRequired = withSecondRequired;
+            m_instanceBound = instanceBound;
+        }
+
+        public void init(Component c) {
+            if (m_instanceBound) {
+                DependencyManager m = c.getDependencyManager();
+                c.add(m.createServiceDependency().setService(ServiceInterface2.class).setRequired(false).setAutoConfig("m_service"),
+                    m.createServiceDependency().setService(ServiceInterface2.class).setRequired(m_secondDependencyRequired).setAutoConfig("m_service2"),
+                    m.createServiceDependency().setService(ServiceInterface2.class).setRequired(false).setAutoConfig("m_service3"));
+            } else {
+                check();
+            }
+        }
+        
+        public void start() {
+            if (m_instanceBound) {
+                check();
+            }
+        }
+        
+        public void check() {
+            warn("ServiceConsumerNamedInjectionInstanceBound: m_service=%s, m_service2=%s, m_service3=%s", m_service, m_service2, m_service3);
+            // invoke the second method
+            m_service.invoke2();
+            // invoke the first method (twice)
+            m_service2.invoke();
+            ((ServiceInterface) m_service3).invoke();
+            Assert.assertNotNull("Should have been injected", m_service);
+            Assert.assertNotNull("Should have been injected", m_service2);
+            Assert.assertNotNull("Should have been injected", m_service3);
+            Assert.assertEquals("Members should have been injected with the same service.", m_service, m_service2);
+            Assert.assertEquals("Members should have been injected with the same service.", m_service, m_service3);          
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyPropagateTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyPropagateTest.java
new file mode 100644
index 0000000..227a738
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyPropagateTest.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Validates ServiceDependency service properties propagation.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes", "serial"})
+public class ServiceDependencyPropagateTest extends TestBase {
+    /**
+     * Checks that a ServiceDependency propagates the dependency service properties to the provided service properties.
+     */
+    public void testServiceDependencyPropagate() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        Component c1 = component(m)
+                      .impl(new C1(e))
+                      .withSrv(C2.class, s->s.cb("bind")).build();
+
+        Component c2 = component(m)
+                      .provides(C2.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+                      .impl(new C2())
+                      .withSrv(C3.class, s->s.propagate()).build();
+
+        Component c3 = component(m)
+                      .provides(C3.class.getName(), new Hashtable() {{ put("foo2", "bar2"); put("foo", "overriden");}})
+                      .impl(new C3()).build();
+        
+        m.add(c1);
+        m.add(c2);
+        m.add(c3);
+
+        e.waitForStep(3, 10000);
+        
+        m.remove(c3);
+        m.remove(c2);
+        m.remove(c1);
+        m.clear();
+    }
+    
+    /**
+     * Checks that a ServiceDependency propagates the dependency service properties to the provided service properties,
+     * using a callback method.
+     */
+    public void testServiceDependencyPropagateCallback() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        Component c1 = component(m)
+                      .impl(new C1(e))
+                      .withSrv(C2.class, s->s.cb("bind")).build();
+
+        C2 c2Impl = new C2();
+        Component c2 = component(m)
+                      .provides(C2.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+                      .impl(c2Impl)
+                      .withSrv(C3.class, s->s.propagate(c2Impl, "getServiceProperties")).build();
+        
+        Component c3 = component(m)
+                      .provides(C3.class.getName())
+                      .impl(new C3()).build();
+        
+        m.add(c1);
+        m.add(c2);
+        m.add(c3);
+
+        e.waitForStep(3, 10000);
+        m.clear();
+    }
+    
+    public void testServiceDependencyPropagateCallbackRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        Component c1 = component(m)
+                      .impl(new C1(e))
+                      .withSrv(C2.class, s->s.cb(C1::bind)).build();
+
+        C2 c2Impl = new C2();
+        Component c2 = component(m)
+                      .provides(C2.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+                      .impl(c2Impl)
+                      .withSrv(C3.class, s->s.propagate(c2Impl::getServiceProperties)).build();
+        
+        Component c3 = component(m)
+                      .provides(C3.class.getName())
+                      .impl(new C3()).build();
+        
+        m.add(c1);
+        m.add(c2);
+        m.add(c3);
+
+        e.waitForStep(3, 10000);
+        m.clear();
+    }
+
+    public static class C1 {
+        private Map m_props;
+        private Ensure m_ensure;
+        
+        C1(Ensure ensure) {
+            m_ensure = ensure;
+        }
+
+        void bind(C2 c2, Map props) {
+            m_props = props;
+        }
+        
+        void start() {
+            m_ensure.step(1);
+            if ("bar".equals(m_props.get("foo"))) { // "foo=overriden" from C2 should not override our own "foo" property
+                m_ensure.step(2);
+            }
+            if ("bar2".equals(m_props.get("foo2"))) {
+                m_ensure.step(3);
+            }
+        }
+    }
+    
+    public static class C2 {
+      C3 m_c3;
+      
+      public Dictionary getServiceProperties(ServiceReference ref) {
+          return new Hashtable() {{ put("foo2", "bar2"); put("foo", "overriden"); }};
+      }
+    }
+    
+    public static class C3 {
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyTest.java
new file mode 100644
index 0000000..6f4e35a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyTest.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceDependencyTest extends TestBase {
+    public void testServiceRegistrationAndConsumption() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class).build();
+        		
+        Component sc2 = component(m).impl(new ServiceConsumerCallbacks(e))
+            .withSrv(ServiceInterface.class, srv -> srv.required(false).cb(ServiceConsumerCallbacks::add, ServiceConsumerCallbacks::remove))
+            .build();
+
+        m.add(sp);
+        m.add(sc);
+        m.remove(sc);
+        m.add(sc2);
+        m.remove(sp);
+        m.remove(sc2);
+        // ensure we executed all steps inside the component instance
+        e.step(6);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke();
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke() {
+            m_ensure.step(2);
+        }
+    }
+
+    static class ServiceConsumer {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            m_ensure.step(1);
+            m_service.invoke();
+        }
+        
+        public void destroy() {
+            m_ensure.step(3);
+        }
+    }
+
+    static class ServiceConsumerCallbacks {
+        private final Ensure m_ensure;
+
+        public ServiceConsumerCallbacks(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void add(ServiceInterface service) {
+            m_ensure.step(4);
+        }
+        public void remove(ServiceInterface service) {
+            m_ensure.step(5);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyThroughCallbackInstanceTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyThroughCallbackInstanceTest.java
new file mode 100644
index 0000000..31616f9
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyThroughCallbackInstanceTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.BundleContext;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceDependencyThroughCallbackInstanceTest extends TestBase {
+    public void testServiceWithCallbacksAndOneDependency() {
+        invokeTest(context, 1);
+    }
+    
+    public void testServiceWithCallbacksAndThreeDependencies() {
+        invokeTest(context, 3);
+    }
+
+    private void invokeTest(BundleContext context, int numberOfServices) {
+        DependencyManager m = getDM();
+        // create a number of services
+		for (int i = 0; i < numberOfServices; i++) {
+			final int num = i;
+			component(m, comp -> comp
+					.provides(Service.class).impl(new Service() {
+						public String toString() {
+							return "A" + num;
+						}}));
+		}
+
+		// create a service with dependency which will be invoked on a callback instance
+		CallbackInstance instance = new CallbackInstance();
+		component(m, comp -> comp
+				.impl(new SimpleService() {})
+				.withSrv(Service.class, srv -> srv.cbi(instance::added, instance::removed)));
+		
+		Assert.assertEquals(numberOfServices, instance.getCount());
+		m.clear();
+    }
+    
+    public static interface Service {
+    }
+    
+    public static interface SimpleService {
+    }
+    
+    public static class CallbackInstance {
+    	int m_count = 0;
+
+    	void added(Service service) {
+    	    System.out.println("added " + service);
+    		m_count++;
+    	}
+    	
+    	void removed(Service service) {
+    	}	
+    	
+    	int getCount() {
+    		return m_count;
+    	}
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceUpdateTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceUpdateTest.java
new file mode 100644
index 0000000..b181449
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceUpdateTest.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ResourceHandler;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceUpdateTest extends TestBase {
+    public void testServiceUpdate() throws Exception {
+        final DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a resource provider
+        ResourceProvider provider = new ResourceProvider(context, new URL("file://localhost/path/to/file1.txt"));        
+        // activate it
+        component(m, comp -> comp
+        		.impl(new ServiceProvider(e))
+        		.withSrv(ServiceInterface.class, srv -> srv
+        				.cb(ServiceProvider::add, ServiceProvider::change, ServiceProvider::remove)));
+        component(m, comp -> comp
+        		.impl(provider)
+        		.withSrv(ResourceHandler.class, srv -> srv.cb(ResourceProvider::add, ResourceProvider::remove)));
+               
+        // TODO implement resource adapters in new builder API and use it for the following resource adapter.
+        
+        // create a resource adapter for our single resource
+        // note that we can provide an actual implementation instance here because there will be only one
+        // adapter, normally you'd want to specify a Class here
+        CallbackInstance callbackInstance = new CallbackInstance(e);
+        Hashtable<String, String> serviceProps = new Hashtable<String, String>();
+        serviceProps.put("number", "1");
+        Component component = m.createResourceAdapterService("(&(path=/path/to/*.txt)(host=localhost))", false, callbackInstance, "changed")
+            .setImplementation(new ResourceAdapter(e))
+            .setInterface(ServiceInterface.class.getName(), serviceProps)
+            .setCallbacks(callbackInstance, "init", "start", "stop", "destroy");
+        m.add(component);
+        // wait until the single resource is available
+        e.waitForStep(1, 5000);
+        // wait until the component gets the dependency injected
+        e.waitForStep(2, 5000);
+        // trigger a 'change' in our resource
+        provider.change();
+        // wait until the changed callback is invoked
+        e.waitForStep(3, 5000);        
+        // wait until the changed event arrived at the component
+        e.waitForStep(4, 5000);
+        System.out.println("Done!");
+     }
+    
+    static class ResourceAdapter implements ServiceInterface {
+        protected URL m_resource; // injected by reflection.
+        
+        ResourceAdapter(Ensure e) {
+        }
+
+        public void invoke() {
+            // TODO Auto-generated method stub
+            
+        }
+    }
+        
+    static interface ServiceInterface {
+        public void invoke();
+    }
+
+    static class ServiceProvider {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        void add(ServiceInterface i) {
+            m_ensure.step(2);
+        }
+        void change(ServiceInterface i) {
+            System.out.println("Change...");
+            m_ensure.step(4);
+        }
+        void remove(ServiceInterface i) {
+            System.out.println("Remove...");
+        }
+    }    
+    
+    static class CallbackInstance {
+        private final Ensure m_ensure;
+        public CallbackInstance(Ensure e) {
+            m_ensure = e;
+        }
+        
+        void init() {
+            System.out.println("init");
+        }
+        void start() {
+            System.out.println("start");
+            m_ensure.step(1);
+        }
+        void stop() {
+            System.out.println("stop");
+        }
+        void destroy() {
+            System.out.println("destroy");
+        }
+        @SuppressWarnings("unchecked")
+		void changed(Component component) {
+            System.out.println("resource changed");
+            m_ensure.step(3);
+            
+            Properties newProps = new Properties();
+            // update the component's service properties
+            Dictionary<String, String> dict = component.getServiceProperties();
+            Enumeration<String> e = dict.keys();
+            while (e.hasMoreElements()) {
+                String key = e.nextElement();
+                String value = dict.get(key);
+                newProps.setProperty(key, value);
+            }
+            newProps.setProperty("new-property", "2");
+            component.getServiceRegistration().setProperties(newProps);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceUtil.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceUtil.java
new file mode 100644
index 0000000..3862885
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceUtil.java
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import java.util.List;
+
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * OSGi service utilities (copied from dependency manager implementation).
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceUtil {
+    /**
+     * Returns the service ranking of a service, based on its service reference. If
+     * the service has a property specifying its ranking, that will be returned. If
+     * not, the default ranking of zero will be returned.
+     * 
+     * @param ref the service reference to determine the ranking for
+     * @return the ranking
+     */
+    public static int getRanking(ServiceReference<?> ref) {
+        return getRankingAsInteger(ref).intValue();
+    }
+    
+    /**
+     * Returns the service ranking of a service, based on its service reference. If
+     * the service has a property specifying its ranking, that will be returned. If
+     * not, the default ranking of zero will be returned.
+     * 
+     * @param ref the service reference to determine the ranking for
+     * @return the ranking
+     */
+    public static Integer getRankingAsInteger(ServiceReference<?> ref) {
+        Integer rank = (Integer) ref.getProperty(Constants.SERVICE_RANKING);
+        if (rank != null) {
+            return rank;
+        }
+        return new Integer(0);
+    }
+    
+    /**
+     * Returns the service ID of a service, based on its service reference. This
+     * method is aware of service aspects as defined by the dependency manager and
+     * will return the ID of the orginal service if you give it an aspect.
+     * 
+     * @param ref the service reference to determine the service ID of
+     * @return the service ID
+     */
+    public static long getServiceId(ServiceReference<?> ref) {
+        return getServiceIdAsLong(ref).longValue();
+    }
+    
+    /**
+     * Returns the service ID of a service, based on its service reference. This
+     * method is aware of service aspects as defined by the dependency manager and
+     * will return the ID of the orginal service if you give it an aspect.
+     * 
+     * @param ref the service reference to determine the service ID of
+     * @return the service ID
+     */
+    public static Long getServiceIdAsLong(ServiceReference<?> ref) {
+    	return getServiceIdObject(ref);
+    }
+    
+    public static Long getServiceIdObject(ServiceReference<?> ref) {
+        Long aid = (Long) ref.getProperty(DependencyManager.ASPECT);
+        if (aid != null) {
+            return aid;
+        }
+        Long sid = (Long) ref.getProperty(Constants.SERVICE_ID);
+        if (sid != null) {
+            return sid;
+        }
+        throw new IllegalArgumentException("Invalid service reference, no service ID found");
+    }
+
+    /**
+     * Determines if the service is an aspect as defined by the dependency manager.
+     * Aspects are defined by a property and this method will check for its presence.
+     * 
+     * @param ref the service reference
+     * @return <code>true</code> if it's an aspect, <code>false</code> otherwise
+     */
+    public static boolean isAspect(ServiceReference<?> ref) {
+        Long aid = (Long) ref.getProperty(DependencyManager.ASPECT);
+        return (aid != null);
+    }
+    
+    /**
+     * Converts a service reference to a string, listing both the bundle it was
+     * registered from and all properties.
+     * 
+     * @param ref the service reference
+     * @return a string representation of the service
+     */
+    public static String toString(ServiceReference<?> ref) {
+        if (ref == null) {
+            return "ServiceReference[null]";
+        }
+        else {
+            StringBuffer buf = new StringBuffer();
+            Bundle bundle = ref.getBundle();
+            if (bundle != null) {
+                buf.append("ServiceReference[");
+                buf.append(bundle.getBundleId());
+                buf.append("]{");
+            }
+            else {
+                buf.append("ServiceReference[unregistered]{");
+            }
+            buf.append(propertiesToString(ref, null));
+            buf.append("}");
+            return buf.toString();
+        }
+    }
+    
+    /**
+     * Converts the properties of a service reference to a string.
+     * 
+     * @param ref the service reference
+     * @param exclude a list of properties to exclude, or <code>null</code> to show everything
+     * @return a string representation of the service properties
+     */
+    public static String propertiesToString(ServiceReference<?> ref, List<String> exclude) {
+        StringBuffer buf = new StringBuffer();
+        String[] keys = ref.getPropertyKeys();
+        for (int i = 0; i < keys.length; i++) {
+            if (i > 0) { 
+                buf.append(','); 
+            }
+            buf.append(keys[i]);
+            buf.append('=');
+            Object val = ref.getProperty(keys[i]);
+            if (exclude == null || !exclude.contains(val)) {
+                if (val instanceof String[]) {
+                    String[] valArray = (String[]) val;
+                    StringBuffer valBuf = new StringBuffer();
+                    valBuf.append('{');
+                    for (int j = 0; j < valArray.length; j++) {
+                        if (valBuf.length() > 1) {
+                            valBuf.append(',');
+                        }
+                        valBuf.append(valArray[j].toString());
+                    }
+                    valBuf.append('}');
+                    buf.append(valBuf);
+                }
+                else {
+                    buf.append(val.toString());
+                }
+            }
+        }
+        return buf.toString();
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/TemporalServiceDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/TemporalServiceDependencyTest.java
new file mode 100644
index 0000000..eaa4c6b
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/TemporalServiceDependencyTest.java
@@ -0,0 +1,271 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.serviceDependency;
+
+import java.util.Hashtable;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ServiceDependency;
+import org.junit.Assert;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes", "serial"})
+public class TemporalServiceDependencyTest extends TestBase {
+    public void testServiceConsumptionAndIntermittentAvailability() {
+        if (true) return;
+        final DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        TemporalServiceProvider provider = new TemporalServiceProvider(e);
+        Component sp = component(m).impl(provider).provides(TemporalServiceInterface.class.getName()).build();
+        TemporalServiceProvider2 provider2 = new TemporalServiceProvider2(e);
+        Component sp2 = component(m).impl(provider2).provides(TemporalServiceInterface.class.getName()).build();
+        TemporalServiceConsumer consumer = new TemporalServiceConsumer(e);
+        Component sc = component(m).impl(consumer).withSrv(TemporalServiceInterface.class, s->s.timeout(10000)).build();
+        // add the service consumer
+        m.add(sc);
+        // now add the first provider
+        m.add(sp);
+        e.waitForStep(2, 5000);
+        // and remove it again (this should not affect the consumer yet)
+        m.remove(sp);
+        // now add the second provider
+        m.add(sp2);
+        e.step(3);
+        e.waitForStep(4, 5000);
+        // and remove it again
+        m.remove(sp2);
+        // finally remove the consumer
+        m.remove(sc);
+        // ensure we executed all steps inside the component instance
+        e.step(6);
+        m.clear();
+    }
+
+    public void testServiceConsumptionWithCallbackAndIntermittentAvailability() {
+        if (true) return;
+        final DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        TemporalServiceProvider provider = new TemporalServiceProvider(e);
+        Component sp = component(m).impl(provider).provides(TemporalServiceInterface.class.getName()).build();
+        TemporalServiceProvider2 provider2 = new TemporalServiceProvider2(e);
+        Component sp2 = component(m).impl(provider2).provides(TemporalServiceInterface.class.getName()).build();
+        TemporalServiceConsumerWithCallback consumer = new TemporalServiceConsumerWithCallback(e);
+        Component sc = component(m).impl(consumer).withSrv(TemporalServiceInterface.class, srv->srv.cb("add", "remove").timeout(10000)).build();
+            
+        // add the service consumer
+        m.add(sc);
+        // now add the first provider
+        m.add(sp);
+        e.waitForStep(2, 5000);
+        // and remove it again (this should not affect the consumer yet)
+        m.remove(sp);
+        // now add the second provider
+        m.add(sp2);
+        e.step(3);
+        e.waitForStep(4, 5000);
+        // and remove it again
+        m.remove(sp2);
+        // finally remove the consumer
+        m.remove(sc);
+        // Wait for the consumer.remove callback
+        e.waitForStep(6, 5000);
+        // ensure we executed all steps inside the component instance
+        e.step(7);
+        m.clear();
+    }
+
+    // Same test as testServiceConsumptionWithCallbackAndIntermittentAvailability, but the consumer is now
+    // an adapter for the Adaptee interface.
+    public void testFELIX4858_ServiceAdapterConsumptionWithCallbackAndIntermittentAvailability() {
+        if (true) return;
+        final DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        TemporalServiceProvider provider = new TemporalServiceProvider(e);
+        Component sp = component(m).impl(provider).provides(TemporalServiceInterface.class.getName()).build();
+        TemporalServiceProvider2 provider2 = new TemporalServiceProvider2(e);
+        Component sp2 = component(m).impl(provider2).provides(TemporalServiceInterface.class.getName()).build();
+        TemporalServiceConsumerAdapterWithCallback consumer = new TemporalServiceConsumerAdapterWithCallback(e);
+        Component sc = m.createAdapterService(Adaptee.class, null).setImplementation(consumer);
+        ServiceDependency temporalDep = serviceDependency(sc, TemporalServiceInterface.class).timeout(10000).cb("add", "remove").build();
+        sc.add(temporalDep);
+        Component adaptee = component(m).impl(new Adaptee()).provides(Adaptee.class.getName()).build();
+            
+        // add the adapter service consumer
+        m.add(sc);
+        // add the adaptee (the adapter service depends on it)
+        m.add(adaptee);
+        // now add the first provider
+        m.add(sp);
+        e.waitForStep(2, 5000);
+        // and remove it again (this should not affect the consumer yet)
+        m.remove(sp);
+        // now add the second provider
+        m.add(sp2);
+        e.step(3);
+        e.waitForStep(4, 5000);
+        // and remove it again
+        m.remove(sp2);
+        // finally remove the consumer
+        m.remove(sc);
+        // Wait for the consumer.remove callback
+        e.waitForStep(6, 5000);
+        // ensure we executed all steps inside the component instance
+        e.step(7);
+        m.clear();
+    }
+
+    public void testFelix4602_PropagateServiceInvocationException() {
+        if (true) return;
+        final DependencyManager m = getDM();
+        final Ensure ensure = new Ensure();
+        Runnable provider = new Runnable() {
+        	public void run() {
+        		throw new UncheckedException();
+        	}
+        };
+        Hashtable props = new Hashtable();
+        props.put("target", getClass().getSimpleName());
+        Component providerComp = component(m)
+        		.provides(Runnable.class.getName(), props)
+        		.impl(provider).build();
+
+        Object consumer = new Object() {
+        	volatile Runnable m_provider;
+        	@SuppressWarnings("unused")
+            void start() {
+        		try {
+        			ensure.step(1);
+        			m_provider.run();
+        		} catch (UncheckedException e) {
+        			ensure.step(2);
+        		}
+        	}
+        };
+        Component consumerComp = component(m)
+        		.impl(consumer)
+        		.withSrv(Runnable.class, s->s.timeout(5000).filter("(target=" + getClass().getSimpleName() + ")")).build();
+        m.add(consumerComp);
+        m.add(providerComp);
+        ensure.waitForStep(2, 5000);
+        m.clear();
+    }
+    
+    static class UncheckedException extends RuntimeException {    	
+    }
+
+    static interface TemporalServiceInterface {
+        public void invoke();
+    }
+
+    static class TemporalServiceProvider implements TemporalServiceInterface {
+        private final Ensure m_ensure;
+        public TemporalServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke() {
+            m_ensure.step(2);
+        }
+    }
+
+    static class TemporalServiceProvider2 implements TemporalServiceInterface {
+        protected final Ensure m_ensure;
+        public TemporalServiceProvider2(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke() {
+            m_ensure.step(4);
+        }
+    }
+
+    static class TemporalServiceConsumer implements Runnable {
+        protected volatile TemporalServiceInterface m_service;
+        protected final Ensure m_ensure;
+
+        public TemporalServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            m_ensure.step(1);
+            Thread t = new Thread(this);
+            t.start();
+        }
+        
+        public void run() {
+            m_service.invoke();
+            m_ensure.waitForStep(3, 15000);
+            m_service.invoke();
+        }
+        
+        public void destroy() {
+            m_ensure.step(5);
+        }
+    }
+    
+    static class TemporalServiceConsumerWithCallback extends TemporalServiceConsumer {
+        public TemporalServiceConsumerWithCallback(Ensure e) {
+            super(e);
+        }
+        
+        public void add(TemporalServiceInterface service) {
+            m_service = service;
+        }
+        
+        public void remove(TemporalServiceInterface service) {
+            Assert.assertTrue(m_service == service);
+            m_ensure.step(6);
+        }
+    }
+    
+    public static class Adaptee {       
+    }
+       
+    static class TemporalServiceConsumerAdapterWithCallback extends TemporalServiceConsumer {
+        volatile Adaptee m_adaptee;
+        
+        public TemporalServiceConsumerAdapterWithCallback(Ensure e) {
+            super(e);
+        }
+        
+        public void start() {
+            Assert.assertTrue(m_adaptee != null);
+        }
+        
+        public void add(TemporalServiceInterface service) {
+            m_service = service;
+        }
+        
+        public void remove(TemporalServiceInterface service) {
+            Assert.assertTrue(m_service == service);
+            m_ensure.step(6);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/TestBase.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/TestBase.java
new file mode 100644
index 0000000..9599760
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/TestBase.java
@@ -0,0 +1,354 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.itest;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Hashtable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.ComponentExecutorFactory;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.log.LogService;
+
+import junit.framework.TestCase;
+
+/**
+ * Base class for all integration tests.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public abstract class TestBase extends TestCase implements LogService, FrameworkListener {
+    // Default OSGI log service level.
+    protected final static int LOG_LEVEL = LogService.LOG_WARNING;
+    
+    // optional thread pool used by parallel dependency managers
+    private volatile ExecutorService m_threadPool;
+    
+    // flag used to check if the threadpool must be used for a given test.
+    protected volatile boolean m_parallel;
+        
+    // Flag used to check if some errors have been logged during the execution of a given test.
+    private volatile boolean m_errorsLogged;
+
+    // We implement OSGI log service.
+    protected ServiceRegistration logService;
+    
+    // Our bundle context
+    protected BundleContext context;
+
+    // Our dependency manager used to create test components.
+    protected volatile DependencyManager m_dm;
+
+    // The Registration for the DM threadpool.
+    private ServiceRegistration m_componentExecutorFactoryReg;
+
+    public TestBase() {
+    }
+       
+    protected void setParallel() {
+        m_parallel = true;
+    }
+    
+    public void setUp() throws Exception {
+    	warn("Setting up test " + getClass().getName());
+    	context = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+    	Hashtable<String, Object> props = new Hashtable<>();
+    	props.put(Constants.SERVICE_RANKING, new Integer(Integer.MAX_VALUE));
+        logService = context.registerService(LogService.class.getName(), this, props);
+        context.addFrameworkListener(this);
+        m_dm = new DependencyManager(context);
+        if (m_parallel) {
+            warn("Using threadpool ...");
+            m_threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+            m_componentExecutorFactoryReg = context.registerService(ComponentExecutorFactory.class.getName(), 
+                new ComponentExecutorFactory() {
+                    @Override
+                    public Executor getExecutorFor(Component component) {
+                        return m_threadPool;
+                    }
+                },
+                null);
+        }
+    }
+    
+    public void tearDown() throws Exception {
+    	warn("Tearing down test " + getClass().getName());
+    	logService.unregister();
+    	context.removeFrameworkListener(this);
+        clearComponents();
+        if (m_parallel && m_componentExecutorFactoryReg != null) {
+    	    m_componentExecutorFactoryReg.unregister();
+    	    m_threadPool.shutdown();
+            try {
+                m_threadPool.awaitTermination(60, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+            }
+    	}
+        Assert.assertFalse(errorsLogged());
+    }
+        
+    protected DependencyManager getDM() {
+        return m_dm;
+    }
+                
+    protected void clearComponents() {
+        m_dm.clear();
+        warn("All component cleared.");
+    }
+
+    /**
+     * Creates and provides an Ensure object with a name service property into the OSGi service registry.
+     */
+    protected ServiceRegistration register(Ensure e, String name) {
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put("name", name);
+        return context.registerService(Ensure.class.getName(), e, props);
+    }
+
+    /**
+     * Helper method used to stop a given bundle.
+     * 
+     * @param symbolicName
+     *            the symbolic name of the bundle to be stopped.
+     */
+    protected void stopBundle(String symbolicName) {
+        // Stop the test.annotation bundle
+        boolean found = false;
+        for (Bundle b : context.getBundles()) {
+            if (b.getSymbolicName().equals(symbolicName)) {
+                try {
+                    found = true;
+                    b.stop();
+                } catch (BundleException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        if (!found) {
+            throw new IllegalStateException("bundle " + symbolicName + " not found");
+        }
+    }
+
+    /**
+     * Helper method used to start a given bundle.
+     * 
+     * @param symbolicName
+     *            the symbolic name of the bundle to be started.
+     */
+    protected void startBundle(String symbolicName) {
+        // Stop the test.annotation bundle
+        boolean found = false;
+        for (Bundle b : context.getBundles()) {
+            if (b.getSymbolicName().equals(symbolicName)) {
+                try {
+                    found = true;
+                    b.start();
+                } catch (BundleException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        if (!found) {
+            throw new IllegalStateException("bundle " + symbolicName + " not found");
+        }
+    }
+
+    /**
+     * Helper method used to get a given bundle.
+     * 
+     * @param symbolicName
+     *            the symbolic name of the bundle to get.
+     */
+    protected Bundle getBundle(String symbolicName) {
+        for (Bundle b : context.getBundles()) {
+            if (b.getSymbolicName().equals(symbolicName)) {
+                return b;
+            }
+        }
+        throw new IllegalStateException("bundle " + symbolicName + " not found");
+    }
+    
+    /**
+     * Suspend the current thread for a while.
+     * 
+     * @param n
+     *            the number of milliseconds to wait for.
+     */
+    protected void sleep(int ms) {
+        try {
+            Thread.sleep(ms);
+        } catch (InterruptedException e) {
+        }
+    }
+
+    public void log(int level, String message) {
+        checkError(level, null);
+        if (LOG_LEVEL >= level) {
+            System.out.println(getLevel(level) + " - " + Thread.currentThread().getName() + " : " + message);
+        }
+    }
+
+    public void log(int level, String message, Throwable exception) {
+        checkError(level, exception);
+        if (LOG_LEVEL >= level) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : ");
+            sb.append(message);
+            parse(sb, exception);
+            System.out.println(sb.toString());
+        }
+    }
+
+    public void log(ServiceReference sr, int level, String message) {
+        checkError(level, null);
+        if (LOG_LEVEL >= level) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : ");
+            sb.append(message);
+            System.out.println(sb.toString());
+        }
+    }
+
+    public void log(ServiceReference sr, int level, String message, Throwable exception) {
+        checkError(level, exception);
+        if (LOG_LEVEL >= level) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : ");
+            sb.append(message);
+            parse(sb, exception);
+            System.out.println(sb.toString());
+        }
+    }
+
+    protected boolean errorsLogged() {
+        return m_errorsLogged;
+    }
+
+    private void parse(StringBuilder sb, Throwable t) {
+        if (t != null) {
+            sb.append(" - ");
+            StringWriter buffer = new StringWriter();
+            PrintWriter pw = new PrintWriter(buffer);
+            t.printStackTrace(pw);
+            sb.append(buffer.toString());
+            m_errorsLogged = true;
+        }
+    }
+
+    private String getLevel(int level) {
+        switch (level) {
+            case LogService.LOG_DEBUG :
+                return "DEBUG";
+            case LogService.LOG_ERROR :
+                return "ERROR";
+            case LogService.LOG_INFO :
+                return "INFO";
+            case LogService.LOG_WARNING :
+                return "WARN";
+            default :
+                return "";
+        }
+    }
+
+    private void checkError(int level, Throwable exception) {
+        if (level <= LOG_ERROR) {
+            m_errorsLogged = true;
+        }
+        if (exception != null) {
+            m_errorsLogged = true;
+        }
+    }
+
+    public void frameworkEvent(FrameworkEvent event) {
+        int eventType = event.getType();
+        String msg = getFrameworkEventMessage(eventType);
+        int level = (eventType == FrameworkEvent.ERROR) ? LOG_ERROR : LOG_WARNING;
+        if (msg != null) {
+            log(level, msg, event.getThrowable());
+        } else {
+            log(level, "Unknown fwk event: " + event);
+        }
+    }
+
+    private String getFrameworkEventMessage(int event) {
+        switch (event) {
+            case FrameworkEvent.ERROR :
+                return "FrameworkEvent: ERROR";
+            case FrameworkEvent.INFO :
+                return "FrameworkEvent INFO";
+            case FrameworkEvent.PACKAGES_REFRESHED :
+                return "FrameworkEvent: PACKAGE REFRESHED";
+            case FrameworkEvent.STARTED :
+                return "FrameworkEvent: STARTED";
+            case FrameworkEvent.STARTLEVEL_CHANGED :
+                return "FrameworkEvent: STARTLEVEL CHANGED";
+            case FrameworkEvent.WARNING :
+                return "FrameworkEvent: WARNING";
+            default :
+                return null;
+        }
+    }
+
+    protected void warn(String msg, Object ... params) {
+	if (LOG_LEVEL >= LogService.LOG_WARNING) {
+	    log(LogService.LOG_WARNING, params.length > 0 ? String.format(msg, params) : msg);
+	}
+    }
+
+    @SuppressWarnings("unused")
+    protected void info(String msg, Object ... params) {
+	if (LOG_LEVEL >= LogService.LOG_INFO) {
+	    log(LogService.LOG_INFO, params.length > 0 ? String.format(msg, params) : msg);
+	}
+    }
+
+    @SuppressWarnings("unused")
+    protected void debug(String msg, Object ... params) {
+	if (LOG_LEVEL >= LogService.LOG_DEBUG) {
+	    log(LogService.LOG_DEBUG, params.length > 0 ? String.format(msg, params) : msg);
+	}
+    }
+
+    protected void error(String msg, Object ... params) {
+        log(LogService.LOG_ERROR, params.length > 0 ? String.format(msg, params) : msg);
+    }
+
+    protected void error(String msg, Throwable err, Object ... params) {
+        log(LogService.LOG_ERROR, params.length > 0 ? String.format(msg, params) : msg, err);
+    }
+
+    protected void error(Throwable err) {
+        log(LogService.LOG_ERROR, "error", err);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.classpath b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.classpath
new file mode 100644
index 0000000..57c70f3
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="bin" path="src"/>
+	<classpathentry kind="src" output="bin_test" path="test"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.gitignore b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.gitignore
new file mode 100644
index 0000000..90dde36
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.gitignore
@@ -0,0 +1,3 @@
+/bin/
+/bin_test/
+/generated/
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.project b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.project
new file mode 100644
index 0000000..4e58a1c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.apache.felix.dependencymanager.lambda.samples</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.settings/org.eclipse.jdt.core.prefs b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..144c60c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/bnd.bnd
new file mode 100644
index 0000000..bdcf9bc
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/bnd.bnd
@@ -0,0 +1,18 @@
+-buildpath: \
+	org.apache.felix.dependencymanager.lambda;version=latest,\
+	org.apache.felix.dependencymanager;version=latest,\
+	org.apache.felix.gogo.runtime;version=latest,\
+	osgi.core;version=6.0,\
+	osgi.cmpn;version=6.0,\
+	biz.aQute.bnd.annotation
+	
+Bundle-Version: 0.0.0.${tstamp}
+-sub: *.bnd
+-metatype: *
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-DocURL: http://felix.apache.org/documentation/subprojects/apache-felix-dependency-manager.html
+Bundle-Vendor: The Apache Software Foundation
+-runproperties:  \
+	org.apache.felix.dependencymanager.loglevel=2,\
+	org.apache.felix.log.maxSize=100000,\
+	org.apache.felix.log.storeDebug=true
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/build.gradle b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/build.gradle
new file mode 100644
index 0000000..8dc5b97
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/build.gradle
@@ -0,0 +1,3 @@
+ tasks.withType(JavaCompile) {
+  options.compilerArgs << "-parameters"
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/compositefactory.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/compositefactory.bnd
new file mode 100644
index 0000000..bc24ffd
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/compositefactory.bnd
@@ -0,0 +1,2 @@
+Private-Package: org.apache.felix.dm.lambda.samples.compositefactory
+Bundle-Activator: org.apache.felix.dm.lambda.samples.compositefactory.Activator
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/compositefactory.bndrun b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/compositefactory.bndrun
new file mode 100644
index 0000000..3463517
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/compositefactory.bndrun
@@ -0,0 +1,19 @@
+-runfw: org.apache.felix.framework;version='[5.2.0,5.2.0]'
+-runee: JavaSE-1.8
+-runsystemcapabilities: ${native_capability}
+
+-resolve.effective: active;skip:="osgi.service"
+
+-runbundles: \
+	org.apache.felix.gogo.runtime,\
+	org.apache.felix.gogo.shell,\
+	org.apache.felix.gogo.command,\
+	org.apache.felix.log;version=1.0.1,\
+	org.apache.felix.configadmin;version=1.8.8,\
+	org.apache.felix.metatype;version=1.1.2,\
+	org.apache.felix.dependencymanager.lambda.samples.compositefactory;version=latest,\
+	org.apache.felix.dependencymanager;version=4.2.0,\
+	org.apache.felix.dependencymanager.shell;version=4.0.3,\
+	org.apache.felix.dependencymanager.lambda;version=latest
+
+	
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/device.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/device.bnd
new file mode 100644
index 0000000..35349e2
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/device.bnd
@@ -0,0 +1,2 @@
+Private-Package: org.apache.felix.dm.lambda.samples.device
+Bundle-Activator: org.apache.felix.dm.lambda.samples.device.Activator
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/device.bndrun b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/device.bndrun
new file mode 100644
index 0000000..54ea630
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/device.bndrun
@@ -0,0 +1,19 @@
+-runfw: org.apache.felix.framework;version='[5.2.0,5.2.0]'
+-runee: JavaSE-1.8
+-runsystemcapabilities: ${native_capability}
+
+-resolve.effective: active;skip:="osgi.service"
+
+-runbundles: \
+	org.apache.felix.gogo.runtime,\
+	org.apache.felix.gogo.shell,\
+	org.apache.felix.gogo.command,\
+	org.apache.felix.log;version=1.0.1,\
+	org.apache.felix.configadmin;version=1.8.8,\
+	org.apache.felix.metatype;version=1.1.2,\
+	org.apache.felix.dependencymanager.lambda.samples.device;version=latest,\
+	org.apache.felix.dependencymanager;version=4.2.0,\
+	org.apache.felix.dependencymanager.shell;version=4.0.3,\
+	org.apache.felix.dependencymanager.lambda;version=latest
+
+	
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/dictionary.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/dictionary.bnd
new file mode 100644
index 0000000..d1dea14
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/dictionary.bnd
@@ -0,0 +1,2 @@
+Private-Package: org.apache.felix.dm.lambda.samples.dictionary
+Bundle-Activator: org.apache.felix.dm.lambda.samples.dictionary.Activator
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/dictionary.bndrun b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/dictionary.bndrun
new file mode 100644
index 0000000..8d9d16f
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/dictionary.bndrun
@@ -0,0 +1,26 @@
+-runfw: org.apache.felix.framework;version='[5.2.0,5.2.0]'
+-runee: JavaSE-1.8
+-runsystemcapabilities: ${native_capability}
+
+-resolve.effective: active;skip:="osgi.service"
+
+-runbundles: \
+	org.apache.felix.gogo.runtime,\
+	org.apache.felix.gogo.shell,\
+	org.apache.felix.gogo.command,\
+	org.apache.felix.log;version=1.0.1,\
+	org.apache.felix.configadmin;version=1.8.8,\
+	org.apache.felix.metatype;version=1.1.2,\
+	org.apache.felix.dependencymanager.lambda.samples.dictionary;version=latest,\
+	org.apache.felix.dependencymanager;version=4.2.0,\
+	org.apache.felix.dependencymanager.shell;version=4.0.3,\
+	org.apache.felix.dependencymanager.lambda;version=latest,\
+	org.apache.felix.eventadmin;version=1.4.3,\
+	biz.aQute.bndlib;version=2.3.0,\
+	org.apache.felix.webconsole;version=4.2.2,\
+	org.apache.felix.http.api;version=2.3.0,\
+	org.apache.felix.http.servlet-api;version=1.0.0,\
+	org.apache.felix.http.jetty;version="[2.3.0,2.3.0]"
+	
+
+	
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/factory.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/factory.bnd
new file mode 100644
index 0000000..703f6f8
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/factory.bnd
@@ -0,0 +1,2 @@
+Private-Package: org.apache.felix.dm.lambda.samples.factory
+Bundle-Activator: org.apache.felix.dm.lambda.samples.factory.Activator
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/factory.bndrun b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/factory.bndrun
new file mode 100644
index 0000000..245fc91
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/factory.bndrun
@@ -0,0 +1,19 @@
+-runfw: org.apache.felix.framework;version='[5.2.0,5.2.0]'
+-runee: JavaSE-1.8
+-runsystemcapabilities: ${native_capability}
+
+-resolve.effective: active;skip:="osgi.service"
+
+-runbundles: \
+	org.apache.felix.gogo.runtime,\
+	org.apache.felix.gogo.shell,\
+	org.apache.felix.gogo.command,\
+	org.apache.felix.log;version=1.0.1,\
+	org.apache.felix.configadmin;version=1.8.8,\
+	org.apache.felix.metatype;version=1.1.2,\
+	org.apache.felix.dependencymanager.lambda.samples.factory;version=latest,\
+	org.apache.felix.dependencymanager;version=4.2.0,\
+	org.apache.felix.dependencymanager.shell;version=4.0.3,\
+	org.apache.felix.dependencymanager.lambda;version=latest
+
+	
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/future.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/future.bnd
new file mode 100644
index 0000000..4844e29
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/future.bnd
@@ -0,0 +1,2 @@
+Private-Package: org.apache.felix.dm.lambda.samples.future
+Bundle-Activator: org.apache.felix.dm.lambda.samples.future.Activator
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/future.bndrun b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/future.bndrun
new file mode 100644
index 0000000..8745ebd
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/future.bndrun
@@ -0,0 +1,17 @@
+-runfw: org.apache.felix.framework;version='[5.2.0,5.2.0]'
+-runee: JavaSE-1.8
+-runsystemcapabilities: ${native_capability}
+
+-resolve.effective: active;skip:="osgi.service"
+
+-runbundles: \
+	org.apache.felix.gogo.runtime,\
+	org.apache.felix.gogo.shell,\
+	org.apache.felix.gogo.command,\
+	org.apache.felix.log;version=1.0.1,\
+	org.apache.felix.configadmin;version=1.8.8,\
+	org.apache.felix.metatype;version=1.1.2,\
+	org.apache.felix.dependencymanager.lambda.samples.future;version=latest,\
+	org.apache.felix.dependencymanager;version=4.2.0,\
+	org.apache.felix.dependencymanager.shell;version=4.0.3,\
+	org.apache.felix.dependencymanager.lambda;version=latest
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/hello.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/hello.bnd
new file mode 100644
index 0000000..91317f1
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/hello.bnd
@@ -0,0 +1,2 @@
+Private-Package: org.apache.felix.dm.lambda.samples.hello
+Bundle-Activator: org.apache.felix.dm.lambda.samples.hello.Activator
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/hello.bndrun b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/hello.bndrun
new file mode 100644
index 0000000..3cd553d
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/hello.bndrun
@@ -0,0 +1,19 @@
+-runfw: org.apache.felix.framework;version='[5.2.0,5.2.0]'
+-runee: JavaSE-1.8
+-runsystemcapabilities: ${native_capability}
+
+-resolve.effective: active;skip:="osgi.service"
+
+-runbundles: \
+	org.apache.felix.gogo.runtime,\
+	org.apache.felix.gogo.shell,\
+	org.apache.felix.gogo.command,\
+	org.apache.felix.log;version=1.0.1,\
+	org.apache.felix.configadmin;version=1.8.8,\
+	org.apache.felix.metatype;version=1.1.2,\
+	org.apache.felix.dependencymanager.lambda.samples.hello;version=latest,\
+	org.apache.felix.dependencymanager;version=4.2.0,\
+	org.apache.felix.dependencymanager.shell;version=4.0.3,\
+	org.apache.felix.dependencymanager.lambda;version=latest
+
+	
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/.gitignore b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/.gitignore
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/Activator.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/Activator.java
new file mode 100644
index 0000000..2aab3bc
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/Activator.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.compositefactory;
+
+import static java.lang.System.out;
+
+import org.apache.felix.dm.lambda.DependencyManagerActivator;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+
+/**
+ * Creates a "Provider" service. The implementation for this service (ProviderImpl) is
+ * created using a factory class (ProviderFactory) that also creates some other helper classes 
+ * (ProviderComposite1 and ProviderComposite2) that are internally used by ProviderImpl.
+ * 
+ * The ProviderFactory is also injected with a Configuration that can be used by the Factory
+ * when creating the ProviderImpl, ProviderComposite1, and ProviderComposite2 classes.
+ * 
+ * The LogService in only injected to the ProviderImpl and the ProviderComposite1 classes.
+ * Both composites are called in their "start" callbacks, when all required dependencies are available.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Activator extends DependencyManagerActivator {
+    @Override
+    public void activate() throws Exception {
+    	out.println("type \"log info\" to see the logs emitted by this test.");
+
+    	// Create the Factory used to instantiate ProvuderImpl, ProviderComposite1 and ProviderComposite2
+        ProviderFactory factory = new ProviderFactory();
+                
+        // Define the component which implementation is instantiated by the ProviderFactory.
+        // a LogService is injected in the ProviderImpl, as well as to the ProviderComposite1 class.
+        // And a configuration is injected directly to the ProviderFactory so it can use some configurations
+        // before creating the composition of classes.
+        component(comp -> comp
+            .factory(factory::create, factory::getComposition)
+            .start(ProviderImpl::start) // only call start on ProviderImpl          
+            .withSrv(LogService.class, srv -> srv.cb(ProviderImpl::bind).cb(ProviderComposite1::bind))
+            .withCnf(conf -> conf.pid(ProviderFactory.class).cbi(factory::updated)));
+                
+        // Creates a configuration with pid name = "org.apache.felix.dependencymanager.lambda.samples.compositefactory.ProviderFactory"
+        component(comp -> comp
+            .impl(Configurator.class)
+            .withSrv(ConfigurationAdmin.class));
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/Configurator.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/Configurator.java
new file mode 100644
index 0000000..b030616
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/Configurator.java
@@ -0,0 +1,20 @@
+package org.apache.felix.dm.lambda.samples.compositefactory;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class Configurator {
+    volatile ConfigurationAdmin m_cm; // injected by reflection.
+    
+    void start() throws IOException {
+        // Configure the ServiceConsumer component
+        Configuration c = m_cm.getConfiguration(ProviderFactory.class.getName(), null);
+        Dictionary<String, Object> props = new Hashtable<>();
+        props.put("foo", "bar");
+        c.update(props);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/Provider.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/Provider.java
new file mode 100644
index 0000000..75c2773
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/Provider.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.compositefactory;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface Provider {
+
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderComposite1.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderComposite1.java
new file mode 100644
index 0000000..bad0463
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderComposite1.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.compositefactory;
+
+import org.osgi.service.log.LogService;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ProviderComposite1 {
+    private volatile LogService m_log;
+
+    public void bind(LogService log) {
+        m_log = log;
+    }
+
+    void start() {
+        m_log.log(LogService.LOG_INFO, "ProviderParticipant1.start()");
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderComposite2.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderComposite2.java
new file mode 100644
index 0000000..8386244
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderComposite2.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.compositefactory;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ProviderComposite2 {
+
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderFactory.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderFactory.java
new file mode 100644
index 0000000..3b35134
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderFactory.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.compositefactory;
+
+import java.util.Dictionary;
+
+/**
+ * Pojo used to create all the objects composition used to implements the "Provider" Service.
+ * The manager is using a Configuration injected by Config Admin, in order to configure the 
+ * various objects being part of the "Provider" service implementation.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ProviderFactory {
+    private ProviderComposite1 m_composite1;
+    private ProviderComposite2 m_composite2;
+    private ProviderImpl m_providerImpl;
+    @SuppressWarnings("unused")
+	private Dictionary<String, Object> m_conf;
+
+    public void updated(Dictionary<String, Object> conf) {
+        // validate configuration and throw an exception if the properties are invalid
+        m_conf = conf;
+    }
+
+    /**
+     * Builds the composition of objects used to implement the "Provider" service.
+     * The Configuration injected by Config Admin will be used to configure the components
+     * @return The "main" object providing the "Provider" service.
+     */
+    ProviderImpl create() {
+        // Here, we can instantiate our object composition and configure them using the injected Configuration ...
+        m_composite1 = new ProviderComposite1(); // possibly configure this object using our configuration
+        m_composite2 = new ProviderComposite2(); // possibly configure this object using our configuration
+        m_providerImpl = new ProviderImpl(m_composite1, m_composite2);
+        return m_providerImpl; // Main object implementing the Provider service
+    }
+
+    /**
+     * Returns the 
+     * @return
+     */
+    Object[] getComposition() {
+        return new Object[] { m_providerImpl, m_composite1, m_composite2 };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderImpl.java
new file mode 100644
index 0000000..c874d71
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/ProviderImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.compositefactory;
+
+import org.osgi.service.log.LogService;
+
+/**
+ * This is the main implementation for our "Provider" service.
+ * This service is using a composition of two participants, which are used to provide the service
+ * (ProviderParticipant1, and ProviderParticipant2).
+ * 
+ * This class is instantiated by the CompositionManager class.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ProviderImpl implements Provider {
+    private final ProviderComposite1 m_participant1;
+    private final ProviderComposite2 m_participant2;
+    private volatile LogService m_log;
+    
+    public void bind(LogService log) {
+        m_log = log;
+    }
+
+    ProviderImpl(ProviderComposite1 participant1, ProviderComposite2 participant2) {
+        m_participant1 = participant1;
+        m_participant2 = participant2;
+    }
+
+    void start() {
+        m_log.log(LogService.LOG_INFO, "ProviderImpl.start(): participants=" + m_participant1 + "," + m_participant2);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/README b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/README
new file mode 100644
index 0000000..b9ab260
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/compositefactory/README
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+This Activator is an example usage of DM composite components. A composite component is implemented
+using a composition of multiple object instances, which are used to implement a given service.
+
+The sample also uses a Factory approach in order to instantiate the composition of objects: A
+"CompositionManager" is first injected with a Configuration that can possibly be used to create
+and configure all the composites.
+
+Dependencies are injected is some of the component implementation instances, using java8 method references. For instance,
+the LogService is only injected in the ProviderImpl and the ProviderComposite1 class and not in the ProviderComposite2 class.
+
+To see logs, type this command under the gogo shell:
+
+g! log info|grep compositefactory
+
+
+
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/Activator.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/Activator.java
new file mode 100644
index 0000000..978367c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/Activator.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.device;
+
+import static java.lang.System.out;
+
+import org.apache.felix.dm.lambda.DependencyManagerActivator;
+import org.osgi.service.log.LogService;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Activator extends DependencyManagerActivator {
+    @Override
+    public void activate() throws Exception { 
+    	out.println("type \"log info\" to see the logs emitted by this test.");
+
+    	// Create a pair of Device/DeviceParameter service with id=1
+        createDeviceAndParameter(1);
+        
+        // Create a pair of Device/DeviceParameter service with id=2
+        createDeviceAndParameter(2);
+        
+        // Create a DeviceParameter adapter: for each pair of Device/DeviceParameter services having the same id,
+        // a DeviceParameter adapter service will be created.
+        adapter(Device.class, adpt -> adpt.provides(DeviceAccess.class).impl(DeviceAccessImpl.class));
+        
+        // Creates a component that simply displays all available DeviceParameter adapter services.
+        component(comp -> comp
+            .impl(DeviceAccessConsumer.class)
+            .withSrv(LogService.class)
+            .withSrv(DeviceAccess.class, device -> device.cb(DeviceAccessConsumer::add)));       
+    }
+    
+    private void createDeviceAndParameter(int id) {
+        // Creates a Device service with the provided id.
+        component(comp -> comp.factory(() -> new DeviceImpl(id)).provides(Device.class, "device.id", id));
+        
+        // Creates a DeivceParameter with the provided id.
+        component(comp -> comp.factory(() -> new DeviceParameterImpl(id)).provides(DeviceParameter.class, "device.id", id));
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/Device.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/Device.java
new file mode 100644
index 0000000..0e4cf10
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/Device.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.device;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface Device {
+    int getDeviceId();
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceAccess.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceAccess.java
new file mode 100644
index 0000000..f9f0ec4
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceAccess.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.device;
+
+/**
+ * Provides unified access to a pair of Device/DeviceParameter services having the same device ID.
+
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface DeviceAccess {
+    Device getDevice();
+
+    DeviceParameter getDeviceParameter();
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceAccessConsumer.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceAccessConsumer.java
new file mode 100644
index 0000000..1d46839
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceAccessConsumer.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.device;
+
+import java.util.Map;
+
+import org.osgi.service.log.LogService;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DeviceAccessConsumer {
+    volatile LogService log;
+
+    void add(DeviceAccess deviceAccess, Map<String, Object> props) {
+        log.log(LogService.LOG_INFO, "DeviceAccessConsumer: Handling device access: id=" + props.get("device.access.id") 
+            + "\n\t device=" + deviceAccess.getDevice() 
+            + "\n\t device parameter=" + deviceAccess.getDeviceParameter()
+            + "\n\t device access properties=" + props);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceAccessImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceAccessImpl.java
new file mode 100644
index 0000000..9a8e321
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceAccessImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.device;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DeviceAccessImpl implements DeviceAccess {
+    volatile Device device;
+    volatile DeviceParameter deviceParameter;
+
+    void init(Component c) {
+        // Dynamically add an extra dependency on a DeviceParameter.
+    	// Notice that we also add a "device.access.id" service property dynamically.
+                
+        component(c, builder -> builder
+            .properties("device.access.id", device.getDeviceId())
+            .withSrv(DeviceParameter.class, srv -> srv.filter("(device.id=" + device.getDeviceId() + ")")));
+    }
+    
+    @Override
+    public Device getDevice() {
+        return device;
+    }
+
+    @Override
+    public DeviceParameter getDeviceParameter() {
+        return deviceParameter;
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceImpl.java
new file mode 100644
index 0000000..6caacbe
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.device;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DeviceImpl implements Device {
+    final int id;
+
+    public DeviceImpl(int id) {
+        this.id = id;
+    }
+
+    @Override
+    public int getDeviceId() {
+        return id;
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceParameter.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceParameter.java
new file mode 100644
index 0000000..f6efdab
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceParameter.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.device;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface DeviceParameter {
+    int getDeviceId();
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceParameterImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceParameterImpl.java
new file mode 100644
index 0000000..f7b9779
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/DeviceParameterImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.device;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DeviceParameterImpl implements DeviceParameter {
+    final int id;
+
+    public DeviceParameterImpl(int id) {
+        this.id = id;
+    }
+
+    @Override
+    public int getDeviceId() {
+        return id;
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/README b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/README
new file mode 100644
index 0000000..d013c28
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/device/README
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+This is an example showing a Dependency Manager "Adapter" in action. Two kinds of services are
+registered in the registry: some Device, and some DeviceParameter services. For each Device (having
+a given id), there is also a corresponding "DeviceParameter" service, having the same id.
+
+Then a "DeviceAccessImpl" adapter service is defined: it is used to "adapt" the "Device" service to
+a "DeviceAccess" service, which provides the union of each pair of Device/DeviceParameter having the
+same device.id . The adapter also dynamically propagate the service properties of the adapted Device
+service.
+
+So see logs, just type this command under gogo shell:
+
+g! log info|grep device.api
+
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/Activator.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/Activator.java
new file mode 100644
index 0000000..a60db9c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/Activator.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.dictionary;
+
+import static java.lang.System.out;
+
+import org.apache.felix.dm.lambda.DependencyManagerActivator;
+import org.osgi.service.log.LogService;
+import static org.apache.felix.service.command.CommandProcessor.COMMAND_FUNCTION;
+import static org.apache.felix.service.command.CommandProcessor.COMMAND_SCOPE;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Activator extends DependencyManagerActivator {
+    @Override
+    public void activate() throws Exception {
+    	out.println("type \"log info\" to see the logs emitted by this test.");
+
+        // Create the factory configuration for our DictionaryImpl service. An instance of the DictionaryImpl is created for each
+    	// factory configuration that you add from webconsole (using the DictionaryConfiguration factory pid).
+        factoryPidAdapter(adapter -> adapter
+            .impl(DictionaryImpl.class)
+            .provides(DictionaryService.class)
+            .factoryPid(DictionaryConfiguration.class)
+            .propagate()
+            .cb(DictionaryImpl::updated)
+            .withSrv(LogService.class));
+                            
+        // Create the Dictionary Aspect that decorates any registered Dictionary service. For each Dictionary, an instance of the 
+        // DictionaryAspect service is created).
+        aspect(DictionaryService.class, aspect -> aspect
+            .impl(DictionaryAspect.class)
+            .filter("(lang=en)").rank(10)
+            .withCnf(conf -> conf.pid(DictionaryAspectConfiguration.class).cb(DictionaryAspect::addWords))
+            .withSrv(LogService.class));
+                    
+        // Create the SpellChecker component. It depends on all available DictionaryService instances, possibly
+        // decorated by some DictionaryAspects.
+        component(comp -> comp
+            .impl(SpellChecker.class)
+            .provides(SpellChecker.class, COMMAND_SCOPE, "dictionary", COMMAND_FUNCTION, new String[] {"spellcheck"}) 
+            .withSrv(DictionaryService.class)
+            .withSrv(LogService.class));
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryAspect.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryAspect.java
new file mode 100644
index 0000000..1982db5
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryAspect.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless
+ * required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.dictionary;
+
+import java.util.Dictionary;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.osgi.service.log.LogService;
+
+import aQute.bnd.annotation.metatype.Configurable;
+
+/**
+ * This aspect applies to the English DictionaryService, and allows to decorate it with some
+ * custom English words, which are configurable from WebConsole.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DictionaryAspect implements DictionaryService {
+    /**
+     * This is the service this aspect is applying to.
+     */
+    private volatile DictionaryService m_originalDictionary;
+
+    /**
+     * We store all configured words in a thread-safe data structure, because ConfigAdmin may
+     * invoke our updated method at any time.
+     */
+    private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>();
+
+    /**
+     * We'll use the OSGi log service for logging. If no log service is available, then we'll
+     * use a NullObject.
+     */
+    private LogService m_log;
+
+    /**
+     * Defines a configuration dependency for retrieving our english custom words (by default,
+     * our PID is our full class name).
+     */
+    protected void addWords(Dictionary<String, ?> config) {
+        if (config != null) {
+            // We use the bnd "Configurable" helper in order to get an implementation for our DictionaryConfiguration interface.
+            DictionaryConfiguration cnf = Configurable.createConfigurable(DictionaryConfiguration.class, config);
+            m_words.clear();
+            for (String word : cnf.words()) {
+                m_words.add(word);
+            }
+        }
+    }
+
+    /**
+     * Our Aspect Service is starting and is about to be registered in the OSGi regsitry.
+     */
+    protected void start() {
+        m_log.log(LogService.LOG_INFO, "Starting aspect Dictionary with words: " + m_words
+            + "; original dictionary service=" + m_originalDictionary);
+    }
+
+    /**
+     * Checks if a word is found from our custom word list. if not, delegate to the decorated
+     * dictionary.
+     */
+    public boolean checkWord(String word) {
+        m_log.log(LogService.LOG_INFO, "DictionaryAspect: checking word " + word + " (original dictionary="
+            + m_originalDictionary + ")");
+        if (m_words.contains(word)) {
+            return true;
+        }
+        return m_originalDictionary.checkWord(word);
+    }
+
+    public String toString() {
+        return "DictionaryAspect: words=" + m_words + "; original dictionary=" + m_originalDictionary;
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryAspectConfiguration.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryAspectConfiguration.java
new file mode 100644
index 0000000..7b9d10a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryAspectConfiguration.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.dictionary;
+
+import java.util.List;
+
+import aQute.bnd.annotation.metatype.Meta.AD;
+import aQute.bnd.annotation.metatype.Meta.OCD;
+
+/**
+ * This interface describes the configuration for our DictionaryAspect component. We are using the bnd metatype
+ * annotations, allowing to configure our Dictionary Services from web console.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@OCD(name="Spell Checker Dictionary Aspect",
+     description = "Declare here the list of english words to be added into the default english dictionary")
+public interface DictionaryAspectConfiguration {
+    @AD(description = "Dictionary aspect words")
+    List<String> words();
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryConfiguration.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryConfiguration.java
new file mode 100644
index 0000000..12a4cd7
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.dictionary;
+
+import java.util.List;
+
+import aQute.bnd.annotation.metatype.Meta.AD;
+import aQute.bnd.annotation.metatype.Meta.OCD;
+
+/**
+ * This interface describes the configuration for our DictionaryImpl component. We are using the bnd metatype
+ * annotations, allowing to configure our Dictionary Services from web console.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@OCD(name="Spell Checker Dictionary",
+     factory = true, 
+     description = "Declare here some Dictionary instances, allowing to instantiates some DictionaryService services for a given dictionary language")
+public interface DictionaryConfiguration {
+    @AD(description = "Describes the dictionary language", deflt = "en")
+    String lang();
+
+    @AD(description = "Declare here the list of words supported by this dictionary.")
+    List<String> words();
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryImpl.java
new file mode 100644
index 0000000..4167e77
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryImpl.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.dictionary;
+
+import java.util.Dictionary;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.osgi.service.log.LogService;
+
+import aQute.bnd.annotation.metatype.Configurable;
+
+/**
+ * A Dictionary Service, instantiated from webconsole, when you add some configurations instances to the
+ * DictionaryConfiguration factory pid. The Configuration metatype informations is described using the
+ * bnd metatype information (see the DictionaryConfiguration interface).
+ * 
+ * You must configure at least one Dictionary from web console, since the SpellCheck won't start if no Dictionary
+ * Service is available.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DictionaryImpl implements DictionaryService {
+    /**
+     * 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>();
+
+    /**
+     * We'll use the OSGi log service for logging. If no log service is available, then we'll use a NullObject.
+     */
+    private LogService m_log;
+
+    /**
+     * Our Dictionary language.
+     */
+    private String m_lang;
+
+    /**
+     * Our service will be initialized from ConfigAdmin.
+     * @param config The configuration where we'll lookup our words list (key=".words").
+     */
+    protected void updated(Dictionary<String, ?> config) {
+        if (config != null) {
+            // We use the bnd "Configurable" helper in order to get an implementation for our DictionaryConfiguration interface.
+            DictionaryConfiguration cnf = Configurable.createConfigurable(DictionaryConfiguration.class, config);
+
+            m_lang = cnf.lang();
+            m_words.clear();
+            for (String word : cnf.words()) {
+                m_words.add(word);
+            }
+        }
+    }
+
+    /**
+     * A new Dictionary Service is starting (because a new factory configuration has been created
+     * from webconsole).
+     */
+    protected void start() {
+        m_log.log(LogService.LOG_INFO, "Starting Dictionary Service with language: " + m_lang);
+    }
+
+    /**
+     * Check if a word exists if the list of words we have been configured from ConfigAdmin/WebConsole.
+     */
+    public boolean checkWord(String word) {
+        return m_words.contains(word);
+    }
+
+    @Override
+    public String toString() {
+        return "Dictionary: language=" + m_lang + ", words=" + m_words;
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryService.java
new file mode 100644
index 0000000..535210a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/DictionaryService.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.dictionary;
+
+/**
+ * A simple service interface that defines a dictionary service. A dictionary
+ * service simply verifies the existence of a word. 
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface DictionaryService {
+    /**
+     * Check for the existence of a word.
+     * 
+     * @param word the word to be checked.
+     * @return true if the word is in the dictionary, false otherwise.
+     */
+    public boolean checkWord(String word);
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/README b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/README
new file mode 100644
index 0000000..2dda5b8
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/README
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+This sample shows a "SpellChecker" application (using DM API) which provides a
+"dictionary:spellcheck" GOGO shell command. The GOGO "dictionary:spellcheck" command accepts a
+string as parameter, which is checked for proper existence. The SpellChecker class has a
+required/multiple (1..N) dependency over every available "DictionaryService" services, which are
+internally used by the SpellChecker command, when checking word existence.
+
+A DictionaryService is defined using a FactoryConfigurationAdapterService , allowing to instantiate
+many "DictionaryService" instances for each configuration that are added to the
+factory pid "Spell Checker Configuration (api)" from web console.
+The factory pid configuration metatypes are defined using the bnd "metatype" annotations
+(see DictionaryConfiguration.java).
+
+The DictionaryService is decorated with a DictionaryAspect, which you can instantiate by adding a
+configuration to the "Spell Checker Aspect Dictionary (api)" pid from web console. The
+aspect configuration metatype is also declared using the bnd metatype annotations (see
+DictionaryAspectConfiguration.java). 
+
+Before running this sample, go to webconsole, and add some words in the Spell Checker Configuration (api) factory PID, and
+in the Spell Checker Aspect Dictionary (api) PID.
+
+Then go to gogo shell, and type dm help. You will normally see the dictionary:spellcheck command.
+Type dictionary:spellcheck <some words configured either in the spell checker configuration, or in the spell checker aspect configuration, 
+and the dictionary will check for proper word existance in the configuration.
+
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/SpellChecker.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/SpellChecker.java
new file mode 100644
index 0000000..6429643
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/dictionary/SpellChecker.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.dictionary;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.apache.felix.service.command.Descriptor;
+import org.osgi.service.log.LogService;
+
+/**
+ * Felix "spellcheck" Gogo Shell Command. This command allows to check if some given words are valid or not.
+ * This command will be activated only if (at least) one DictionaryService has been injected.
+ * To create a Dictionary Service, you have to go the the web console and add a configuration in the 
+ * "Dictionary Configuration" factory pid.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class SpellChecker {
+    /**
+     * We'll use the OSGi log service for logging. If no log service is available, then we'll use a NullObject.
+     */
+    private volatile LogService m_log;
+
+    /**
+     * We'll store all Dictionaries in a concurrent list, in order to avoid method synchronization.
+     * (Auto-Injected from Activator, at any time). DependencyManager detects that the field is an 
+     * Iterable of a DictionaryService and automatically adds any available DictionaryService, at any time.
+     */
+    private final Iterable<DictionaryService> m_dictionaries = new ConcurrentLinkedQueue<>();
+
+    /**
+     * Lifecycle method callback, used to check if our service has been activated.
+     */
+    protected void start() {
+        m_log.log(LogService.LOG_WARNING, "Spell Checker started");
+    }
+
+    /**
+     * Lifecycle method callback, used to check if our service has been activated.
+     */
+    protected void stop() {
+        m_log.log(LogService.LOG_WARNING, "Spell Checker stopped");
+    }
+
+    // --- Gogo Shell command
+
+    @Descriptor("checks if word is found from an available dictionary")
+    public void spellcheck(@Descriptor("the word to check") String word) {
+        m_log.log(LogService.LOG_INFO, "Checking spelling of word \"" + word + "\" using the following dictionaries: "
+            + m_dictionaries);
+
+        for (DictionaryService dictionary : m_dictionaries) {
+            if (dictionary.checkWord(word)) {
+                System.out.println("word " + word + " is correct");
+                return;
+            }
+        }
+        System.err.println("word " + word + " is incorrect");
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/Activator.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/Activator.java
new file mode 100644
index 0000000..3f4080b
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/Activator.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.factory;
+
+import static java.lang.System.out;
+
+import org.apache.felix.dm.lambda.DependencyManagerActivator;
+import org.osgi.service.log.LogService;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Activator extends DependencyManagerActivator {
+    @Override
+    public void activate() throws Exception {   
+    	out.println("type \"log info\" to see the logs emitted by this test.");
+
+        component(comp -> comp
+            .factory(ProviderFactory::new, ProviderFactory::create)       
+            .provides(Provider.class)
+            .start(ProviderImpl::start)                      
+            .withSrv(LogService.class, log -> log.required().cb(ProviderImpl::set)));
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/Provider.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/Provider.java
new file mode 100644
index 0000000..7b06e63
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/Provider.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.factory;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface Provider {
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/ProviderFactory.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/ProviderFactory.java
new file mode 100644
index 0000000..c90770e
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/ProviderFactory.java
@@ -0,0 +1,7 @@
+package org.apache.felix.dm.lambda.samples.factory;
+
+public class ProviderFactory {
+    public ProviderImpl create() {
+        return new ProviderImpl();
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/ProviderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/ProviderImpl.java
new file mode 100644
index 0000000..220958e
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/ProviderImpl.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.factory;
+
+import org.osgi.service.log.LogService;
+
+/**
+ * This is the main implementation for our "Provider" service.
+ * This service is using a composition of two participants, which are used to provide the service
+ * (ProviderParticipant1, and ProviderParticipant2).
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ProviderImpl implements Provider {
+    private volatile LogService m_log;
+            
+    void set(LogService log) { m_log = log; }
+
+    void start() {
+        m_log.log(LogService.LOG_INFO, "ProviderImpl.start()");
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/README b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/README
new file mode 100644
index 0000000..3093738
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/factory/README
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+This sample is an example usage of DM components that are created using a Factory object. 
+The Factory is defined using java8 method references.
+
+To see logs, type this command under the gogo shell:
+
+g! log info|grep compositefactory
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/Activator.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/Activator.java
new file mode 100644
index 0000000..117af23
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/Activator.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.future;
+
+import static java.lang.System.out;
+
+import org.apache.felix.dm.lambda.DependencyManagerActivator;
+import org.osgi.service.log.LogService;
+
+/**
+ * This examples show how to use the new "Future" dependency available from the dependencymanager-lambda library.
+ * The PageLink component provides the list of available hrefs found from the Felix web site.
+ * The page is downloaded asynchronously using a CompletableFuture, and the component of the PageLinkImpl class
+ * will wait for the completion of the future before start.
+ * 
+ * The interesting thing to look at is located in the PageLinkImpl.init() method.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Activator extends DependencyManagerActivator {
+    /**
+     * Initialize our components using new DM-lambda activator base.
+     */
+    @Override
+    public void activate() throws Exception {
+    	out.println("type \"log info\" to see the logs emitted by this test.");
+    	
+    	// System.setProperty("http.proxyHost","your.http.proxy.host");
+    	// System.setProperty("http.proxyPort", "your.http.proxy.port");
+    	    	
+        // Create the PageLinks service, which asynchronously download the content of the Felix web page.
+    	// The PageLink service will be started once the page has been downloaded (using a CompletableFuture).
+        component(comp -> comp
+            .factory(() -> new PageLinksImpl("http://felix.apache.org/"))
+            .provides(PageLinks.class)
+            .withSrv(LogService.class, log -> log.cb(PageLinksImpl::bind)));
+        
+        // Just wait for the PageLinks service and display all links found from the Felix web site.
+        component(comp -> comp.impl(this).withSrv(PageLinks.class, page -> page.cbi(this::setPageLinks))); 
+    }
+        
+    /**
+     * display all the hrefs (links) found from the Felix web site.
+     */
+    void setPageLinks(PageLinks page) {
+        out.println("Felix site links: " + page.getLinks());
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/PageLinks.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/PageLinks.java
new file mode 100644
index 0000000..37eda50
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/PageLinks.java
@@ -0,0 +1,10 @@
+package org.apache.felix.dm.lambda.samples.future;
+
+import java.util.List;
+
+/**
+ * Service that displays all links found from a given web page.
+ */
+public interface PageLinks {
+    List<String> getLinks();
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/PageLinksImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/PageLinksImpl.java
new file mode 100644
index 0000000..c6e0895
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/PageLinksImpl.java
@@ -0,0 +1,81 @@
+package org.apache.felix.dm.lambda.samples.future;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+import java.util.concurrent.CompletableFuture;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.felix.dm.Component;
+import org.osgi.service.log.LogService;
+
+/**
+ * Provides all hrefs found from a given web page.
+ */
+public class PageLinksImpl implements PageLinks {
+	private LogService m_log;
+	private final static String HREF_PATTERN = "<a\\s+href\\s*=\\s*(\"[^\"]*\"|[^\\s>]*)\\s*>";
+	private List<String> m_links; // web page hrefs (links).
+    private String m_url;
+
+	PageLinksImpl(String url) {
+	    m_url = url;
+	}
+	
+	void bind(LogService log) {
+		m_log = log;
+	}
+	
+	void init(Component c) {
+	    // asynchronously download the content of the URL specified in the constructor.
+	    CompletableFuture<List<String>> futureLinks = CompletableFuture.supplyAsync(() -> download(m_url)) 
+	        .thenApply(this::parseLinks);	       
+
+	    // Add the future dependency so we'll be started once the CompletableFuture "futureLinks" has completed.
+	    component(c, comp -> comp.withFuture(futureLinks, links -> links.cbi(this::setLinks)));
+	}
+	
+	// Called when our future has completed.
+    void setLinks(List<String> links) {
+        m_links = links;
+    }
+    
+	// once our future has completed, our component is started.
+	void start() {
+		m_log.log(LogService.LOG_INFO, "Service starting: number of links found from Felix web site: " + m_links.size());
+	}
+	
+	@Override
+	public List<String> getLinks() {
+		return m_links;
+	}
+
+	private String download(String url) {
+		try (Scanner in = new Scanner(new URL(url).openStream())) {
+			StringBuilder builder = new StringBuilder();
+			while (in.hasNextLine()) {
+				builder.append(in.nextLine());
+				builder.append("\n");
+			}
+			return builder.toString();
+		} catch (IOException ex) {
+			RuntimeException rex = new RuntimeException();
+			rex.initCause(ex);
+			throw rex;
+		}
+	}
+	
+	private List<String> parseLinks(String content) {		 
+		Pattern pattern = Pattern.compile(HREF_PATTERN, Pattern.CASE_INSENSITIVE);
+		Matcher matcher = pattern.matcher(content);
+		List<String> result = new ArrayList<>();
+		while (matcher.find())
+			result.add(matcher.group(1));
+		return result;
+	}
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/README b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/README
new file mode 100644
index 0000000..a72c0f1
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/future/README
@@ -0,0 +1,16 @@
+The purpose of this sample is to show an example usage of the new "CompletableFuture" dependency that has been
+added in the dm-lambda library. CompletableFuture java8 class provides functional operations and promotes an asynchronous event-driven model.
+
+In such model, you can use the new dm-lambda library to add dependencies on asynchronous events using the standard JDK CompletableFuture class.
+
+In this example, the Activator first defines a PageLink component that is used to download a given page from the web. The service then parses 
+the content of the page and returns all available hrefs (links) found from the web page.
+
+The PageLink is initialized with the Felix web site URL, which is asynchronously downloaded from the PageLink::init method, using a CompletableFuture. 
+The CF is then added as a "FutureDependency" in the PageLinkImpl.init() method, and when the CF completes, the PageLinkImpl.start() callback is invoked 
+and the service is registered.
+
+The Activator is then getting injected with the PageLink service, and displays the links (hrefs) found from the Felix web site.
+
+Caution: if you are using a corporate http proxy, you have to fix the Activator in order to configure the ip addr and port number of your
+http proxy.
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/Activator.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/Activator.java
new file mode 100644
index 0000000..e36a7f2
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/Activator.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.hello;
+
+import static java.lang.System.out;
+
+import org.apache.felix.dm.lambda.DependencyManagerActivator;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Activator extends DependencyManagerActivator {
+    @Override
+    public void activate() throws Exception {
+    	out.println("type \"log info\" to see the logs emitted by this test.");
+    	
+    	// Creates a Service Provider
+        component(comp -> comp
+            .impl(ServiceProviderImpl.class)
+            .provides(ServiceProvider.class, property1 -> "value1", property2 -> 123) // property names are deduced from lambda parameter names
+            .start(ServiceProviderImpl::activate)
+            .withSrv(LogService.class, log -> log.cb(ServiceProviderImpl::bind)));
+
+        // Creates a Service Consumer. Notice that if your configuration callback is "updated", you can 
+        // simply use "withCnf(pid)" instead of explicitely providing the method reference.
+        
+        component(comp -> comp
+            .impl(ServiceConsumer.class)
+            .withSrv(LogService.class)
+            .withSrv(ServiceProvider.class, srv -> srv.filter("(property1=value1)")) 
+            .withCnf(conf -> conf.pid(ServiceConsumer.class).cb(ServiceConsumer::updated)));  
+        
+        // Same as above, but using a shorter form of "withCnf" declaration
+//        component(comp -> comp
+//            .impl(ServiceConsumer.class)
+//            .withSrv(LogService.class)
+//            .withSrv(ServiceProvider.class, srv -> srv.filter("(property1=value1)")) 
+//            .withCnf(ServiceConsumer.class));  
+
+        // Creates a component that populates some properties in the Configuration Admin.
+        component(comp -> comp.impl(Configurator.class).withSrv(ConfigurationAdmin.class));
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/Configurator.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/Configurator.java
new file mode 100644
index 0000000..544c7cb
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/Configurator.java
@@ -0,0 +1,20 @@
+package org.apache.felix.dm.lambda.samples.hello;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class Configurator {
+    volatile ConfigurationAdmin m_cm; // injected by reflection.
+    
+    void start() throws IOException {
+        // Configure the ServiceConsumer component
+        Configuration c = m_cm.getConfiguration(ServiceConsumer.class.getName(), null);
+        Dictionary<String, Object> props = new Hashtable<>();
+        props.put("foo", "bar");
+        c.update(props);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/README b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/README
new file mode 100644
index 0000000..d762a3c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/README
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+This sample provides a DM Activator declaring one service consumer and a service provider. The
+ServiceConsumer is also depending on a configuration pid  (see org.apache.felix.dependencymanager.samples.hello.Configurator).
+To see logs, just type this under gogo shell:
+
+g! log info|grep hello.annot
+
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/ServiceConsumer.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/ServiceConsumer.java
new file mode 100644
index 0000000..3762789
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/ServiceConsumer.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.hello;
+
+import java.util.Dictionary;
+
+import org.osgi.service.log.LogService;
+
+/**
+ * Our service consumer. We depend on a ServiceProvider, and on a configuration.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceConsumer {
+    volatile ServiceProvider service;
+    volatile LogService log;
+    Dictionary<?, ?> conf;
+
+    public void updated(Dictionary<String, Object> conf) {
+        this.conf = conf;
+    }
+    
+    public void start() {
+        log.log(LogService.LOG_INFO, "ServiceConsumer.start: calling service.hello()");
+        this.service.hello();
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/ServiceProvider.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/ServiceProvider.java
new file mode 100644
index 0000000..2c34285
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/ServiceProvider.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.hello;
+
+/**
+ * The interface for our service provider.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ServiceProvider {
+    public void hello();
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/ServiceProviderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/ServiceProviderImpl.java
new file mode 100644
index 0000000..221b75c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dm/lambda/samples/hello/ServiceProviderImpl.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.lambda.samples.hello;
+
+import org.osgi.service.log.LogService;
+
+/**
+ * The implementation for our service provider.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceProviderImpl implements ServiceProvider {
+    volatile LogService log;
+
+    void bind(LogService log) { this.log = log; }
+    
+    void activate() {
+        log.log(LogService.LOG_INFO, "ServiceProviderImpl.start");
+    }
+
+    @Override
+    public void hello() {
+        log.log(LogService.LOG_INFO, "ServiceProviderImpl.hello");
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/test/.gitignore b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/test/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/test/.gitignore
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/.classpath b/dependencymanager/org.apache.felix.dependencymanager.lambda/.classpath
new file mode 100644
index 0000000..8c73872
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="bin" path="src"/>
+	<classpathentry kind="src" output="bin_test" path="test"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/.gitignore b/dependencymanager/org.apache.felix.dependencymanager.lambda/.gitignore
new file mode 100644
index 0000000..90dde36
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/.gitignore
@@ -0,0 +1,3 @@
+/bin/
+/bin_test/
+/generated/
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/.project b/dependencymanager/org.apache.felix.dependencymanager.lambda/.project
new file mode 100644
index 0000000..fcd766f
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.apache.felix.dependencymanager.lambda</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda/bnd.bnd
new file mode 100644
index 0000000..eb6ff34
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/bnd.bnd
@@ -0,0 +1,13 @@
+javac.source:          1.8
+javac.target:          1.8
+Bundle-Version: 1.0.0
+-buildpath: \
+	org.apache.felix.dependencymanager;version=latest,\
+	osgi.core;version=6.0,\
+	osgi.cmpn;version=6.0
+Export-Package: \
+	org.apache.felix.dm.lambda,\
+	org.apache.felix.dm.lambda.callbacks
+-runfw: org.apache.felix.framework;version='[4.4.1,4.4.1]'
+-runee: JavaSE-1.8
+Private-Package: org.apache.felix.dm.lambda.impl
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/.gitignore b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/.gitignore
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/BundleAdapterBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/BundleAdapterBuilder.java
new file mode 100644
index 0000000..8a393a1
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/BundleAdapterBuilder.java
@@ -0,0 +1,243 @@
+package org.apache.felix.dm.lambda;
+
+import org.apache.felix.dm.lambda.callbacks.CbBundle;
+import org.apache.felix.dm.lambda.callbacks.CbComponentBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentBundle;
+
+/**
+ * Builds a Dependency Manager bundle adapter. The adapter created by this builder will be applied to any bundle that matches the specified 
+ * bundle state mask and filter condition. For each matching bundle an adapter service will be created based on the adapter implementation class. 
+ * The adapter will be registered with the specified interface and existing properties from the original bundle plus any extra properties 
+ * you supply here. The bundle is injected by reflection in adapter class fields having a Bundle type, or using a callback method that you can 
+ * specify.
+ * 
+ * <p> Example which creates a BundleAdapter service for each started bundle (the bundle is added by reflection on
+ * a class field that has a "Bundle" type):
+ * 
+ * <pre> {@code
+ * public class Activator extends DependencyManagerActivator {
+ *     public void activate() throws Exception { 
+ *       bundleAdapter(adapt -> adapt
+ *           .impl(BundleAdapterImpl.class)
+ *           .provides(BundleAdapter.class)
+ *           .mask(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE));
+ *    }
+ * }
+ * } </pre>
+ * 
+ * Example that creates a BundleAdapter service for each started bundle (the bundle is added using a method reference):
+ * 
+ * <pre> {@code
+ * public class Activator extends DependencyManagerActivator {
+ *     public void activate() throws Exception { 
+ *       bundleAdapter(adapt -> adapt
+ *           .impl(BundleAdapterImpl.class)
+ *           .provides(BundleAdapter.class)
+ *           .mask(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE)
+ *           .cb(BundleAdapterImpl::setBundle));
+ *    }
+ * }
+ * }</pre>
+ *
+ * Example that creates a BundleAdapter service for each started bundle (the bundle is added using a method name):
+ * 
+ * <pre> {@code
+ * public class Activator extends DependencyManagerActivator {
+ *     public void activate() throws Exception { 
+ *       bundleAdapter(adapt -> adapt
+ *           .impl(BundleAdapterImpl.class)
+ *           .provides(BundleAdapter.class)
+ *           .mask(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE)
+ *           .cb("setBundle"));
+ *    }
+ * }
+ * }</pre>
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface BundleAdapterBuilder extends ComponentBuilder<BundleAdapterBuilder> {
+    /**
+     * Sets the bundle state mask to depend on. The OSGi BundleTracker explains this mask in more detail, but
+     * it is basically a mask with flags for each potential state a bundle can be in.
+     * 
+     * @param mask the mask to use
+     * @return this builder
+     */
+    BundleAdapterBuilder mask(int mask);
+    
+    /**
+     * Sets the filter condition to depend on. Filters are matched against the full manifest of a bundle.
+     * 
+     * @param filter the filter condition
+     * @return this builder
+     */
+    BundleAdapterBuilder filter(String filter);
+
+    /**
+     * Sets property propagation. If set to <code>true</code> any bundle manifest properties will be added
+     * to the service properties of the component that has this dependency (if it registers as a service).
+     * 
+     * @param propagate <code>true</code> to propagate the bundle manifest properties
+     * @return this builder
+     */
+    BundleAdapterBuilder propagate(boolean propagate);
+    
+    /**
+     * Enables property propagation. Any bundle manifest properties will be added
+     * to the service properties of the component that has this dependency (if it registers as a service).
+     * 
+     * @return this builder
+     */
+    BundleAdapterBuilder propagate();
+    
+    /**
+     * Sets some <code>callbacks</code> invoked on the component implementation instances. When a bundle state matches the bundle 
+     * adapter filter, then the bundle is injected using the specified callback methods. When you specify one callback, it stands for the "add" callback.
+     * When you specify two callbacks, the first one corresponds to the "add" callback, and the second one to the "remove" callback. When you specify three
+     * callbacks, the first one stands for the "add" callback, the second one for the "change" callback, and the third one for the "remove" callback.
+     * 
+     * @param callbacks a list of callbacks (1 param : "add", 2 params : "add"/remove", 3 params : "add"/"change"/"remove").
+     * @return this builder
+     */
+    BundleAdapterBuilder cb(String ... callbacks);
+    
+    /**
+     * Sets some <code>callback instance</code> methods invoked on a given Object instance. When a bundle state matches the bundle 
+     * adapter filter, then the bundle is injected using the specified callback methods. When you specify one callback, it stands for the "add" callback.
+     * When you specify two callbacks, the first one corresponds to the "add" callback, and the second one to the "remove" callback. 
+     * When you specify three callbacks, the first one stands for the "add" callback, the second one for the "change" callback, and the third one for 
+     * the "remove" callback.
+     * 
+     * @param callbackInstance the Object instance where the callbacks are invoked on
+     * @param callbacks a list of callbacks (1 param : "add", 2 params : "add"/remove", 3 params : "add"/"change"/"remove").
+     * @return this builder
+     */
+    BundleAdapterBuilder cbi(Object callbackInstance, String ... callbacks);
+
+    /**
+     * Sets a <code>callback</code> invoked on a component implementation instance when a bundle is added.
+     * The method reference must point to a Component implementation class method, and take as argument a Bundle.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a bundle is added.
+     * @return this builder
+     */
+    <T> BundleAdapterBuilder cb(CbTypeBundle<T> add);
+    
+    /**
+     * Sets some <code>callbacks</code> invoked on a component implementation instance when a bundle is added/removed.
+     * The method references must point to a Component implementation class method, and take as argument a Bundle.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a bundle is added.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    <T> BundleAdapterBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> remove);
+    
+    /**
+     * Sets some <code>callbacks</code> invoked on a component implementation instance when a bundle is added, changed or removed.
+     * The method references must point to a Component implementation class method, and take as argument a Bundle.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a bundle is added.
+     * @param change the method reference invoked when a bundle has changed.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    <T> BundleAdapterBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> change, CbTypeBundle<T> remove);
+    
+    /**
+     * Sets a <code>callback</code> invoked on a component implementation instance when a bundle is added.
+     * The method reference must point to a Component implementation class method, and take as argument a Component and a Bundle.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a bundle is added.
+     * @return this builder
+     */
+    <T> BundleAdapterBuilder cb(CbTypeComponentBundle<T> add);    
+    
+    /**
+     * Sets some <code>callbacks</code> invoked on a component implementation instance when a bundle is added, or removed.
+     * The method references must point to a Component implementation class method, and take as argument a Component and a Bundle.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a bundle is added.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    <T> BundleAdapterBuilder cb(CbTypeComponentBundle<T> add, CbTypeComponentBundle<T> remove);   
+    
+    /**
+     * Sets some <code>callbacks</code> invoked on a component implementation instance when a bundle is added, changed or removed.
+     * The method references must point to a Component implementation class method, and take as argument a Component and a Bundle.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a bundle is added.
+     * @param change the method reference invoked when a bundle has changed.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    <T> BundleAdapterBuilder cb(CbTypeComponentBundle<T> add, CbTypeComponentBundle<T> change, CbTypeComponentBundle<T> remove);         
+
+    /**
+     * Sets a <code>callback instance</code> invoked on a given Object instance when a bundle is added. 
+     * The method reference must point to an Object instance method, and takes as argument a Bundle parameter.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @return this builder
+     */
+    BundleAdapterBuilder cbi(CbBundle add);
+    
+    /**
+     * Sets some <code>callback instance</code> invoked on a given Object instance when a bundle is added or removed. 
+     * The method references must point to an Object instance method, and take as argument a Bundle parameter.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    BundleAdapterBuilder cbi(CbBundle add, CbBundle remove);
+    
+    /**
+     * Sets some <code>callback instance</code> invoked on a given Object instance when a bundle is added, changed or removed.
+     * The method references must point to an Object instance method, and take as argument a Bundle parameter.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @param change the method reference invoked when a bundle has changed.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    BundleAdapterBuilder cbi(CbBundle add, CbBundle change, CbBundle remove);
+
+    /**
+     * Sets a <code>callback instance</code> invoked on a given Object instance when a bundle is added. 
+     * The method reference must point to an Object instance method, and takes as arguments a Component and a Bundle.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @return this builder
+     */
+    BundleAdapterBuilder cbi(CbComponentBundle add);
+    
+    /**
+     * Sets some <code>callback instance</code> invoked on a given Object instance when a bundle is added or removed. 
+     * The method references must point to an Object instance method, and take as argument a Component and a Bundle.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    BundleAdapterBuilder cbi(CbComponentBundle add, CbComponentBundle remove);
+    
+    /**
+     * Sets some <code>callback instance</code> invoked on a given Object instance when a bundle is added, changed or removed.
+     * The method references must point to an Object instance method, and take as argument a Component and a Bundle.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @param change the method reference invoked when a bundle has changed.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    BundleAdapterBuilder cbi(CbComponentBundle add, CbComponentBundle change, CbComponentBundle remove);
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/BundleDependencyBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/BundleDependencyBuilder.java
new file mode 100644
index 0000000..0c577ba
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/BundleDependencyBuilder.java
@@ -0,0 +1,279 @@
+package org.apache.felix.dm.lambda;
+
+import java.util.Dictionary;
+import java.util.function.Supplier;
+
+import org.apache.felix.dm.BundleDependency;
+import org.apache.felix.dm.lambda.callbacks.CbBundle;
+import org.apache.felix.dm.lambda.callbacks.CbComponentBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentBundle;
+import org.osgi.framework.Bundle;
+
+/**
+ * Builds a Dependency Manager Bundle Dependency. The Dependency is required by default (unlike in the original Dependency Manager API).
+ * 
+ * <p> Example of a Component which tracks a started bundle having a given bundle symbolic name:
+ * 
+ * <pre> {@code
+ * public class Activator extends DependencyManagerActivator {
+ *     public void activate() throws Exception { 
+ *         String BSN = "org.apache.felix.dependencymanager";
+ *         component(comp -> comp
+ *             .impl(MyComponent.class)
+ *             .withBundle(b -> b.mask(Bundle.ACTIVE).filter("(Bundle-SymbolicName=" + BSN + ")").cb(MyComponent::add, MyComponent::remove)));
+ *                  
+ *    }
+ * }
+ * } </pre>
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface BundleDependencyBuilder extends DependencyBuilder<BundleDependency> {
+    /**
+     * Enables auto configuration for this dependency. This means the component implementation (composition) will be
+     * injected with this bundle dependency automatically.
+     * 
+     * @param autoConfig <code>true</code> to enable auto configuration
+     * @return the bundle dependency builder
+     */
+    public BundleDependencyBuilder autoConfig(boolean autoConfig);
+
+    /**
+     * Enables auto configuration for this dependency. This means the component implementation (composition) will be
+     * injected with this bundle dependency automatically.
+     * 
+     * @return the bundle dependency builder
+     */
+    public BundleDependencyBuilder autoConfig();
+
+    /**
+     * Sets the dependency to be required. By default, the dependency is required.
+     * 
+     * @param required <code>true</code> if this bundle dependency is required (true by default).
+     * @return the bundle dependency builder
+     */
+    public BundleDependencyBuilder required(boolean required);
+
+    /**
+     * Sets the dependency to be required.
+     * 
+     * @return the bundle dependency builder
+     */
+    public BundleDependencyBuilder required();
+
+    /**
+     * Sets the bundle to depend on directly.
+     * 
+     * @param bundle the bundle to depend on
+     * @return the bundle dependency builder
+     */
+    public BundleDependencyBuilder bundle(Bundle bundle);
+
+    /**
+     * Sets the filter condition to depend on. Filters are matched against the full manifest of a bundle.
+     * 
+     * @param filter the filter condition
+     * @return the bundle dependency builder
+     */
+    public BundleDependencyBuilder filter(String filter);
+
+    /**
+     * Sets the bundle state mask to depend on. The OSGi BundleTracker explains this mask in more detail, but
+     * it is basically a mask with flags for each potential state a bundle can be in.
+     * 
+     * @param mask the mask to use
+     * @return the bundle dependency builder
+     */
+    public BundleDependencyBuilder mask(int mask);
+
+    /**
+     * Sets property propagation. If set to <code>true</code> any bundle manifest properties will be added
+     * to the service properties of the component that has this dependency (if it registers as a service).
+     * 
+     * @param propagate <code>true</code> to propagate the bundle manifest properties
+     * @return the bundle dependency builder
+     */
+    public BundleDependencyBuilder propagate(boolean propagate);
+    
+    /**
+     * Sets property propagation. any bundle manifest properties will be added
+     * to the service properties of the component that has this dependency (if it registers as a service).
+     * 
+     * @return the bundle dependency builder
+     */
+    public BundleDependencyBuilder propagate();
+    
+    /**
+     * Sets an Object instance and a callback method used to propagate some properties to the provided service properties.
+     * The method will be invoked on the specified object instance and must have one of the following signatures:
+     * <ul><li>Dictionary callback(ServiceReference, Object service) 
+     * <li>Dictionary callback(ServiceReference)
+     * </ul>
+     * @param instance the Object instance which is used to retrieve propagated service properties 
+     * @param method the method to invoke for retrieving the properties to be propagated to the service properties.
+     * @return this service dependency. builder
+     */
+    public BundleDependencyBuilder propagate(Object instance, String method);
+    
+    /**
+     * Sets an Object instance and a callback method used to propagate some properties to the provided service properties.
+     * The method will be invoked on the specified object instance and must have one of the following signatures:
+     * <ul><li>Dictionary callback(ServiceReference, Object service) 
+     * <li>Dictionary callback(ServiceReference)
+     * </ul>
+     * @param instance the Object instance which is used to retrieve propagated service properties 
+     * @return this service dependency. builder
+     */
+    public BundleDependencyBuilder propagate(Supplier<Dictionary<?, ?>> instance);
+
+    /**
+     * Sets some <code>callback</code> methods to invoke on the component instance(s). When a bundle state matches the bundle 
+     * filter, then the bundle is injected using the specified callback methods. When you specify one callback, it stands for the "add" callback.
+     * When you specify two callbacks, the first one corresponds to the "add" callback, and the second one to the "remove" callback. When you specify three
+     * callbacks, the first one stands for the "add" callback, the second one for the "change" callback, and the third one for the "remove" callback.
+     * 
+     * @param callbacks a list of callbacks (1 param: "add", 2 params: "add"/remove", 3 params: "add"/"change"/"remove" callbacks).
+     * @return this builder
+     */
+    BundleDependencyBuilder cb(String ... callbacks);
+    
+    /**
+     * Sets some <code>callback instance</code> methods to invoke on a given Object instance. When a bundle state matches the bundle 
+     * filter, then the bundle is injected using the specified callback methods. When you specify one callback, it stands for the "add" callback.
+     * When you specify two callbacks, the first one corresponds to the "add" callback, and the second one to the "remove" callback. 
+     * When you specify three callbacks, the first one stands for the "add" callback, the second one for the "change" callback, and the third one for 
+     * the "remove" callback.
+     * 
+     * @param callbackInstance the Object instance where the callbacks are invoked on
+     * @param callbacks a list of callbacks (1 param: "add", 2 params: "add/remove", 3 params: "add/change/remove" callbacks).
+     * @return this builder
+     */
+    BundleDependencyBuilder cb(Object callbackInstance, String ... callbacks);
+
+    /**
+     * Sets a <code>callback</code> method reference which is invoked when a bundle is added.
+     * The method reference must point to a Component implementation class method, and take as argument a Bundle.
+     * 
+     * @param <T> the type of the component implementation class on which the callback is invoked on.
+     * @param add the method reference invoked when a bundle is added.
+     * @return this builder
+     */
+    <T> BundleDependencyBuilder cb(CbTypeBundle<T> add);
+    
+    /**
+     * Sets some <code>callback</code> method references which are invoked when a bundle is added, or removed.
+     * The method references must point to a Component implementation class method, and take as argument a Bundle.
+     * 
+     * @param <T> the type of the component implementation class on which the callback is invoked on.
+     * @param add the method reference invoked when a bundle is added.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    <T> BundleDependencyBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> remove);
+    
+    /**
+     * Sets some <code>callback</code> method references which are invoked when a bundle is added, changed or removed.
+     * The method references must point to a Component implementation class method, and take as argument a Bundle.
+     * 
+     * @param <T> the type of the component implementation class on which the callback is invoked on.
+     * @param add the method reference invoked when a bundle is added.
+     * @param change the method reference invoked when a bundle has changed.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    <T> BundleDependencyBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> change, CbTypeBundle<T> remove);
+    
+    /**
+     * Sets a <code>callback</code> method reference which is invoked when a bundle is added.
+     * The method reference must point to a Component implementation class method, and take as argument a Component and a Bundle.
+     * 
+     * @param <T> the type of the component implementation class on which the callback is invoked on.
+     * @param add the method reference invoked when a bundle is added.
+     * @return this builder
+     */
+    <T> BundleDependencyBuilder cb(CbTypeComponentBundle<T> add); 
+    
+    /**
+     * Sets some <code>callback</code> method references which are invoked when a bundle is added, or removed.
+     * The method references must point to a Component implementation class method, and take as argument a Component and a Bundle.
+     * 
+     * @param <T> the type of the component implementation class on which the callback is invoked on.
+     * @param add the method reference invoked when a bundle is added.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    <T> BundleDependencyBuilder cb(CbTypeComponentBundle<T> add, CbTypeComponentBundle<T> remove); 
+    
+    /**
+     * Sets some <code>callback</code> method references which are invoked when a bundle is added, changed or removed.
+     * The method references must point to a Component implementation class method, and take as argument a Component and a Bundle.
+     * 
+     * @param <T> the type of the component implementation class on which the callback is invoked on.
+     * @param add the method reference invoked when a bundle is added.
+     * @param change the method reference invoked when a bundle has changed.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    <T> BundleDependencyBuilder cb(CbTypeComponentBundle<T> add, CbTypeComponentBundle<T> change, CbTypeComponentBundle<T> remove); 
+ 
+    /**
+     * Sets a <code>callback instance</code> method reference which is invoked when a bundle is added. 
+     * The method reference must point to an Object instance method, and takes as argument a Bundle parameter.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @return this builder
+     */
+    BundleDependencyBuilder cbi(CbBundle add);
+    
+    /**
+     * Sets some <code>callback instance</code> method references which are invoked when a bundle is added or removed. 
+     * The method references must point to an Object instance method, and take as argument a Bundle parameter.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    BundleDependencyBuilder cbi(CbBundle add, CbBundle remove);
+    
+    /**
+     * Sets some <code>callback instance</code> method references which are invoked when a bundle is added, changed or removed.
+     * The method references must point to an Object instance method, and take as argument a Bundle parameter.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @param change the method reference invoked when a bundle has changed.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    BundleDependencyBuilder cbi(CbBundle add, CbBundle change, CbBundle remove);
+
+    /**
+     * Sets a <code>callback instance</code> method reference which is invoked when a bundle is added. 
+     * The method reference must point to an Object instance method, and takes as arguments a Component and a Bundle.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @return this builder
+     */
+    BundleDependencyBuilder cbi(CbComponentBundle add);
+    
+    /**
+     * Sets some <code>callback instance</code> method references which are invoked when a bundle is added or removed. 
+     * The method references must point to an Object instance method, and take as argument a Component and a Bundle.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    BundleDependencyBuilder cbi(CbComponentBundle add, CbComponentBundle remove);
+    
+    /**
+     * Sets some <code>callback instance</code> method references which are invoked when a bundle is added, changed or removed.
+     * The method references must point to an Object instance method, and take as argument a Component and a Bundle.
+     * 
+     * @param add the method reference invoked when a bundle is added.
+     * @param change the method reference invoked when a bundle has changed.
+     * @param remove the method reference invoked when a bundle is removed.
+     * @return this builder
+     */
+    BundleDependencyBuilder cbi(CbComponentBundle add, CbComponentBundle change, CbComponentBundle remove);    
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ComponentBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ComponentBuilder.java
new file mode 100644
index 0000000..8ac2366
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ComponentBuilder.java
@@ -0,0 +1,791 @@
+package org.apache.felix.dm.lambda;
+
+import java.util.Dictionary;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.lambda.callbacks.CbComponent;
+import org.apache.felix.dm.lambda.callbacks.CbConsumer;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponent;
+
+/**
+ * Builds a Dependency Manager Component. 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.
+ * 
+ * <p> This interface is also the base interface for extended components like aspects, adapters, etc ...
+ *
+ * <p> Example of a component that depends on a ConfigurationAdmin service. The dependency is injected by reflection
+ * on a class field which type matches the ConfigurationAdmin interface:
+ * 
+ * <pre>{@code
+ * public class Activator extends DependencyManagerActivator {
+ *   public void activate() throws Exception {
+ *       component(comp -> comp.impl(Configurator.class).withSrv(ConfigurationAdmin.class));
+ *   }
+ * }
+ * } </pre>
+ *
+ * @param <B> the type of a builder that may extends this builder interface (aspect/adapter).
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ComponentBuilder<B extends ComponentBuilder<B>> {
+    /**
+     * Configures the component implementation. Can be a class name, or a component implementation object.
+     * 
+     * @param impl the component implementation (a class, or an Object).
+     * @return this builder
+     */
+    B impl(Object impl);   
+    
+    /**
+     * Sets the factory to use to create the implementation. You can specify both the factory class and method to invoke. The method should return the implementation, 
+     * and can use any method to create it. Actually, this can be used together with setComposition to create a composition of instances that work together to implement 
+     * a component. The factory itself can also be instantiated lazily by not specifying an instance, but a Class. 
+     * 
+     * @param factory the factory instance, or the factory class.
+     * @param createMethod the create method called on the factory in order to instantiate the component instance.
+     * @return this builder
+     */
+    B factory(Object factory, String createMethod);
+        
+    /**
+     * Configures a factory that can be used to create this component implementation.
+     * Example: 
+     * 
+     * <pre> {@code
+     * factory(ComponentImpl::new)", or "factory(() -> new ComponentImpl())
+     * }</pre>
+     * 
+     * @param create the factory used to create the component implementation.
+     * @return this builder
+     */
+    B factory(Supplier<?> create);
+    
+    /**
+     * Configures a factory used to create this component implementation using a Factory object and a method in the Factory object.
+     * Example:
+     * 
+     * <pre> {@code
+     * factory(Factory::new, Factory::create)
+     * }</pre>
+     * 
+     * @param <U> the type of the factory returned by the supplier
+     * @param <V> the type of the object that is returned by the factory create method.
+     * @param factory the function used to create the Factory itself
+     * @param create the method reference on the Factory method that is used to create the Component implementation
+     * @return this builder
+     */
+    <U, V> B factory(Supplier<U> factory, Function<U, V> create);
+        
+    /**
+     * Configures a factory used to create this component implementation using a Factory object and a "getComponent" factory method.
+     * the Factory method may then return multiple objects that will be part of this component implementation.
+     * 
+     * Example:
+     * 
+     * <pre> {@code
+     * CompositionManager mngr = new CompositionManager();
+     * ...
+     * factory(mngr::create, mngr::getComposition)
+     * }</pre>
+     * 
+     * @param factory the supplier used to return the main component implementation instance
+     * @param getComposition the supplier that returns the list of instances that are part of the component implementation classes.
+     * @return this builder
+     */
+    B factory(Supplier<?> factory, Supplier<Object[]> getComposition);
+
+    /**
+     * Configures a factory that also returns a composition of objects for this component implemenation.
+     * 
+     * Example:
+     * 
+     * <pre> {@code
+     * factory(CompositionManager::new, CompositionManager::create, CompositionManager::getComposition).
+     * }</pre>
+     * 
+     * Here, the CompositionManager will act as a factory (the create method will return the component implementation object), and the
+     * CompositionManager.getComposition() method will return all the objects that are also part of the component implementation.
+     * 
+     * @param <U> the type of the object returned by the supplier factory
+     * @param factory the function used to create the Factory itself
+     * @param create the Factory method used to create the main component implementation object
+     * @param getComposition the Factory method used to return the list of objects that are also part of the component implementation.
+     * @return this builder
+     */
+    <U> B factory(Supplier<U> factory, Function<U, ?> create, Function<U, Object[]> getComposition);
+
+    /**
+     * Sets the public interfaces under which this component should be registered in the OSGi service registry.
+     * 
+     * @param iface the public interfaces to register in the OSGI service registry.
+     * @return this builder
+     */
+	B provides(Class<?>  iface);
+	
+	/**
+     * Sets the public interface under which this component should be registered in the OSGi service registry.
+     * 
+     * @param iface the public interfaces to register in the OSGI service registry.
+	 * @param name a property name for the provided service
+	 * @param value a property value for the provided service
+	 * @param rest the rest of property name/value pairs.
+	 * @return this builder.
+	 */
+	B provides(Class<?>  iface, String name, Object value, Object ... rest);
+	
+	/**
+     * Sets the public interface under which this component should be registered in the OSGi service registry.
+     * Warning: you can only use this method if you compile your application using the "-parameters" javac option.
+     * 
+     * code example:
+     * 
+     * <pre> {@code
+     *  provides(MyService.class, property1 -> "value1", property2 -> 123);
+     * }</pre>
+     *
+     * @param iface the public interfaces to register in the OSGI service registry.
+	 * @param properties a list of fluent service properties for the provided service. You can specify a list of lambda expression, each one implementing the
+	 * {@link FluentProperties} interface that allows to define a property name using a lambda parameter.
+     * @return this builder.
+	 */
+	B provides(Class<?>  iface, FluentProperties ... properties);
+	
+	/**
+     * Sets the public interface under which this component should be registered in the OSGi service registry.
+     * @param iface the public interfaces to register in the OSGI service registry.
+	 * @param properties the properties for the provided service
+     * @return this builder.
+	 */
+    B provides(Class<?>  iface, Dictionary<?,?> properties);
+    
+    /**
+     * Sets the public interfaces under which this component should be registered in the OSGi service registry.
+     * 
+     * @param ifaces list of services provided by the component.
+     * @return this builder.
+     */
+    B provides(Class<?>[] ifaces);
+    
+    /**
+     * Sets the public interfaces under which this component should be registered in the OSGi service registry.
+     * 
+     * @param ifaces the public interfaces to register in the OSGI service registry.
+     * @param name a property name for the provided service
+     * @param value a property value for the provided service
+     * @param rest the rest of property name/value pairs.
+     * @return this builder.
+     */
+    B provides(Class<?>[] ifaces, String name, Object value, Object ... rest);
+    
+    /**
+     * Sets the public interfaces under which this component should be registered in the OSGi service registry.
+     * Warning: you can only use this method if you compile your application using the "-parameters" javac option. 
+     * code example:
+     * 
+     * <pre> {@code
+     *    provides(new Class[] { MyService.class, MyService2.class }, property1 -> "value1", property2 -> 123);
+     * }</pre>
+     *
+     * @param ifaces the public interfaces to register in the OSGI service registry.
+     * @param properties a list of fluent service properties for the provided service. You can specify a list of lambda expression, each one implementing the
+     * {@link FluentProperties} interface that allows to define a property name using a lambda parameter.
+     * @return this builder.
+     */
+    B provides(Class<?>[] ifaces, FluentProperties ... properties);
+    
+    /**
+     * Sets the public interfaces under which this component should be registered in the OSGi service registry.
+     * @param ifaces the public interfaces to register in the OSGI service registry.
+     * @param properties the properties for the provided service
+     * @return this builder.
+     */
+    B provides(Class<?>[] ifaces, Dictionary<?,?> properties);
+
+    /**
+     * Sets the public interface under which this component should be registered in the OSGi service registry.
+     * 
+     * @param iface the service provided by this component.
+     * @return this builder.
+     */
+    B provides(String iface);
+    
+    /**
+     * Sets the public interface under which this component should be registered in the OSGi service registry.
+     * 
+     * @param iface the public interfaces to register in the OSGI service registry.
+     * @param name a property name for the provided service
+     * @param value a property value for the provided service
+     * @param rest the rest of property name/value pairs.
+     * @return this builder.
+     */
+    B provides(String iface, String name, Object value, Object ... rest);
+    
+    /**
+     * Sets the public interface under which this component should be registered in the OSGi service registry. 
+     * Warning: you can only use this method if you compile your application using the "-parameters" javac option.
+     * code example:
+     * 
+     * <pre> {@code 
+     * provides(MyService.class, property1 -> "value1", property2 -> 123);
+     * }</pre>
+     *
+     * @param iface the public interfaces to register in the OSGI service registry.
+     * @param properties a list of fluent service properties for the provided service. You can specify a list of lambda expression, each one implementing the
+     * {@link FluentProperties} interface that allows to define a property name using a lambda parameter.
+     * @return this builder.
+     */
+    B provides(String iface, FluentProperties ... properties);
+    
+    /**
+     * Sets the public interface under which this component should be registered in the OSGi service registry.
+     * @param iface the public interfaces to register in the OSGI service registry.
+     * @param properties the properties for the provided service
+     * @return this builder.
+     */
+    B provides(String iface, Dictionary<?,?> properties);
+    
+    /**
+     * Sets the public interfaces under which this component should be registered in the OSGi service registry.
+     * 
+     * @param ifaces the list of services provided by the component.
+     * @return this builder.
+     */
+    B provides(String[] ifaces);
+    
+    /**
+     * Sets the public interfaces under which this component should be registered in the OSGi service registry.
+     * 
+     * @param ifaces the public interfaces to register in the OSGI service registry.
+     * @param name a property name for the provided service
+     * @param value a property value for the provided service
+     * @param rest the rest of property name/value pairs.
+     * @return this builder.
+     */
+    B provides(String[] ifaces, String name, Object value, Object ... rest);
+    
+    /**
+     * Sets the public interfaces under which this component should be registered in the OSGi service registry.
+     * Warning: you can only use this method if you compile your application using the "-parameters" javac option.
+     * 
+     * code example:
+     * <pre> {@code 
+     * provides(new Class[] { MyService.class, MyService2.class }, property1 -> "value1", property2 -> 123);
+     * }</pre>
+     * 
+     * @param ifaces the public interfaces to register in the OSGI service registry.
+     * @param properties a list of fluent service properties for the provided service. You can specify a list of lambda expression, each one implementing the
+     * {@link FluentProperties} interface that allows to define a property name using a lambda parameter.
+     * @return this builder.
+     */
+    B provides(String[] ifaces, FluentProperties ... properties);
+    
+    /**
+     * Sets the public interfaces under which this component should be registered in the OSGi service registry.
+     * @param ifaces the public interfaces to register in the OSGI service registry.
+     * @param properties the properties for the provided service
+     * @return this builder.
+     */
+    B provides(String[] ifaces, Dictionary<?,?> properties);
+
+    /**
+     * Sets the component's service properties
+     * @param properties the component's service properties
+     * @return this builder
+     */
+    B properties(Dictionary<?,?> properties);     
+    
+    /**
+     * Sets the components's service properties using varargs. The number of parameters must be even, representing a list of pair property key-value.
+     * 
+     * <pre> {@code 
+     * Example: properties("param1", "value1", "service.ranking", 3)
+     * }</pre>
+     * 
+     * @param name the first property name
+     * @param value the first property value
+     * @param rest the rest of properties key/value pairs.
+     * @return this builder
+     */
+    B properties(String name, Object value, Object ... rest);  
+    
+    /**
+     * Sets the components's service properties using List of lamda properties. 
+     *  
+     * Example: 
+     * 
+     * <pre> {@code
+     *   properties(param1 -> "value1, param2 -> 2);
+     * }</pre>
+     * 
+     * When you use this method, you must compile your source code using the "-parameters" option, and the "arg0" parameter
+     * name is now allowed.
+     * 
+     * @param properties the fluent properties
+     * @return this builder
+     */
+    B properties(FluentProperties ... properties);  
+
+    /**
+     * Adds a required/autoconfig service dependency.
+     * 
+     * @param service the service dependency filter
+     * @param filter the service filter
+     * @return this builder
+     */
+    B withSrv(Class<?> service, String filter);
+
+    /**
+     * Adds in one shot multiple required/autoconfig service dependencies.
+     * @param services the dependencies that are required and that will be injected in any field with the same dependency type.
+     * @return this builder
+     */
+    B withSrv(Class<?> ... services);
+           
+    /**
+     * Adds a service dependency built using a Consumer lambda that is provided with a ServiceDependencyBuilder. 
+     * 
+     * @param <U> the type of the dependency service
+     * @param service the service
+     * @param consumer the lambda for building the service dependency
+     * @return this builder.
+     */
+    <U> B withSrv(Class<U> service, Consumer<ServiceDependencyBuilder<U>> consumer);
+    
+    /**
+     * Adds a configuration dependency.
+     * @param consumer the lambda used to build the configuration dependency.
+     * @return this builder.
+     */
+    B withCnf(Consumer<ConfigurationDependencyBuilder> consumer);     
+    
+    /**
+     * Adds multiple configuration dependencies in one single call. All configurations are injected by default in the "updated" callback.
+     * @param pids list of configuration pids.
+     * @return this builder
+     */
+    @SuppressWarnings("unchecked")
+    default B withCnf(String ... pids) {
+        Stream.of(pids).forEach(pid -> withCnf(cnf -> cnf.pid(pid)));
+        return (B) this;
+    }
+    
+    /**
+     * Adds multiple configuration dependencies in one single call. 
+     * @param pids list of configuration pids
+     * @return this builder
+     */
+    @SuppressWarnings("unchecked")
+    default B withCnf(Class<?> ... pids) {
+        Stream.of(pids).forEach(pid -> withCnf(cnf -> cnf.pid(pid)));
+        return (B) this;
+    }
+
+    /**
+     * Adds a bundle dependency.
+     * @param consumer the lambda used to build the bundle dependency.
+     * @return this builder.
+     */
+    B withBundle(Consumer<BundleDependencyBuilder> consumer);        
+
+    /**
+     * Adds a CompletableFuture dependency.
+     * 
+     * @param <U> the type of the result of the CompletableFuture.
+     * @param future a CompletableFuture on which the dependency will wait for
+     * @param consumer the builder used to build the dependency
+     * @return this builder.
+     */
+    <U> B withFuture(CompletableFuture<U> future, Consumer<FutureDependencyBuilder<U>> consumer);
+    
+    /**
+     * Sets the name of the method used as the "init" callback. This method, when found, is
+     * invoked as part of the life cycle management of the component implementation. 
+     * This method is useful because when it is invoked, all required dependencies defines in the Activator
+     * are already injected, and you can then add more extra dependencies from the init() method.
+     * And once all extra dependencies will be available and injected, then the "start" callback will be invoked.
+     * The dependency manager will look for a method of this name with the following signatures,
+     * in this order:
+     * <ol>
+     * <li>method(Component component)</li>
+     * <li>method()</li>
+     * </ol>
+     * 
+     * @param callback the callback name
+     * @return this builder.
+     */
+    B init(String callback);
+    
+    /**
+     * Sets the name of the method used as the "start" callback. This method, when found, is
+     * invoked as part of the life cycle management of the component implementation. The
+     * dependency manager will look for a method of this name with the following signatures,
+     * in this order:
+     * <ol>
+     * <li>method(Component component)</li>
+     * <li>method()</li>
+     * </ol>
+     * 
+     * @param callback the callback name
+     * @return this builder.
+     */
+    B start(String callback);
+    
+    /**
+     * Sets the name of the method used as the "stop" callback. This method, when found, is
+     * invoked as part of the life cycle management of the component implementation. The
+     * dependency manager will look for a method of this name with the following signatures,
+     * in this order:
+     * <ol>
+     * <li>method(Component component)</li>
+     * <li>method()</li>
+     * </ol>
+     * 
+     * @param callback the callback name
+     * @return this builder.
+     */
+    B stop(String callback);
+    
+    /**
+     * Sets the name of the method used as the "destroy" callback. This method, when found, is
+     * invoked as part of the life cycle management of the component implementation. The
+     * dependency manager will look for a method of this name with the following signatures,
+     * in this order:
+     * <ol>
+     * <li>method(Component component)</li>
+     * <li>method()</li>
+     * </ol>
+     * 
+     * @param callback the callback name
+     * @return this builder.
+     */
+    B destroy(String callback);
+    
+    /**
+     * Sets the name of the methods used as init callback that is invoked on a given Object instance. 
+     * These methods, when found, are invoked on the specified instance as part of the life cycle management 
+     * of the component implementation.
+     * <p>
+     * Specifying an instance means you can create a manager
+     * that will be invoked whenever the life cycle of a component changes and this manager
+     * can then decide how to expose this life cycle to the actual component, offering an
+     * important indirection when developing your own component models.
+     * 
+     * @see #init(String)
+     * @param callbackInstance the instance the callback will be invoked on.
+     * @param callback the callback name
+     * @return this builder.
+     */
+    B init(Object callbackInstance, String callback);
+    
+    /**
+     * Sets the name of the methods used as start callback that is invoked on a given Object instance. 
+     * These methods, when found, are invoked on the specified instance as part of the life cycle management 
+     * of the component implementation.
+     * <p>
+     * Specifying an instance means you can create a manager
+     * that will be invoked whenever the life cycle of a component changes and this manager
+     * can then decide how to expose this life cycle to the actual component, offering an
+     * important indirection when developing your own component models.
+     * 
+     * @see #start(String)
+     * @param callbackInstance the instance the callback will be invoked on.
+     * @param callback the name of the start method
+     * @return this builder.
+     */
+    B start(Object callbackInstance, String callback);
+   
+    /**
+     * Sets the name of the methods used as stop callback that is invoked on a given Object instance. 
+     * These methods, when found, are invoked on the specified instance as part of the life cycle management 
+     * of the component implementation.
+     * <p>
+     * Specifying an instance means you can create a manager
+     * that will be invoked whenever the life cycle of a component changes and this manager
+     * can then decide how to expose this life cycle to the actual component, offering an
+     * important indirection when developing your own component models.
+     * 
+     * @see #stop(String)
+     * @param callbackInstance the instance the callback will be invoked on.
+     * @param callback the name of the stop method
+     * @return this builder.
+     */
+    B stop(Object callbackInstance, String callback);
+  
+    /**
+     * Sets the name of the methods used as destroy callback that is invoked on a given Object instance. 
+     * These methods, when found, are invoked on the specified instance as part of the life cycle management 
+     * of the component implementation.
+     * <p>
+     * Specifying an instance means you can create a manager
+     * that will be invoked whenever the life cycle of a component changes and this manager
+     * can then decide how to expose this life cycle to the actual component, offering an
+     * important indirection when developing your own component models.
+     * 
+     * @see #destroy(String)
+     * @param callbackInstance the instance the callback will be invoked on.
+     * @param callback the name of the destroy method
+     * @return this builder.
+     */
+    B destroy(Object callbackInstance, String callback);
+
+    /**
+     * Sets a method reference used as the "init" callback. This method reference must point to method from one 
+     * of the component instance classes. It is invoked as part of the life cycle management of the component implementation. 
+     * This method is useful because when it is invoked, all required dependencies defines in the Activator
+     * are already injected, and you can then add more extra dependencies from the init() method.
+     * And once all extra dependencies will be available and injected, then the "start" callback will be invoked.
+     * The method does not take any parameters.
+     * 
+     * @param <U> the type of the component class on which the callback is invoked on.
+     * @param callback a method reference must point to method from one of the component instance classes.
+     * @return this builder
+     */
+    <U> B init(CbConsumer<U> callback);
+  
+    /**
+     * Sets a method reference used as the "start" callback. This method reference must point to method from one 
+     * of the component instance classes. This method is invoked as part of the life cycle management of the component implementation. 
+     * 
+     * @param <U> the type of the component class on which the callback is invoked on.
+     * @param callback  a method reference must point to method from one of the component instance classes.
+     * @return this builder.
+     */
+    <U> B start(CbConsumer<U> callback);
+   
+    /**
+     * Sets a method reference used as the "stop" callback. This method reference must point to method from one 
+     * of the component instance classes. This method is invoked as part of the life cycle management of the component implementation. 
+     * 
+     * @param <U> the type of the component class on which the callback is invoked on.
+     * @param callback  a method reference must point to method from one of the component instance classes.
+     * @return this builder.
+     */
+    <U> B stop(CbConsumer<U> callback);
+  
+    /**
+     * Sets a method reference used as the "destroy" callback. This method reference must point to method from one 
+     * of the component instance classes. This method is invoked as part of the life cycle management of the component implementation. 
+     * 
+     * @param <U> the type of the component class on which the callback is invoked on.
+     * @param callback  a method reference must point to method from one of the component instance classes.
+     * @return this builder.
+     */
+    <U> B destroy(CbConsumer<U> callback);
+
+    /**
+     * Sets a method reference used as the "init" callback. This method reference must point to method from one 
+     * of the component instance classes. It is invoked as part of the life cycle management of the component implementation. 
+     * This method is useful because when it is invoked, all required dependencies defines in the Activator
+     * are already injected, and you can then add more extra dependencies from the init() method.
+     * And once all extra dependencies will be available and injected, then the "start" callback will be invoked.
+     * The method takes as argument a Component parameter.
+     * 
+     * @param <U> the type of the component class on which the callback is invoked on.
+     * @param callback a method reference must point to method from one of the component instance classes. The method takes as argument a Component parameter.
+     * @return this builder
+     */
+    <U> B init(CbTypeComponent<U> callback);
+    
+    /**
+     * Sets a method reference used as the "start" callback. This method reference must point to method from one 
+     * of the component instance classes. This method is invoked as part of the life cycle management of the component implementation. 
+     * The method takes as argument a Component parameter.
+     * 
+     * @param <U> the type of the component class on which the callback is invoked on.
+     * @param callback a method reference must point to method from one of the component instance classes. The method takes as argument a Component parameter.
+     * @return this builder.
+     */
+    <U> B start(CbTypeComponent<U> callback);
+  
+    /**
+     * Sets a method reference used as the "stop" callback. This method reference must point to method from one 
+     * of the component instance classes. This method is invoked as part of the life cycle management of the component implementation. 
+     * The method takes as argument a Component parameter.
+     * 
+     * @param <U> the type of the component class on which the callback is invoked on.
+     * @param callback a method reference must point to method from one of the component instance classes. The method takes as argument a Component parameter.
+     * @return this builder.
+     */
+    <U> B stop(CbTypeComponent<U> callback);
+  
+    /**
+     * Sets a method reference used as the "destroy" callback. This method reference must point to method from one 
+     * of the component instance classes. This method is invoked as part of the life cycle management of the component implementation. 
+     * The method takes as argument a Component parameter.
+     * 
+     * @param <U> the type of the component class on which the callback is invoked on.
+     * @param callback a method reference must point to method from one of the component instance classes. The method takes as argument a Component parameter.
+     * @return this builder.
+     */
+    <U> B destroy(CbTypeComponent<U> callback);
+
+    /**
+     * Sets an Object instance method reference used as the "init" callback. It is invoked as part of the life cycle management of the component 
+     * implementation. 
+     * This method is useful because when it is invoked, all required dependencies defines in the Activator
+     * are already injected, and you can then add more extra dependencies from the init() method.
+     * And once all extra dependencies will be available and injected, then the "start" callback will be invoked.
+     * The method does not take any parameters.
+     * 
+     * @param callback an Object instance method reference. The method does not take any parameters.
+     * @return this builder
+     */
+    B initInstance(Runnable callback);
+ 
+    /**
+     * Sets an Object instance method reference used as the "start" callback. This method reference must point to method from one 
+     * of the component instance classes. This method is invoked as part of the life cycle management of the component implementation. 
+     * The method does not take any parameters.
+     *
+     * @param callback an Object instance method reference. The method does not take any parameters.
+     * @return this builder.
+     */
+    B startInstance(Runnable callback);
+  
+    /**
+     * Sets an Object instance method reference used as the "stop" callback. It is invoked as part of the life cycle management of the component 
+     * implementation. 
+     * This method is useful because when it is invoked, all required dependencies defines in the Activator
+     * are already injected, and you can then add more extra dependencies from the init() method.
+     * And once all extra dependencies will be available and injected, then the "start" callback will be invoked.
+     * The method does not take any parameters.
+     * 
+     * @param callback an Object instance method reference. The method does not take any parameters.
+     * @return this builder
+     */
+    B stopInstance(Runnable callback);
+  
+    /**
+     * Sets an Object instance method reference used as the "destroy" callback. It is invoked as part of the life cycle management of the component 
+     * implementation. 
+     * This method is useful because when it is invoked, all required dependencies defines in the Activator
+     * are already injected, and you can then add more extra dependencies from the init() method.
+     * And once all extra dependencies will be available and injected, then the "start" callback will be invoked.
+     * The method does not take any parameters.
+     * 
+     * @param callback an Object instance method reference. The method does not take any parameters.
+     * @return this builder
+     */
+    B destroyInstance(Runnable callback);
+
+    /**
+     * Sets an Object instance method reference used as the "init" callback. It is invoked as part of the life cycle management of the component 
+     * implementation. 
+     * This method is useful because when it is invoked, all required dependencies defines in the Activator
+     * are already injected, and you can then add more extra dependencies from the init() method.
+     * And once all extra dependencies will be available and injected, then the "start" callback will be invoked.
+     * The method takes as argument a Component parameter.
+     * 
+     * @param callback an Object instance method reference.
+     * @return this builder
+     */
+    B initInstance(CbComponent callback);
+   
+    /**
+     * Sets an Object instance method reference used as the "start" callback. This method reference must point to method from one 
+     * of the component instance classes. This method is invoked as part of the life cycle management of the component implementation. 
+     * The method takes as argument a Component parameter.
+     *
+     * @param callback an Object instance method reference. The method takes as argument a Component parameter.
+     * @return this builder.
+     */
+    B startInstance(CbComponent callback);
+    
+    /**
+     * Sets an Object instance method reference used as the "stop" callback. This method reference must point to method from one 
+     * of the component instance classes. This method is invoked as part of the life cycle management of the component implementation. 
+     * The method takes as argument a Component parameter.
+     *
+     * @param callback an Object instance method reference. The method takes as argument a Component parameter.
+     * @return this builder.
+     */
+    B stopInstance(CbComponent callback);
+  
+    /**
+     * Sets an Object instance method reference used as the "destroy" callback. This method reference must point to method from one 
+     * of the component instance classes. This method is invoked as part of the life cycle management of the component implementation. 
+     * The method takes as argument a Component parameter.
+     *
+     * @param callback an Object instance method reference. The method takes as argument a Component parameter.
+     * @return this builder.
+     */
+    B destroyInstance(CbComponent callback);
+
+    /**
+     * Configures OSGi object (BundleContext, Component, etc ...) that will be injected in any field having the same OSGi object type.
+     * @param clazz the OSGi object type (BundleContext, Component, DependencyManager).
+     * @param autoConfig true if the OSGi object has to be injected, false if not
+     * @return this builder
+     */
+    B autoConfig(Class<?> clazz, boolean autoConfig); 
+    
+    /**
+     * Configures OSGi object (BundleContext, Component, etc ...) that will be injected in a given field.
+     * @param clazz the OSGi object type (BundleContext, Component, DependencyManager).
+     * @param field the field that will be injected with the OSGI object
+     * @return this builder
+     */
+    B autoConfig(Class<?> clazz, String field);
+    
+    /**
+     * Activates debug mode
+     * @param label the debug label
+     * @return this builder
+     */
+    B debug(String label);
+    
+    /**
+     * Automatically adds this component to its DependencyManager object. When a lambda builds a Component using this builder, by default
+     * the built component is auto added to its DependencyManager object, unless you invoke autoAdd(false).
+     * 
+     * @param autoAdd true for automatically adding this component to the DependencyManager object, false if not
+     * @return this builder
+     */
+    B autoAdd(boolean autoAdd);
+    
+    /**
+     * Sets the method to invoke on the service implementation to get back all
+     * instances that are part of a composition and need dependencies injected.
+     * All of them will be searched for any of the dependencies. The method that
+     * is invoked must return an <code>Object[]</code>.
+     * 
+     * @param getCompositionMethod the method to invoke
+     * @return this builder
+     */
+    B composition(String getCompositionMethod);
+    
+    /**
+     * Sets the instance and method to invoke to get back all instances that
+     * are part of a composition and need dependencies injected. All of them
+     * will be searched for any of the dependencies. The method that is
+     * invoked must return an <code>Object[]</code>.
+     * 
+     * @param instance the instance that has the method
+     * @param getCompositionMethod the method to invoke
+     * @return this builder
+     */
+    B composition(Object instance, String getCompositionMethod);
+
+    /**
+     * Sets a java8 method reference to a Supplier that returns all instances that are part of a composition and need dependencies injected.
+     * All of them will be searched for any of the dependencies. The method that
+     * is invoked must return an <code>Object[]</code>.
+     * 
+     * @param getCompositionMethod the method to invoke
+     * @return this builder
+     */
+    B composition(Supplier<Object[]> getCompositionMethod);
+
+    /**
+     * Builds the real DependencyManager Component.
+     * @return the real DependencyManager Component.
+     */
+    Component build();
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ConfigurationDependencyBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ConfigurationDependencyBuilder.java
new file mode 100644
index 0000000..c91a7fd
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ConfigurationDependencyBuilder.java
@@ -0,0 +1,129 @@
+package org.apache.felix.dm.lambda;
+
+import org.apache.felix.dm.ConfigurationDependency;
+import org.apache.felix.dm.lambda.callbacks.CbComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeDictionary;
+
+/**
+ * Builds a Dependency Manager Configuration Dependency.
+ * By default, the updated callback is "updated", like in original DM API.
+ * 
+ * <p> Code example with a component that defines a Configuration Dependency. the ServiceImpl modified method
+ * callback is declared using a method reference (see the "cb(ServiceImpl::modified)" code):
+ * 
+ * <pre> {@code
+ * public class Activator extends DependencyManagerActivator {
+ *     public void activate() throws Exception { 
+ *         component(comp -> comp
+ *           .impl(ServiceImpl.class)
+ *           .withConf(conf -> conf.pid(ServiceConsumer.class).cb(ServiceImpl::modified)));  
+ *    }
+ * }
+ * }</pre>
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ConfigurationDependencyBuilder extends DependencyBuilder<ConfigurationDependency> { 
+    /**
+     * Sets the pid for this configuration dependency.
+     * 
+     * @param pid the configuration dependendency pid.
+     * @return this builder
+     */
+    ConfigurationDependencyBuilder pid(String pid);
+    
+    /**
+     * Sets the class which fqdn represents the pid for this configuration dependency. Usually, this class can optionally be annotated with metatypes bnd annotations.
+     * 
+     * @param pidClass the class which fqdn represents the pid for this configuration dependency.
+     * @return this builder
+     */
+    ConfigurationDependencyBuilder pid(Class<?> pidClass);
+    
+    /**
+     * Sets propagation of the configuration properties to the service properties (false by default). 
+     * All public configuration properties (not starting with a dot) will be propagated to the component service properties.
+     * 
+     * @return this builder
+     */
+    ConfigurationDependencyBuilder propagate();
+    
+    /**
+     * Sets propagation of the configuration properties to the service properties (false by default).
+     * 
+     * @param propagate true if all public configuration properties (not starting with a dot) must be propagated to the component service properties (false by default)
+     * @return this builder
+     */
+    ConfigurationDependencyBuilder propagate(boolean propagate);
+    
+    /**
+     * Configures whether or not the component instance should be instantiated at the time the updated callback is invoked. 
+     * By default, when the callback is applied on an external object instance, the component is not instantiated, but in this case
+     * you can force the creation of the component instances by calling this method.
+     * 
+     * @param needsInstance true if the component instance should be instantiated at the time the updated callback is invoked on an external object instance.
+     * @return this builder
+     */
+    ConfigurationDependencyBuilder needsInstance(boolean needsInstance);
+    
+    /**
+     * Sets a <code>callback</code> to call on the component instance(s) when the configuration is updated.
+     * 
+     * @param updateMethod the callback to call on the component instance(s) when the configuration is updated.
+     * @return this builder
+     */
+    ConfigurationDependencyBuilder cb(String updateMethod);
+    
+    /**
+     * Sets a <code>callback instance</code> to call on a given object instance when the configuration is updated.
+     * When the updated method is invoked, the Component implementation has not yet been instantiated, unless you have called
+     * the @link {@link #needsInstance(boolean)} method with "true".
+     * 
+     * @param callbackInstance the object instance on which the updatedMethod is invoked
+     * @param updateMethod the callback to call on the callbackInstance when the configuration is updated.
+     * @return this builder
+     */
+    ConfigurationDependencyBuilder cbi(Object callbackInstance, String updateMethod);
+
+    /**
+     * Sets a <code>callback</code> method reference used to invoke an update method. The method reference must point to a method from one of the component
+     * implementation classes, and is invoked when the configuration is updated.
+     *
+     * @param <T> the type of the component implementation class on which the callback is invoked on.
+     * @param callback the callback method reference which must point to a method from one of the component implementation classes. The method
+     * takes as argument a Dictionary.
+     * @return this builder
+     */
+    <T> ConfigurationDependencyBuilder cb(CbTypeDictionary<T> callback);
+    
+    /**
+     * Sets the <code>callback</code> method reference used to invoke an update method. The method reference must point to a method from one of the 
+     * component implementation classes, and is invoked when the configuration is updated.
+     *
+     * @param <T> the type of the component implementation class on which the callback is invoked on.
+     * @param callback the callback method reference used to invoke an update method on the component instance(s) when the configuration is updated.
+     * The method takes as argument a Component and a Dictionary.
+     * @return this builder
+     */
+    <T> ConfigurationDependencyBuilder cb(CbTypeComponentDictionary<T> callback);
+  
+    /**
+     * Sets a <code>callback instance</code> method reference used to invoke the update method. The method reference must point to an Object instance 
+     * method which takes as argument a Dictionary.
+     * 
+     * @param updated a method reference that points to an Object instance method which takes as argument a Dictionary.
+     * @return this builder
+     */
+    ConfigurationDependencyBuilder cbi(CbDictionary updated);   
+
+    /**
+     * Sets a <code>callback instance</code> method reference used to invoke the update method. The method reference must point to an Object instance method 
+     * which takes as argument a Component and a Dictionary.
+     * 
+     * @param updated a method reference that points to an Object instance method which takes as argument a Component and a Dictionary.
+     * @return this builder
+     */
+    ConfigurationDependencyBuilder cbi(CbComponentDictionary updated);   
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/DependencyBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/DependencyBuilder.java
new file mode 100644
index 0000000..cf0fb10
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/DependencyBuilder.java
@@ -0,0 +1,15 @@
+package org.apache.felix.dm.lambda;
+
+import org.apache.felix.dm.Dependency;
+
+/**
+ * Base class for all dependency builders
+ * @param <T> the dependency type.
+ */
+public interface DependencyBuilder<T extends Dependency> {
+	/**
+	 * Builds a DependencyManager dependency. 
+	 * @return a real DependencyManager dependency
+	 */
+    T build();
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/DependencyManagerActivator.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/DependencyManagerActivator.java
new file mode 100644
index 0000000..ae511e5
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/DependencyManagerActivator.java
@@ -0,0 +1,424 @@
+package org.apache.felix.dm.lambda;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.lambda.impl.BundleAdapterBuilderImpl;
+import org.apache.felix.dm.lambda.impl.BundleDependencyBuilderImpl;
+import org.apache.felix.dm.lambda.impl.CompletableFutureDependencyImpl;
+import org.apache.felix.dm.lambda.impl.ComponentBuilderImpl;
+import org.apache.felix.dm.lambda.impl.ConfigurationDependencyBuilderImpl;
+import org.apache.felix.dm.lambda.impl.FactoryPidAdapterBuilderImpl;
+import org.apache.felix.dm.lambda.impl.ServiceAdapterBuilderImpl;
+import org.apache.felix.dm.lambda.impl.ServiceAspectBuilderImpl;
+import org.apache.felix.dm.lambda.impl.ServiceDependencyBuilderImpl;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Defines a base for Activators in order to build DependencyManager Components using a java8 style.<p>
+ * 
+ * Code example using auto configured fields:
+ * 
+ * <pre> {@code
+ * 
+ * import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.*;
+ *
+ * public class Activator extends DependencyManagerActivator {    
+ *     public void activate() throws Exception {
+ *         component(comp -> comp
+ *             .provides(Service.class, property -> "value")
+ *             .impl(ServiceImpl.class)            
+ *             .withSrv(LogService.class, ConfigurationAdmni.class) // both services are required and injected in class fields with compatible types.           
+ *     }
+ * }
+ * }</pre>
+ *
+ * Code example using reflection callbacks:
+ * 
+ * <pre> {@code
+ * import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.*;
+ *
+ * public class Activator extends DependencyManagerActivator {    
+ *     public void activate() throws Exception {
+ *         component(comp -> comp
+ *             .provides(Service.class, property -> "value")
+ *             .impl(ServiceImpl.class)            
+ *             .withSrv(LogService.class, log -> log.cb("setLog"))              
+ *             .withSrv(ConfigurationAdmni.class, cm -> cm.cb("setConfigAdmin")))                
+ *     }
+ * }
+ * }</pre>
+ *
+ * Code example using method references:
+ * 
+ * <pre> {@code
+ * import static org.apache.felix.dm.lambda.DependencyActivatorBase.*;
+ *
+ * public class Activator extends DependencyManagerActivator {    
+ *     public void activate() throws Exception {
+ *         component(comp -> comp
+ *             .provides(Service.class, property -> "value")
+ *             .impl(ServiceImpl.class)            
+ *             .withSrv(LogService.class, log -> log.cb(ServiceImpl::setLog))              
+ *             .withSrv(ConfigurationAdmni.class, cm -> cm.cb(ServiceImpl::setConfigAdmin)))                
+ *     }
+ * }
+ * }</pre>
+ */
+public abstract class DependencyManagerActivator implements BundleActivator {    
+	/**
+	 * DependencyManager object used to create/register real DM Components that are built by this activator.
+	 */
+    protected DependencyManager m_manager;
+    
+    /**
+     * Bundle Context asociated to the activator bundle.
+     */
+    protected BundleContext m_ctx;
+
+    /**
+     * Our Activator is starting.
+     */
+    @Override
+    public void start(BundleContext context) throws Exception {
+        m_manager = new DependencyManager(context);
+        m_ctx = context;
+        activate();
+    }
+
+    /**
+     * Our Activator is stopped.
+     */
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        deactivate();
+    }
+
+    /**
+     * Sub classes must override this method in order to build some DM components.
+     * @throws Exception if the activation fails
+     */
+    protected abstract void activate() throws Exception;
+
+    /**
+     * Sub classes may override this method that is called when the Activator is stopped.
+     * @throws Exception if the deactivation fails
+     */
+    protected void deactivate() throws Exception {
+    }
+    
+    /**
+     * Returns the DependencyManager used to create/managed DM Components.
+     * 
+     * @return the DependencyManager associated to this Activator
+     */
+    protected DependencyManager getDependencyManager() {
+        return m_manager;
+    }
+    
+    /**
+     * Returns the bundle context that is associated with this bundle.
+     * 
+     * @return the bundle context
+     */
+    protected BundleContext getBundleContext() {
+        return m_ctx;
+    }
+    
+    /**
+     * Creates a Component builder that can be used to create a DM Component. 
+     * @return a Component builder that can be used to create a DM Component.
+     */
+    protected ComponentBuilder<?> component() {
+        return new ComponentBuilderImpl(m_manager);
+    }
+    
+    /**
+     * Creates a service Aspect builder that can be used to create a DM Aspect Component.
+     * 
+     * @param <T> the aspect service type
+     * @param aspectType the aspect service
+     * @return a service Aspect builder.
+     */
+    protected <T> ServiceAspectBuilder<T> aspect(Class<T> aspectType) {
+        ServiceAspectBuilderImpl<T> aspectBuilder = new ServiceAspectBuilderImpl<>(m_manager, aspectType);
+        return aspectBuilder;
+    }
+    
+    /**
+     * Creates a service Adapter builder that can be used to create a DM Adapter Component. 
+     *
+     * @param <T> the adapted service type.
+     * @param adaptee the adapted service
+     * @return a service Adapter builder.
+     */
+    protected <T> ServiceAdapterBuilder<T> adapter(Class<T> adaptee) {
+        ServiceAdapterBuilderImpl<T> adapterBuilder = new ServiceAdapterBuilderImpl<>(m_manager, adaptee);
+        return adapterBuilder;
+    }
+    
+    /**
+     * Builds a DM Component using a Java8 style ComponentBuilder.
+     * @param consumer the lambda that will use the ComponentBuilder for building the DM component. 
+     * The component is auto-added to the DependencyManager, unless the lambda calls the ComponentBuilder.autoAdd(false) method.
+     * @return a newly built DM component.
+     */
+    protected Component component(Consumer<ComponentBuilder<?>> consumer) {
+        return component(m_manager, consumer);
+    }
+        
+    /**
+     * Builds a DM Aspect Component using a Java8 style AspectBuilder.
+     * The component is auto-added to the DependencyManager, unless the lambda calls the AspectBuilder.autoAdd(false) method.
+     *
+     * @param <T> the aspect service type
+     * @param aspect the aspect service
+     * @param consumer the lambda that will use the AspectBuilder for building the DM aspect component. 
+     * @return the DM component build by the consumer of the aspect builder
+     */
+    protected <T> Component aspect(Class<T> aspect, Consumer<ServiceAspectBuilder<T>> consumer) {
+        return aspect(m_manager, aspect, consumer);
+    }
+
+    /**
+     * Builds a DM Adapter Component using a Java8 style AdapterBuilder.
+     * The component is auto-added to the DependencyManager, unless the lambda calls the AdapterBuilder.autoAdd(false) method.
+     * 
+     * @param <T> the adapted service type
+     * @param adaptee the adapted service
+     * @param consumer the lambda that will use the AdapterBuilder for building the DM adapter component. 
+     * @return a newly built DM component.
+     */
+    protected <T> Component adapter(Class<T> adaptee, Consumer<ServiceAdapterBuilder<T>> consumer) {
+        return adapter(m_manager, adaptee, consumer);
+    }
+    
+    /**
+     * Builds a DM Factory Configuration Adapter Component using a Java8 style FactoryPidAdapterBuilder.
+     * The component is auto-added to the DependencyManager, unless the lambda calls the FactoryPidAdapterBuilder.autoAdd(false) method.
+     *
+     * @param consumer the lambda that will use the FactoryPidAdapterBuilder for building the DM factory configuration adapter component. 
+     * @return a newly built DM component.
+     */
+    protected Component factoryPidAdapter(Consumer<FactoryPidAdapterBuilder> consumer) {
+        return factoryPidAdapter(m_manager, consumer);
+    }
+
+    /**
+     * Builds a DM Bundle Adapter Component.
+     * @param consumer the lambda used to build the actual bundle adapter. 
+     * The component is auto-added to the DependencyManager, unless the lambda calls the BundleAdapter.autoAdd(false) method.
+     * @return a newly built DM component.
+     */
+    protected Component bundleAdapter(Consumer<BundleAdapterBuilder> consumer) {
+        return bundleAdapter(m_manager, consumer);
+    }
+       
+    // These static methods can be used when building DM components outside of an activator.
+	
+    /**
+     * Creates a Component builder that can be used to create a Component. 
+     * 
+     * @param dm the DependencyManager object used to create the component builder
+     * @return a Component builder that can be used to create a Component.
+     */
+    public static ComponentBuilder<?> component(DependencyManager dm) {
+        return new ComponentBuilderImpl(dm);
+    }
+    
+    /**
+     * Creates a service Aspect builder that can be used to create an Aspect Component. 
+     *
+     * @param <T> the aspect service type
+     * @param dm the DependencyManager object used to register the built component
+     * @param aspect the type of the aspect service
+     * @return a service Aspect builder that can be used to create an Aspect Component.
+     */
+    public static <T> ServiceAspectBuilder<T> aspect(DependencyManager dm, Class<T> aspect) {
+        ServiceAspectBuilderImpl<T> aspectBuilder = new ServiceAspectBuilderImpl<>(dm, aspect);
+        return aspectBuilder;
+    }
+    
+    /**
+     * Creates a service Adapter builder that can be used to create an Adapter Component.
+     * 
+     * @param <T> the adapted service type
+     * @param dm the DependencyManager object used to register the built component
+     * @param adaptee the type of the adaptee service
+     * @return a service Adapter builder that can be used to create an Adapter Component.
+     */
+    public static <T> ServiceAdapterBuilder<T> adapter(DependencyManager dm, Class<T> adaptee) {
+        ServiceAdapterBuilderImpl<T> adapterBuilder = new ServiceAdapterBuilderImpl<>(dm, adaptee);
+        return adapterBuilder;
+    }
+
+    /**
+     * Creates a factory pid adapter that can be used to create a factory adapter Component. 
+     * @param dm the DependencyManager object used to register the built component
+     * @return a factory pid adapter that can be used to create a factory adapter Component. 
+     */
+    public static FactoryPidAdapterBuilder factoryPidAdapter(DependencyManager dm) {
+        return new FactoryPidAdapterBuilderImpl(dm);
+    }
+   
+    /**
+     * Creates a bundle adapter builder that can be used to create a DM bundle adapter Component. 
+     *
+     * @param dm the DependencyManager object used to create the bundle adapter builder.
+     * @return a bundle adapter builder that can be used to create a DM bundle adapter Component.
+     */
+    public static BundleAdapterBuilder bundleAdapter(DependencyManager dm) {
+        return new BundleAdapterBuilderImpl(dm);
+    }
+   
+    /**
+     * Creates a DM ServiceDependency builder.
+     *
+     * @param <T> the service dependency type
+     * @param component the component on which you want to build a new service dependency using the returned builder
+     * @param service the service dependency type.
+     * @return a DM ServiceDependency builder.
+     */
+    public static <T> ServiceDependencyBuilder<T> serviceDependency(Component component, Class<T> service) {
+        return new ServiceDependencyBuilderImpl<>(component, service);
+    }
+    
+    /**
+     * Creates a DM Configuration Dependency builder.
+     * 
+     * @param component the component on which you want to build a new configuration dependency using the returned builder
+     * @return a DM Configuration Dependency builder.
+     */
+    public static ConfigurationDependencyBuilder confDependency(Component component) {
+        return new ConfigurationDependencyBuilderImpl(component);
+    }
+    
+    /**
+     * Creates a DM Bundle Dependency builder.
+     * 
+     * @param component the component on which you want to build a new bundle dependency using the returned builder
+     * @return a DM Configuration Dependency builder.
+     */
+    public static BundleDependencyBuilder bundleDependency(Component component) {
+        return new BundleDependencyBuilderImpl(component);
+    }
+
+    /**
+     * Creates a DM CompletableFuture Dependency builder.
+     *
+     * @param <F> the type of the CompletableFuture result.
+     * @param component the component on which you want to build a new completable future dependency using the returned builder.
+     * @param future the future the dependency built using the returned builder will depend on.
+     * @return a CompletableFuture dependency builder.
+     */
+    public static <F> FutureDependencyBuilder<F> futureDependency(Component component, CompletableFuture<F> future) {
+        return new CompletableFutureDependencyImpl<>(component, future);
+    }
+
+    /**
+     * Builds a component using a lambda and a component builder
+     * @param dm the DependencyManager where the component is auto-added (unless the component.autoAdd(false) is called)
+     * @param consumer a lambda that is called to build the component. When the lambda is called, it will be provided with a 
+     * ComponentBuilder object that is used to build the actual DM component.
+     * 
+     * @return the built DM component.
+     */
+    public static Component component(DependencyManager dm, Consumer<ComponentBuilder<?>> consumer) {
+        ComponentBuilder<?> componentBuilder = new ComponentBuilderImpl(dm);
+        consumer.accept(componentBuilder);
+        Component comp = componentBuilder.build();
+        if (((ComponentBuilderImpl) componentBuilder).isAutoAdd()) {
+        	dm.add(comp);
+        }
+        return comp;
+    }
+
+    /**
+     * Update an existing component. Typically, this method can be used from a Component.init method, where more dependencies has to be added.
+     * @param comp an existing DM component
+     * @param consumer the lambda that will be used to update the component
+     */
+    public static void component(Component comp, Consumer<ComponentBuilder<?>> consumer) {
+        ComponentBuilder<?> componentBuilder = new ComponentBuilderImpl(comp, true /* update component */);
+        consumer.accept(componentBuilder);
+        componentBuilder.build();
+    }
+    
+    /**
+     * Builds an aspect DM Component.
+     * 
+     * @param <T> the aspect service type
+     * @param dm the DependencyManager object used to register the built component
+     * @param aspect the type of the aspect service
+     * @param consumer a lambda used to build the DM aspect component
+     * @return a new DM aspect component. The aspect component is auto-added into the dm object, unless the lambda calls
+     * the AspectBuilder.autoAdd(false) method.
+     */
+    public static <T> Component aspect(DependencyManager dm, Class<T> aspect, Consumer<ServiceAspectBuilder<T>> consumer) {
+        ServiceAspectBuilderImpl<T> aspectBuilder = new ServiceAspectBuilderImpl<>(dm, aspect);
+        consumer.accept(aspectBuilder);
+        Component comp = aspectBuilder.build();
+        if (aspectBuilder.isAutoAdd()) {
+        	dm.add(comp);
+        }
+        return comp;
+    }    
+        
+    /**
+     * Builds an adapter DM Component.
+     * 
+     * @param <T> the adapted service type
+     * @param dm the DependencyManager object used to register the built component
+     * @param adaptee the type of the adapted service
+     * @param consumer a lambda used to build the DM adapter component
+     * @return a new DM adapter component. The adapter component is auto-added into the dm object, unless the lambda calls
+     * the AspectBuilder.autoAdd(false) method is called.
+     */
+    public static <T> Component adapter(DependencyManager dm, Class<T> adaptee, Consumer<ServiceAdapterBuilder<T>> consumer) {
+        ServiceAdapterBuilderImpl<T> adapterBuilder = new ServiceAdapterBuilderImpl<>(dm, adaptee);
+        consumer.accept(adapterBuilder);
+        Component comp = adapterBuilder.build();
+        if (adapterBuilder.isAutoAdd()) {
+        	dm.add(comp);
+        }
+        return comp;
+    }
+      
+    /**
+     * Builds a bundle adapter DM Component.
+     * 
+     * @param dm the DependencyManager object used to register the built component
+     * @param consumer a lambda used to build the bundle adapter component
+     * @return a new bundle adapter component. The adapter component is auto-added into the dm object, unless the lambda calls
+     * the AspectBuilder.autoAdd(false) method is called.
+     */
+    public static Component bundleAdapter(DependencyManager dm, Consumer<BundleAdapterBuilder> consumer) {
+        BundleAdapterBuilderImpl adapterBuilder = new BundleAdapterBuilderImpl(dm);
+        consumer.accept(adapterBuilder);
+        Component comp = adapterBuilder.build();
+        if (adapterBuilder.isAutoAdd()) {
+            dm.add(comp);
+        }
+        return comp;
+    }
+
+    /**
+     * Builds a DM factory configuration adapter.
+     * @param dm the DependencyManager object used to create DM components.
+     * @param consumer a lambda used to build the DM factory configuration adapter component
+     * @return a new DM factory configuration adapter component. The adapter component is auto-added into the dm object, unless the lambda calls
+     * the FactoryPidAdapterBuilder.autoAdd(false) method is called
+     */
+    public static Component factoryPidAdapter(DependencyManager dm, Consumer<FactoryPidAdapterBuilder> consumer) {
+        FactoryPidAdapterBuilderImpl factoryPidAdapter = new FactoryPidAdapterBuilderImpl(dm);
+        consumer.accept(factoryPidAdapter);
+        Component comp = factoryPidAdapter.build();
+        if (factoryPidAdapter.isAutoAdd()) {
+        	dm.add(comp);
+        }
+        return comp;
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/FactoryPidAdapterBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/FactoryPidAdapterBuilder.java
new file mode 100644
index 0000000..909109c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/FactoryPidAdapterBuilder.java
@@ -0,0 +1,120 @@
+package org.apache.felix.dm.lambda;
+
+import org.apache.felix.dm.lambda.callbacks.CbComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeDictionary;
+
+/**
+ * Builds a Dependency Manager Factory Configuration Adapter Component. For each new Config Admin factory configuration matching the factoryPid, 
+ * an adapter will be created based on the adapter implementation class. 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.  
+ * 
+ * <p> Example that defines a factory configuration adapter service for the "foo.bar" factory pid:
+ * 
+ * <pre> {@code
+ * public class Activator extends DependencyManagerActivator {
+ *     public void activate() throws Exception { 
+ *         factoryPidAdapter(adapter -> adapter
+ *             .impl(DictionaryImpl.class)
+ *             .factoryPid("foo.bar").cb(ServiceImpl::updated)
+ *             .propagate()
+ *             .withSrv(LogService.class, log -> log.optional()));
+ *    }
+ * }
+ * }</pre>
+ */
+public interface FactoryPidAdapterBuilder extends ComponentBuilder<FactoryPidAdapterBuilder> {
+    /**
+     * Specifies the factory pid used by the adapter.
+     * @param pid the factory pid.
+     * @return this builder
+     */
+    FactoryPidAdapterBuilder factoryPid(String pid);
+    
+    /**
+     * Specifies a class name which fqdn represents the factory pid. Usually, this class can optionally be annotated with metatypes bnd annotations.
+     * @param pidClass the class that acts as the factory pid
+     * @return this builder
+     */
+    FactoryPidAdapterBuilder factoryPid(Class<?> pidClass);
+    
+    /**
+     * Specifies if the public properties (not starting with a dot) should be propagated in the adapter service properties (false by default).
+     * @return this builder.
+     */
+    FactoryPidAdapterBuilder propagate();
+    
+    /**
+     * Specifies if the public properties (not starting with a dot) should be propagated in the adapter service properties (false by default).
+     * @param propagate true if the public properties should be propagated in the adapter service properties (false by default).
+     * @return this builder.
+     */
+    FactoryPidAdapterBuilder propagate(boolean propagate);
+    
+    /**
+     * Specifies a callback method that will be called on the component instances when the configuration is injected
+     * @param updateMethod the method to call on the component instances when the configuration is available ("updated" by default).
+     * The following method signatures are supported:
+     * 
+     * <pre> {@code
+     *    method(Dictionary properties)
+     *    method(Component component, Dictionary properties)
+     * }</pre>
+     * 
+     * @return this builder
+     */
+    FactoryPidAdapterBuilder cb(String updateMethod);
+    
+    /**
+     * Specifies a callback instance method that will be called on a given object instance when the configuration is injected
+     * @param updateMethod the method to call on the given object instance when the configuration is available ("updated" by default).
+     * The following method signatures are supported:
+     * 
+     * <pre> {@code
+     *    method(Dictionary properties)
+     *    method(Component component, Dictionary properties)
+     * }</pre>
+     *
+     * @param callbackInstance the Object instance on which the updated callback will be invoked.
+     * @return this builder
+     */
+    FactoryPidAdapterBuilder cb(Object callbackInstance, String updateMethod);
+    
+    /**
+     * Specifies a callback method reference that will be called on one of the component classes when the configuration is injected.
+     * 
+     * @param <U> the type of the component implementation class on which the callback is invoked on.
+     * @param callback the method to call on one of the component classes when the configuration is available.
+     * @return this builder
+     */
+    <U> FactoryPidAdapterBuilder cb(CbTypeDictionary<U> callback);
+    
+    /**
+     * Specifies a callback method reference that will be called on one of the component classes when the configuration is injected
+     * 
+     * @param <U> the type of the component implementation class on which the callback is invoked on.
+     * @param callback the reference to a method on one of the component classes. The method may takes as parameter a Component and a Dictionary.
+     * @return this builder
+     */
+    <U> FactoryPidAdapterBuilder cb(CbTypeComponentDictionary<U> callback);
+    
+    /**
+     * Specifies a callback instance method reference that will be called on a given object instance when the configuration is injected
+     * 
+     * @param callback the method to call on a given object instance when the configuration is available. The callback takes as argument a
+     * a Dictionary parameter.
+     * @return this builder
+     */
+    FactoryPidAdapterBuilder cbi(CbDictionary callback);
+
+    /**
+     * Specifies a callback instance method reference that will be called on a given object instance when the configuration is injected.
+     * 
+     * @param callback the method to call on a given object instance when the configuration is available. The callback takes as argument a
+     * Dictionary parameter. 
+     * @return this builder
+     */
+    FactoryPidAdapterBuilder cbi(CbComponentDictionary callback);
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/FluentProperties.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/FluentProperties.java
new file mode 100644
index 0000000..7ee7724
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/FluentProperties.java
@@ -0,0 +1,35 @@
+package org.apache.felix.dm.lambda;
+
+import org.apache.felix.dm.lambda.callbacks.SerializableLambda;
+
+/**
+ * Lambda allowing to define fluent service properties. Property names are deduces from the lambda parameter name.
+ * 
+ * <p> Example of a component which provides fluent properties ("foo=bar"; "foo2=Integer(123)):
+ * 
+ * <pre>{@code
+ * public class Activator extends DependencyManagerActivator {
+ *   public void activate() throws Exception {
+ *       component(comp -> comp.impl(MyComponentImpl.class).provides(MyService.class, foo->"bar", foo2 -> 123));
+ *   }
+ * } 
+ * }</pre>
+ * 
+ * <b>Caution: Fluent properties requires the usage of the "-parameter" javac option.</b>
+ * 
+ * Under eclipse, you can enable this option using:
+ * 
+ * <pre>{@code
+ * Windows -> Preference -> Compiler -> Classfile Generation -> Store information about method parameters.
+ * }</pre>
+ */
+@FunctionalInterface
+public interface FluentProperties extends SerializableLambda {
+    /**
+     * Represents a fluent property
+     * 
+     * @param name the property name. The parameter used by the lambda will be intropsected and will be used as the actual property name.
+     * @return the property value
+     */
+    public Object apply(String name);
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/FutureDependencyBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/FutureDependencyBuilder.java
new file mode 100644
index 0000000..800e306
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/FutureDependencyBuilder.java
@@ -0,0 +1,129 @@
+package org.apache.felix.dm.lambda;
+
+import java.util.concurrent.Executor;
+
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.lambda.callbacks.CbFuture;
+import org.apache.felix.dm.lambda.callbacks.CbTypeFuture;
+
+/**
+ * Defines a builder for a CompletableFuture dependency.
+ * Using such dependency allows your component to wait for the completion of a given asynchronous task
+ * represented by a standard jdk <code>CompletableFuture</code> object.
+ * 
+ * A FutureDependency is required and unblock the Component once the CompletableFuture result has completed.
+ * 
+ * <h3>Usage Example</h3>
+ * 
+ * <p> Here is an Activator that downloads a page from the web and injects the string result to a component.
+ * When the web page is downloaded, the result is injected in the MyComponent::setPage method and
+ * the component is then called in its "start" method:
+ * 
+ * <pre>{@code
+ * 
+ * public class Activator extends DependencyManagerActivator {
+ *   public void activate() throws Exception {    	
+ *      String url = "http://felix.apache.org/";
+ *      CompletableFuture<String> page = CompletableFuture.supplyAsync(() -> downloadSite(url));				
+ *
+ *      // The component depends on a log service and on the content of the Felix site.
+ *      // The lambda passed to the "withFuture" method configures the callback that is 
+ *      // invoked with the result of the CompletableFuture (the page content).
+ *      component(comp -> comp
+ *          .impl(MyComponent.class)
+ *          .withService(LogService.class)
+ *          .withFuture(page, result -> result.cb(MyComponent::setPage)));
+ *   }
+ * }
+ * 
+ * public class MyComponent {
+ *   volatile LogService log; // injected.
+ *   
+ *   void setPage(String page) {
+ *      // injected by the FutureDependency.
+ *   }
+ *   
+ *   void start() {
+ *      // all required dependencies injected.
+ *   }
+ * }
+ * 
+ * }</pre>
+ * 
+ * @param <F> the type of the CompletableFuture result.
+ */
+public interface FutureDependencyBuilder<F> extends DependencyBuilder<Dependency> { 
+    /**
+     * Sets the callback method name to invoke on the component instances, once the CompletableFuture has completed.
+     * @param callback the callback method name to invoke on the component instances, once the CompletableFuture on which we depend has completed.
+     * @return this dependency.
+     */
+    FutureDependencyBuilder<F> cb(String callback);
+    
+    /**
+     * Sets the function to invoke when the future task has completed. The function is from one of the Component implementation classes, and it accepts the
+     * result of the completed future.
+     * 
+     * @param <T> the type of the CompletableFuture result.
+     * @param callback the function to perform when the future task as completed. 
+     * @return this dependency
+     */
+    <T> FutureDependencyBuilder<F> cb(CbTypeFuture<T, ? super F> callback);
+    
+    /**
+     * Sets the function to invoke asynchronously when the future task has completed. The function is from one of the Component implementation classes, 
+     * and it accepts the result of the completed future.
+     * 
+     * @param <T> the type of the CompletableFuture result.
+     * @param callback the function to perform when the future task as completed.
+     * @param async true if the callback should be invoked asynchronously using the default jdk execution facility, false if not.
+     * @return this dependency
+     */
+    <T> FutureDependencyBuilder<F> cb(CbTypeFuture<T, ? super F> callback, boolean async);
+
+    /**
+     * Sets the function to invoke asynchronously when the future task has completed. The function is from one of the Component implementation classes, 
+     * and it accepts the result of the completed future.
+     * 
+     * @param <T> the type of the CompletableFuture result.
+     * @param callback the function to perform when the future task as completed. 
+     * @param executor the executor used to schedule the callback.
+     * @return this dependency
+     */
+    <T> FutureDependencyBuilder<F> cb(CbTypeFuture<T, ? super F> callback, Executor executor);   
+        
+    /**
+     * Sets the callback instance method name to invoke on a given Object instance, once the CompletableFuture has completed.
+     * @param callbackInstance the object instance on which the callback must be invoked
+     * @param callback the callback method name to invoke on Object instance, once the CompletableFuture has completed.
+     * @return this dependency.
+     */
+    FutureDependencyBuilder<F> cbi(Object callbackInstance, String callback);
+    
+    /**
+     * Sets the callback instance to invoke when the future task has completed. The callback is a Consumer instance which accepts the
+     * result of the completed future.
+     * @param callback a Consumer instance which accepts the result of the completed future.
+     * @return this dependency
+     */
+    FutureDependencyBuilder<F> cbi(CbFuture<? super F> callback);
+    
+    /**
+     * Sets the callback instance to invoke when the future task has completed. The callback is a Consumer instance which accepts the
+     * result of the completed future.
+     * 
+     * @param callback a Consumer instance which accepts the result of the completed future.
+     * @param async true if the callback should be invoked asynchronously using the default jdk execution facility, false if not.
+     * @return this dependency
+     */
+    FutureDependencyBuilder<F> cbi(CbFuture<? super F> callback, boolean async);
+
+    /**
+     * Sets the callback instance to invoke when the future task has completed. The callback is a Consumer instance which accepts the
+     * result of the completed future.
+     * @param callback the action to perform when the future task as completed. 
+     * @param executor the executor to use for asynchronous execution of the callback.
+     * @return this dependency
+     */
+    FutureDependencyBuilder<F> cbi(CbFuture<? super F> callback, Executor executor);   
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceAdapterBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceAdapterBuilder.java
new file mode 100644
index 0000000..eef4890
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceAdapterBuilder.java
@@ -0,0 +1,59 @@
+package org.apache.felix.dm.lambda;
+
+/**
+ * Builds a Dependency Manager Service Adapter Component.
+ * The adapter will be applied to any service that matches the specified interface and filter. For each matching service an adapter will be created 
+ * based on the adapter implementation class. The adapter will be registered with the specified interface and existing properties from the original 
+ * service plus any extra properties you supply here.<p>
+ * 
+ * Code example that adapts a "Device" service to an HttpServlet service. The adapter is created using a ServiceAdapterBuilder that is passed to the lambda. 
+ * 
+ * <pre> {@code
+ * public class Activator extends DependencyManagerActivator {
+ *    public void activate() throws Exception { 
+ *        adapter(Device.class, adapt -> adapt.impl(DeviceServlet.class).provides(HttpServlet.class).properties(alias -> "/device");                    
+ *    }
+ * }}</pre>
+ * 
+ * @param <T> the adaptee service
+ */
+public interface ServiceAdapterBuilder<T> extends ComponentBuilder<ServiceAdapterBuilder<T>>, ServiceCallbacksBuilder<T, ServiceAdapterBuilder<T>> {
+    /**
+     * Specifies the filter used to match a given adapted service.
+     * 
+     * @param adapteeFilter the filter used to match a given adapted service
+     * @return this builder
+     */
+    ServiceAdapterBuilder<T> filter(String adapteeFilter);
+    
+    /**
+     * Specifies whether or not the adapted service properties must be propagated to the adapter service (true by default). 
+     * 
+     * @param propagate true if the adapted service properties must be propagated to the adapter service (true by default). 
+     * @return this builder
+     */
+    ServiceAdapterBuilder<T> propagate(boolean propagate);
+    
+    /**
+     * Injects this adapted service in all fields matching the adapted service type.
+     * 
+     * @return this builder
+     */
+    ServiceAdapterBuilder<T> autoConfig();
+    
+    /**
+     * Configures whether or not the adapted service can be injected in all fields matching the adapted service type. 
+     * 
+     * @param autoConfig true if the adapted service can be injected in all fields matching the adapted service type
+     * @return this builder
+     */
+    ServiceAdapterBuilder<T> autoConfig(boolean autoConfig);
+    
+    /**
+     * Injects this adapted service on the field matching the given name
+     * 
+     * @param field the field name where the adapted service must be injected to.
+     * @return this builder
+     */
+    ServiceAdapterBuilder<T> autoConfig(String field);        
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceAspectBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceAspectBuilder.java
new file mode 100644
index 0000000..160975e
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceAspectBuilder.java
@@ -0,0 +1,72 @@
+package org.apache.felix.dm.lambda;
+
+/**
+ * Builds a Dependency Manager Aspect Component.
+ * The aspect will be applied to any service that matches the specified interface and filter (if any). For each matching service an aspect will be created based 
+ * on the aspect implementation class. 
+ * The aspect will be registered with the same interface and properties as the original service, plus any extra properties you supply here.
+ * Multiple Aspects of the same service are chained and ordered using aspect ranks.
+ * 
+ * <p> Code example that provides a "LogService" aspect that performs spell-checking of each log message. 
+ * The aspect decorates a LogService. The aspect also depends on an Dictionary service that is internally used to perform log spell checking.
+ * The LogService and Dictionary services are injected in the aspect implementation using reflection on class fields:
+ * 
+ * <pre>{@code
+ * public class Activator extends DependencyManagerActivator {
+ *    public void activate() throws Exception { 
+ *       aspect(LogService.class, asp -> asp.impl(SpellCheckLogAspect.class).rank(10).withSrv(Dictionary.class));
+ *    }
+ * }} </pre>
+ *
+ * Same example, but using callbacks for injecting LogService and Dictionary services in the aspect implementation class:
+ * 
+ * <pre>{@code
+ * public class Activator extends DependencyManagerActivator {
+ *    public void activate() throws Exception { 
+ *       aspect(LogService.class, asp -> asp.impl(SpellCheckLogAspect.class).rank(10)
+ *          .cb(SpellCheckLogAspect::setLogService)
+ *          .withSrv(Dictionary.class, dict -> dict.cb(SpellCheckLogAspect::setDictionary)));
+ *    }
+ * }} </pre>
+ *
+ * @param <T> the aspect service
+ */
+public interface ServiceAspectBuilder<T> extends ComponentBuilder<ServiceAspectBuilder<T>>, ServiceCallbacksBuilder<T, ServiceAspectBuilder<T>> {
+    /**
+     * Specifies the aspect service filter. 
+     * 
+     * @param filter the filter condition to use with the service interface the aspect will apply on
+     * @return this builder
+     */
+    ServiceAspectBuilder<T> filter(String filter);
+    
+    /**
+     * Specifies the aspect ranking. Aspects of a given service are ordered by their ranking property.
+     * 
+     * @param ranking the aspect ranking
+     * @return this builder
+     */
+    ServiceAspectBuilder<T> rank(int ranking);
+    
+    /**
+     * Injects the aspect in all fields matching the aspect type.
+     * @return this builder
+     */
+    ServiceAspectBuilder<T> autoConfig();
+    
+    /**
+     * Configures whether or not the aspect service can be injected in all fields matching the aspect type.
+     *  
+     * @param autoConfig true if the aspect service can be injected in all fields matching the dependency type
+     * @return this builder
+     */
+    ServiceAspectBuilder<T> autoConfig(boolean autoConfig);
+    
+    /**
+     * Injects the aspect service on the field with the given name.
+     * 
+     * @param field the field name where the aspect service must be injected
+     * @return this builder
+     */
+    ServiceAspectBuilder<T> autoConfig(String field);     
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceCallbacksBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceCallbacksBuilder.java
new file mode 100644
index 0000000..d6190bc
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceCallbacksBuilder.java
@@ -0,0 +1,799 @@
+package org.apache.felix.dm.lambda;
+
+import org.apache.felix.dm.lambda.callbacks.CbComponent;
+import org.apache.felix.dm.lambda.callbacks.CbComponentRef;
+import org.apache.felix.dm.lambda.callbacks.CbComponentRefService;
+import org.apache.felix.dm.lambda.callbacks.CbComponentRefServiceRefService;
+import org.apache.felix.dm.lambda.callbacks.CbComponentService;
+import org.apache.felix.dm.lambda.callbacks.CbComponentServiceService;
+import org.apache.felix.dm.lambda.callbacks.CbRef;
+import org.apache.felix.dm.lambda.callbacks.CbRefService;
+import org.apache.felix.dm.lambda.callbacks.CbRefServiceRefService;
+import org.apache.felix.dm.lambda.callbacks.CbService;
+import org.apache.felix.dm.lambda.callbacks.CbServiceDict;
+import org.apache.felix.dm.lambda.callbacks.CbServiceMap;
+import org.apache.felix.dm.lambda.callbacks.CbServiceService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponent;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentRef;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentRefService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentRefServiceRefService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentServiceService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeRef;
+import org.apache.felix.dm.lambda.callbacks.CbTypeRefService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeRefServiceRefService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeServiceDict;
+import org.apache.felix.dm.lambda.callbacks.CbTypeServiceMap;
+import org.apache.felix.dm.lambda.callbacks.CbTypeServiceService;
+
+/**
+ * Builds a service dependency callback (required by default).
+ * 
+ * A Service may be injected in a bind-method of a component or an object instance using this builder.
+ * The builder supports the following kind of method signatures for bind methods:
+ * 
+ * <pre> {@code
+ * method(S service)
+ * method(S service, Map<String, Object> serviceProperties)
+ * method(S service, Dictionary<String, Object> serviceProperties)
+ * method(ServiceReference<S> serviceRef, S service),
+ * method(ServiceReference<S> serviceRef)
+ * method(Component serviceComponent)
+ * method(Component serviceComponent, ServiceReference<S> serviceRef)
+ * method(Component serviceComponent, S service) 
+ * method(Component serviceComponent, ServiceReference<S> serviceRef, S service)
+ * swapMethod(S oldService, S newService)
+ * swapMethod(ServiceReference<S> oldRef, S old, ServiceReference<S> newRef, S newService)
+ * swapMethod(Component component, S oldService, S newService)
+ * swapMethod(Component component, ServiceReference<S> oldRef, S old, ServiceReference<S> newRef, S newService)
+ * }</pre>
+ *
+ * The following families of callbacks are supported:
+ * 
+ * <ul>
+ * <li> "cb(String ... callback)": stands for "callback" and specifies a list of callbacks from the component instances. When using one arg, it stands for the "add" callback. 
+ * When using two args, it stands for "add/remove" callbacks. When using three args, it stands for "add/change/remove" callbacks. When using four args, it stands for "add/change/remove/swap" callbacks. 
+ * <li> "cbi(Object callbackInstance, String ... callbacks)": stands for "callback instance" and specifies some callbacks on a given object instance.
+ * <li> "cb(lambda) ": stands for "callback" and specifies a method reference of a callback from a given component class.
+ * <li> "cbi(lambda)": stands for "callback instance" and specifies a method reference from a given object instance.
+ * <li> "sw(lambda)":  stands for "swap callback" and specifies a method reference of a swap callback from a given component class.
+ * <li> "swi(lambda)": stands for "swap callback instance" and specifies a method reference of a swap callback from a given object instance.
+ * </ul>
+ *
+ * <p> Here is an example of a Component that defines a dependency of a LogService which is injected in the "bindLogService" method using a ServiceCallbacksBuilder:
+ * The withSrv(...)" declaration defines a method reference on the "ComponentImpl::bindLogService" method (using a lambda):
+ * 
+ * <pre> {@code
+ * public class Activator extends DependencyManagerActivator {
+ *    public void activate() throws Exception { 
+ *       component(comp -> comp.impl(ComponentImpl.class).withSrv(LogService.class, log -> log.cb(ComponentImpl::bindLogService)));
+ *    }
+ * }}</pre>
+ *
+ * <p> Same example, but we inject the dependency in an object instance that we already have in hand:
+ * 
+ * <pre> {@code
+ * public class Activator extends DependencyManagerActivator {
+ *    public void activate() throws Exception {
+ *       ComponentImpl impl = new ComponentImpl();
+ *       component(comp -> comp.impl(impl).withSrv(LogService.class, log -> log.cbi(impl::bindLogService)));
+ *    }
+ * }}</pre>
+ * 
+ * <p> Here, we inject a service using method reflection (as it is the case in original DM api):
+ * 
+ * <pre> {@code
+ * public class Activator extends DependencyManagerActivator {
+ *    public void activate() throws Exception {
+ *       component(comp -> comp.impl(ComponentImpl::class).withSrv(LogService.class, log -> log.cb("bindLogService")));
+ *    }
+ * }}</pre>
+ *
+ * <p> Same example, but we inject the dependency in an object instance that we already have in hand:
+ * 
+ * <pre> {@code
+ * public class Activator extends DependencyManagerActivator {
+ *    public void activate() throws Exception {
+ *       ComponentImpl impl = new ComponentImpl();
+ *       component(comp -> comp.impl(impl).withSrv(LogService.class, log -> log.cbi(impl, "bindLogService")));
+ *    }
+ * }}</pre>
+ *
+ * @param <S> the service dependency type
+ * @param <B> the type of a sub interface that may extends this interface.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ServiceCallbacksBuilder<S, B extends ServiceCallbacksBuilder<S, B>> {
+    /**
+     * Sets <code>callback</code> methods to invoke on the component instance(s). When a service matches the service 
+     * filter, then the service is injected using the specified callback methods. When you specify one callback, it stands for the "add" callback.
+     * When you specify two callbacks, the first one corresponds to the "add" callback, and the second one to the "remove" callback. When you specify three
+     * callbacks, the first one stands for the "add" callback, the second one for the "change" callback, and the third one for the "remove" callback.
+     * When you specify four callbacks, it stands for "add"/"change"/"remove"/swap callbacks.
+     * 
+     * The following method signature are supported:
+     * <pre>{@code
+     * method(S service)
+     * method(S service, Map<String, Object> serviceProperties)
+     * method(S service, Dictionary<String, Object> serviceProperties)
+     * method(ServiceReference<S> serviceRef, S service),
+     * method(ServiceReference<S> serviceRef)
+     * method(Component serviceComponent)
+     * method(Component serviceComponent, ServiceReference<S> serviceRef)
+     * method(Component serviceComponent, S service) 
+     * method(Component serviceComponent, ServiceReference<S> serviceRef, S service)
+     * swapMethod(S oldService, S newService)
+     * swapMethod(ServiceReference<S> oldRef, S old, ServiceReference<S> newRef, S newService)
+     * swapMethod(Component component, S oldService, S newService)
+     * swapMethod(Component component, ServiceReference<S> oldRef, S old, ServiceReference<S> newRef, S newService)
+     * }</pre>
+     * 
+     * @param callbacks a list of callbacks (1 param: "add", 2 params: "add"/remove", 3 params: "add"/"change"/"remove", 4 params: "add"/"change"/"remove"/"swap" callbacks).
+     * @return this builder
+     */
+    B cb(String ... callbacks);
+    
+    /**
+     * Sets <code>callback instance</code> methods to invoke on a given Object instance. When a service matches the service 
+     * filter, then the service is injected using the specified callback methods. When you specify one callback, it stands for the "add" callback.
+     * When you specify two callbacks, the first one corresponds to the "add" callback, and the second one to the "remove" callback. When you specify three
+     * callbacks, the first one stands for the "add" callback, the second one for the "change" callback, and the third one for the "remove" callback.
+     * 
+     * @param callbackInstance the object on which the callback is invoked.
+     * @param callbacks a list of callbacks (1 param : "add", 2 params : "add"/remove", 3 params : "add"/"change"/"remove", 4 params : "add"/"change"/"remove"/"swap" callbacks).
+     * @see #cb(String...)
+     * @return this builder
+     */
+    B cbi(Object callbackInstance, String ... callbacks);
+
+    /**
+     * Sets a <code>callback</code> invoked when a service is added.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    <T> B cb(CbTypeService<T, S> add);
+    
+    /**
+     * Sets a <code>callback</code> invoked when a service is added or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeService<T, S> add, CbTypeService<T, S> remove);
+  
+    /**
+     * Sets a <code>callback</code> invoked when a service is added, changed, or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeService<T, S> add, CbTypeService<T, S> change, CbTypeService<T, S> remove);
+    
+    /**
+     * Sets a <code>callback</code> invoked when a service is added.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service, and a properties map.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    <T> B cb(CbTypeServiceMap<T, S> add);
+    
+    /**
+     * Sets a <code>callback</code> invoked when a service is added or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service, and a properties map.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeServiceMap<T, S> add, CbTypeServiceMap<T, S> remove);
+    
+    /**
+     * Sets a <code>callback</code> invoked when a service is added, changed, or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service, and a properties map.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeServiceMap<T, S> add, CbTypeServiceMap<T, S> change, CbTypeServiceMap<T, S> remove);
+  
+    /**
+     * Sets a <code>callback</code> invoked when a service is added.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service, and a properties dictionary.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    <T> B cb(CbTypeServiceDict<T, S> add);
+    
+    /**
+     * Sets a <code>callback</code> invoked when a service is added or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service, and a properties dictionary.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeServiceDict<T, S> add, CbTypeServiceDict<T, S> remove);
+    
+    /**
+     * Sets a <code>callback</code> invoked when a service is added, changed, or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service, and a properties dictionary.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeServiceDict<T, S> add, CbTypeServiceDict<T, S> change, CbTypeServiceDict<T, S> remove);
+
+    /**
+     * Sets a <code>callback</code> invoked when a service is added.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service reference, and the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    <T> B cb(CbTypeRefService<T, S> add);
+    
+    /**
+     * Sets a <code>callback</code> invoked when a service is added or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service reference, and the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeRefService<T, S> add, CbTypeRefService<T, S> remove);
+ 
+    /**
+     * Sets a <code>callback</code> invoked when a service is added, changed, or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service reference, and the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeRefService<T, S> add, CbTypeRefService<T, S> change, CbTypeRefService<T, S> remove);
+
+    /**
+     * Sets a <code>callback</code> invoked when a service is added.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service reference.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    <T> B cb(CbTypeRef<T, S> add);
+  
+    /**
+     * Sets a <code>callback</code> invoked when a service is added or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service reference.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeRef<T, S> add, CbTypeRef<T, S> remove);
+  
+    /**
+     * Sets a <code>callback</code> invoked when a service is added, changed, or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the service reference.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeRef<T, S> add, CbTypeRef<T, S> change, CbTypeRef<T, S> remove);
+
+    /**
+     * Sets a <code>callback</code> invoked when a service is added.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponent<T> add);
+  
+    /**
+     * Sets a <code>callback</code> invoked when a service is added or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponent<T> add, CbTypeComponent<T> remove);
+  
+    /**
+     * Sets a <code>callback</code> invoked when a service is added, changed, or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponent<T> add, CbTypeComponent<T> change, CbTypeComponent<T> remove);
+
+    /**
+     * Sets a <code>callback</code> invoked when a service is added.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component, and the service reference.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponentRef<T, S> add);
+  
+    /**
+     * Sets a <code>callback</code> invoked when a service is added or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component, and the service reference.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponentRef<T, S> add, CbTypeComponentRef<T, S> remove);
+  
+    /**
+     * Sets a <code>callback</code> invoked when a service is added, changed, or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component, and the service reference.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponentRef<T, S> add, CbTypeComponentRef<T, S> change, CbTypeComponentRef<T, S> remove);
+
+    /**
+     * Sets a <code>callback</code> invoked when a service is added.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component, and the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponentService<T, S> add);
+
+    /**
+     * Sets a <code>callback</code> invoked when a service is added or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component, and the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponentService<T, S> add, CbTypeComponentService<T, S> remove);
+    
+    /**
+     * Sets a <code>callback</code> invoked when a service is added, changed, or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component, and the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponentService<T, S> add, CbTypeComponentService<T, S> change, CbTypeComponentService<T, S> remove);
+
+    /**
+     * Sets a <code>callback</code> invoked when a service is added.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component, the service Reference and the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponentRefService<T, S> add);
+ 
+    /**
+     * Sets a <code>callback</code> invoked when a service is added or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component, the service Reference and the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponentRefService<T, S> add, CbTypeComponentRefService<T, S> remove);
+    
+    /**
+     * Sets a <code>callback</code> invoked when a service is added, changed, or removed.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the Component, the service Reference and the service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    <T> B cb(CbTypeComponentRefService<T, S> add, CbTypeComponentRefService<T, S> change, CbTypeComponentRefService<T, S> remove);
+
+    /**
+     * Sets a <code>swap callback(Service, Service)</code> invoked when a service is swapped.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the old service and the new replacing service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param swap the method reference invoked when the service is swapped.
+     * @return this builder
+     */
+    <T> B sw(CbTypeServiceService<T, S> swap);
+ 
+    /**
+     * Sets a <code>swap callback(Component, Service, Service)</code> invoked when a service is swapped.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the component, the old service and the new replacing service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param swap the method reference invoked when the service is swapped.
+     * @return this builder
+     */
+    <T> B sw(CbTypeComponentServiceService<T, S> swap);
+    
+    /**
+     * Sets a <code>swap callback(ServiceReference, Service, ServiceReference, Service)</code> invoked when a service is swapped.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the old service reference, the old service, the new service reference, and
+     * the new service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param swap the method reference invoked when the service is swapped.
+     * @return this builder
+     */
+    <T> B sw(CbTypeRefServiceRefService<T, S> swap);
+    
+    /**
+     * Sets a swap <code>callback</code> invoked when a service is swapped.
+     * The method reference must point to a Component implementation class method. Callback argument(s): the component, the old service reference, the old service, the new service reference, and
+     * the new service.
+     * 
+     * @param <T> the type of the component instance class on which the callback is invoked.
+     * @param swap the method reference invoked when the service is swapped.
+     * @return this builder
+     */
+    <T> B sw(CbTypeComponentRefServiceRefService<T, S> swap);
+
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added.
+     * The method reference must point to a method from an Object instance. Callback argument(s): a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    B cbi(CbService<S> add);
+    
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbService<S> add, CbService<S> remove);
+  
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/changed/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbService<S> add, CbService<S> change, CbService<S> remove);
+
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added.
+     * The method reference must point to a method from an Object instance. Callback argument(s): a service and a properties Map.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    B cbi(CbServiceMap<S> add);
+  
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a service and a properties Map.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbServiceMap<S> add, CbServiceMap<S> remove);
+  
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/changed/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a service and a properties Map.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbServiceMap<S> add, CbServiceMap<S> change, CbServiceMap<S> remove);
+
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added.
+     * The method reference must point to a method from an Object instance. Callback argument(s): a service and a properties Dictionary.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    B cbi(CbServiceDict<S> add);
+   
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a service and a properties Dictionary.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbServiceDict<S> add, CbServiceDict<S> remove);
+ 
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/changed/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a service and a properties Dictionary.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbServiceDict<S> add, CbServiceDict<S> change, CbServiceDict<S> remove);
+
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added.
+     * The method reference must point to a method from an Object instance. Callback argument(s): a service reference and a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    B cbi(CbRefService<S> add);
+    
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a service reference and a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbRefService<S> add, CbRefService<S> remove);
+  
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/changed/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a service reference and a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbRefService<S> add, CbRefService<S> change, CbRefService<S> remove);
+
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added.
+     * The method reference must point to a method from an Object instance. Callback argument(s): a service reference.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    B cbi(CbRef<S> add);
+  
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a service reference.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbRef<S> add, CbRef<S> remove);
+    
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/changed/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a service reference.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbRef<S> add, CbRef<S> change, CbRef<S> remove);
+
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added.
+     * The method reference must point to a method from an Object instance. Callback argument(s): a Component.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    B cbi(CbComponent add);
+    
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a Component.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbComponent add, CbComponent remove);
+ 
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/changed/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a Component.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbComponent add, CbComponent change, CbComponent remove);
+
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added.
+     * The method reference must point to a method from an Object instance. Callback argument(s): a Component and a service reference.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    B cbi(CbComponentRef<S> add);
+  
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a Component and a service reference.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbComponentRef<S> add, CbComponentRef<S> remove);
+ 
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/changed/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a Component and a service reference.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbComponentRef<S> add, CbComponentRef<S> change, CbComponentRef<S> remove);
+
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added.
+     * The method reference must point to a method from an Object instance. Callback argument(s): a Component and a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    B cbi(CbComponentService<S> add);    
+  
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a Component and a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbComponentService<S> add, CbComponentService<S> remove);
+   
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/changed/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a Component and a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbComponentService<S> add, CbComponentService<S> change, CbComponentService<S> remove);
+
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added.
+     * The method reference must point to a method from an Object instance. Callback argument(s): a Component, a service reference, and a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @return this builder
+     */
+    B cbi(CbComponentRefService<S> add);
+   
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a Component, a service reference, and a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbComponentRefService<S> add, CbComponentRefService<S> remove);
+  
+    /**
+     * Sets a <code>callback instance</code> invoked when a service is added/changed/removed.
+     * The method reference must point to method from an Object instance. Callback argument(s): a Component, a service reference, and a service.
+     * 
+     * @param add the method reference invoked when a service is added.
+     * @param change the method reference invoked when a service is changed.
+     * @param remove the method reference invoked when a service is removed.
+     * @return this builder
+     */
+    B cbi(CbComponentRefService<S> add, CbComponentRefService<S> change, CbComponentRefService<S> remove);
+    
+    /**
+     * Sets a swap <code>callback instance</code> invoked when a service is swapped.
+     * The method reference must point to a method from an Object instance. Callback argument(s): the old service, and the new service.
+     * the new service.
+     *
+     * @param swap the method reference invoked when the service is swapped.
+     * @return this builder
+     */
+    B swi(CbServiceService<S> swap);
+   
+    /**
+     * Sets a swap <code>callback instance</code> invoked when a service is swapped.
+     * The method reference must point to a method from an Object instance. Callback argument(s): the component, the old service, and the new service.
+     * the new service.
+     *
+     * @param swap the method reference invoked when the service is swapped.
+     * @return this builder
+     */
+    B swi(CbComponentServiceService<S> swap);
+  
+    /**
+     * Sets a swap <code>callback instance</code> invoked when a service is swapped.
+     * The method reference must point to a method from an Object instance. Callback argument(s): the old service reference, the old service, the 
+     * new service reference, and the new service.
+     *
+     * @param swap the method reference invoked when the service is swapped.
+     * @return this builder
+     */
+    B swi(CbRefServiceRefService<S> swap);
+  
+    /**
+     * Sets a swap <code>callback instance</code> invoked when a service is swapped.
+     * The method reference must point to a method from an Object instance. Callback argument(s): the component, old service reference, the old service, the 
+     * new service reference, and the new service.
+     *
+     * @param swap the method reference invoked when the service is swapped.
+     * @return this builder
+     */
+    B swi(CbComponentRefServiceRefService<S> swap);        
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceDependencyBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceDependencyBuilder.java
new file mode 100644
index 0000000..e2e4370
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/ServiceDependencyBuilder.java
@@ -0,0 +1,132 @@
+package org.apache.felix.dm.lambda;
+
+import java.util.Dictionary;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import org.apache.felix.dm.ServiceDependency;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Builds a Dependency Manager Service Dependency. Dependency callbacks can be defined using methods reflection like 
+ * in original DM API, or using Java8 method references.
+ * 
+ * Unlike with original DM, dependencies are required by default.
+ *
+ * @param <S> the type of the service dependency
+ */
+public interface ServiceDependencyBuilder<S> extends DependencyBuilder<ServiceDependency>, ServiceCallbacksBuilder<S, ServiceDependencyBuilder<S>> {
+    /**
+     * Configures the service dependency filter
+     * @param filter the service filter
+	 * @return this builder
+     */
+    ServiceDependencyBuilder<S> filter(String filter);
+    
+    /**
+     * Configures this dependency with the given ServiceReference.
+     * @param ref the service reference
+	 * @return this builder
+     */
+    ServiceDependencyBuilder<S> ref(ServiceReference<S> ref);
+    
+    /**
+     * Configures this dependency as optional. By default, a dependency is required.
+     * @return this builder
+     */
+    ServiceDependencyBuilder<S> optional();
+
+    /**
+     * Configures this dependency as required. By default, a dependency is required.
+	 * @return this builder
+     */
+    ServiceDependencyBuilder<S> required();
+    
+    /**
+     * Configures whether this dependency is required or not.
+     * 
+     * @param required true if the dependency is required, false if not. Unlike with the original DM API, service dependencies are required by default.
+	 * @return this builder
+     */
+    ServiceDependencyBuilder<S> required(boolean required);
+    
+    /**
+     * Configures debug mode
+     * @param label the label used by debug messages
+	 * @return this builder
+     */
+    ServiceDependencyBuilder<S> debug(String label);
+    
+    /**
+     * Propagates the dependency properties to the component service properties.
+	 * @return this builder
+     */
+    ServiceDependencyBuilder<S> propagate();
+  
+    /**
+     * Configures whether the dependency properties must be propagated or not to the component service properties.
+     * 
+     * @param propagate true if the service dependency properties should be propagated to the properties provided by the component using this dependency.
+	 * @return this builder
+     */
+    ServiceDependencyBuilder<S> propagate(boolean propagate);
+    
+    /**
+     * Configures a method that can is called in order to get propagated service properties.
+     * 
+     * @param instance an object instance
+     * @param method the method name to call on the object instance. This method returns the propagated service properties.
+	 * @return this builder
+     */
+    ServiceDependencyBuilder<S> propagate(Object instance, String method);
+    
+    /**
+     * Specifies a function that is called to get the propagated service properties for this service dependency. 
+     * @param propagate a function that is called to get the propagated service properties for this service dependency. 
+     * @return this builder
+     */
+    ServiceDependencyBuilder<S> propagate(Function<ServiceReference<S>, Dictionary<String, Object>> propagate);
+
+    /**
+     * Specifies a function that is called to get the propagated service properties for this service dependency. 
+     * @param propagate a function that is called to get the propagated service properties for this service dependency. 
+     * @return this builder
+     */
+    ServiceDependencyBuilder<S> propagate(BiFunction<ServiceReference<S>, S, Dictionary<String, Object>> propagate);
+    
+    /**
+     * Sets the default implementation if the service is not available.
+     * @param defaultImpl the implementation used by default when the service is not available.
+	 * @return this builder
+     */
+    ServiceDependencyBuilder<S> defImpl(Object defaultImpl);
+    
+    /**
+     * Sets a timeout for this dependency. A timed dependency blocks the invoker thread is the required dependency is currently unavailable, until it comes up again.
+     * @param timeout the timeout to wait in milliseconds when the service disappears. If the timeout expires, an IllegalStateException is thrown
+     * when the missing service is invoked.
+     * 
+     * @return this builder
+     */
+    ServiceDependencyBuilder<S> timeout(long timeout);
+    
+    /**
+     * Injects this dependency in all fields matching the dependency type.
+     * @return this builder
+     */
+    ServiceDependencyBuilder<S> autoConfig();
+    
+    /**
+     * Configures whether or not the dependency can be injected in all fields matching the dependency type. 
+     * @param autoConfig true if the dependency can be injected in all fields matching the dependency type
+     * @return this builder
+     */
+    ServiceDependencyBuilder<S> autoConfig(boolean autoConfig);
+    
+    /**
+     * Injects this dependency on the field with the given name
+     * @param field the field name where the dependency must be injected
+     * @return this builder
+     */
+    ServiceDependencyBuilder<S> autoConfig(String field);                
+}
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbBundle.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbBundle.java
new file mode 100644
index 0000000..32d24b4
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbBundle.java
@@ -0,0 +1,27 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * Represents a callback(Bundle) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbBundle extends SerializableLambda {
+    /**
+     * Handles the given argument.
+     * @param bundle the callback parameter
+     */
+    void accept(Bundle bundle);
+
+    default CbBundle andThen(CbBundle after) {
+        Objects.requireNonNull(after);
+        return (Bundle bundle) -> {
+            accept(bundle);
+            after.accept(bundle);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponent.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponent.java
new file mode 100644
index 0000000..e5fbf41
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponent.java
@@ -0,0 +1,27 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+
+/**
+ * Represents a callback(Component)  on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbComponent {
+    /**
+     * Handles the given argument.
+     * @param component the callback parameter
+     */
+    void accept(Component component);
+
+    default CbComponent andThen(CbComponent after) {
+        Objects.requireNonNull(after);
+        return (Component component) -> {
+            accept(component);
+            after.accept(component);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentBundle.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentBundle.java
new file mode 100644
index 0000000..5049a25
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentBundle.java
@@ -0,0 +1,29 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+import org.osgi.framework.Bundle;
+
+/**
+ * Represents a callback(Component, Bundle) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbComponentBundle {
+    /**
+     * Handles the given arguments.
+     * @param component the callback parameter
+     * @param bundle the callback parameter
+     */
+    void accept(Component component, Bundle bundle);
+
+    default CbComponentBundle andThen(CbComponentBundle after) {
+        Objects.requireNonNull(after);
+        return (Component component, Bundle bundle) -> {
+            accept(component, bundle);
+            after.accept(component, bundle);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentDictionary.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentDictionary.java
new file mode 100644
index 0000000..1c0f525
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentDictionary.java
@@ -0,0 +1,29 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Dictionary;
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+
+/**
+ * Represents a callback(Component, Dictionary) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbComponentDictionary {
+    /**
+     * Handles the given arguments.
+     * @param component a Component
+     * @param properties some service properties
+     */
+    void accept(Component component, Dictionary<String, Object> properties);
+
+    default CbComponentDictionary andThen(CbComponentDictionary after) {
+        Objects.requireNonNull(after);
+        return (Component component, Dictionary<String, Object> properties) -> {
+            accept(component, properties);
+            after.accept(component, properties);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentRef.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentRef.java
new file mode 100644
index 0000000..956293d
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentRef.java
@@ -0,0 +1,29 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(Component, ServiceReference) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbComponentRef<S> {
+    /**
+     * Handles the given arguments.
+     * @param c a Component
+     * @param ref the service reference
+     */
+    void accept(Component c, ServiceReference<S> ref);
+
+    default CbComponentRef<S> andThen(CbComponentRef<S> after) {
+        Objects.requireNonNull(after);
+        return (Component c, ServiceReference<S> ref) -> {
+            accept(c, ref);
+            after.accept(c, ref);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentRefService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentRefService.java
new file mode 100644
index 0000000..adf982d
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentRefService.java
@@ -0,0 +1,30 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(Component, ServiceReference, Service) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbComponentRefService<S> {
+    /**
+     * Handles the given arguments.
+     * @param c a Component
+     * @param ref the service reference
+     * @param service the service
+     */
+    void accept(Component c, ServiceReference<S> ref, S service);
+
+    default CbComponentRefService<S> andThen(CbComponentRefService<S> after) {
+        Objects.requireNonNull(after);
+        return (Component c, ServiceReference<S> ref, S service) -> {
+            accept(c, ref, service);
+            after.accept(c, ref, service);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentRefServiceRefService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentRefServiceRefService.java
new file mode 100644
index 0000000..6ea5e2a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentRefServiceRefService.java
@@ -0,0 +1,32 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(Component, ServiceReference, Service, ServiceReference, Service) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbComponentRefServiceRefService<S> {
+    /**
+     * Handles the given arguments
+     * @param c a Component
+     * @param oldRef an old swapped service reference
+     * @param old an old swapped service
+     * @param replaceRef the new service reference
+     * @param replace the new service
+     */
+    void accept(Component c, ServiceReference<S> oldRef, S old, ServiceReference<S> replaceRef, S replace);
+
+    default CbComponentRefServiceRefService<S> andThen(CbComponentRefServiceRefService<S> after) {
+        Objects.requireNonNull(after);
+        return (Component c, ServiceReference<S> oldRef, S old, ServiceReference<S> replaceRef, S replace) -> {
+            accept(c, oldRef, old, replaceRef, replace);
+            after.accept(c, oldRef, old, replaceRef, replace);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentService.java
new file mode 100644
index 0000000..7ddbe53
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentService.java
@@ -0,0 +1,28 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+
+/**
+ * Represents a callback(Component, Service) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbComponentService<S> {
+    /**
+     * Handles the given arguments
+     * @param c the component
+     * @param service the service
+     */
+    void accept(Component c, S service);
+
+    default CbComponentService<S> andThen(CbComponentService<S> after) {
+        Objects.requireNonNull(after);
+        return (Component c, S service) -> {
+            accept(c, service);
+            after.accept(c, service);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentServiceService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentServiceService.java
new file mode 100644
index 0000000..cf8190a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbComponentServiceService.java
@@ -0,0 +1,29 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+
+/**
+ * Represents a callback(Component, Service, Service) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbComponentServiceService<S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param c the component
+     * @param old the old service
+     * @param replace the new service
+     */
+    void accept(Component c, S old, S replace);
+
+    default CbComponentServiceService<S> andThen(CbComponentServiceService<S> after) {
+        Objects.requireNonNull(after);
+        return (Component c, S old, S replace) -> {
+            accept(c, old, replace);
+            after.accept(c, old, replace);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbConsumer.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbConsumer.java
new file mode 100644
index 0000000..403ec7a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbConsumer.java
@@ -0,0 +1,26 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+/**
+ * Represents a callback(T param) on an Object instance.
+ * 
+ * @param T the type of the callback parameter.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbConsumer<T> extends SerializableLambda {
+    /**
+     * Handles the given argument
+     * @param t the argument
+     */
+    void accept(T t);
+
+    default CbConsumer<T> andThen(CbConsumer<? super T> after) {
+        Objects.requireNonNull(after);
+        return (T t) -> {
+            accept(t);
+            after.accept(t);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbDictionary.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbDictionary.java
new file mode 100644
index 0000000..dda1178
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbDictionary.java
@@ -0,0 +1,26 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Dictionary;
+import java.util.Objects;
+
+/**
+ * Represents a callback(Dictionary) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbDictionary {
+    /**
+     * Handles the given argument.
+     * @param conf the properties
+     */
+    void accept(Dictionary<String, Object> conf);
+
+    default CbDictionary andThen(CbDictionary after) {
+        Objects.requireNonNull(after);
+        return (Dictionary<String, Object> conf) -> {
+            accept(conf);
+            after.accept(conf);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbFuture.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbFuture.java
new file mode 100644
index 0000000..bab63af
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbFuture.java
@@ -0,0 +1,25 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+/**
+ * Represents a callback that accepts a the result of a CompletableFuture. The callback is invoked on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbFuture<F> {
+    /**
+     * Handles the result of a CompletableFuture operation.
+     * @param future the result of a CompletableFuture operation.
+     */
+    void accept(F future);
+
+    default CbFuture<F> andThen(CbFuture<? super F> after) {
+        Objects.requireNonNull(after);
+        return (F f) -> {
+            accept(f);
+            after.accept(f);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbRef.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbRef.java
new file mode 100644
index 0000000..6e5425c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbRef.java
@@ -0,0 +1,26 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(ServiceReference) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbRef<S> {
+    /**
+     * Handles the given argument
+     * @param ref a service reference
+     */
+    void accept(ServiceReference<S> ref);
+
+    default CbRef<S> andThen(CbRef<S> after) {
+        Objects.requireNonNull(after);
+        return (ServiceReference<S> ref) -> {
+            after.accept(ref);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbRefService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbRefService.java
new file mode 100644
index 0000000..ca795f4
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbRefService.java
@@ -0,0 +1,28 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(ServiceReference, Service) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbRefService<S> {
+    /**
+     * Handles the given arguments.
+     * @param ref a Service Reference
+     * @param service a Service
+     */
+    void accept(ServiceReference<S> ref, S service);
+
+    default CbRefService<S> andThen(CbRefService<S> after) {
+        Objects.requireNonNull(after);
+        return (ServiceReference<S> ref, S service) -> {
+            accept(ref, service);
+            after.accept(ref, service);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbRefServiceRefService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbRefServiceRefService.java
new file mode 100644
index 0000000..7917ea3
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbRefServiceRefService.java
@@ -0,0 +1,30 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(ServiceReference, Service, ServiceReference, Service) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbRefServiceRefService<S> {
+    /**
+     * Handles the given arguments
+     * @param oldRef a service reference
+     * @param old a service
+     * @param replaceRef a service reference
+     * @param replace a service
+     */
+    void accept(ServiceReference<S> oldRef, S old, ServiceReference<S> replaceRef, S replace);
+
+    default CbRefServiceRefService<S> andThen(CbRefServiceRefService<S> after) {
+        Objects.requireNonNull(after);
+        return (ServiceReference<S> oldRef, S old, ServiceReference<S> replaceRef, S replace) -> {
+            accept(oldRef, old, replaceRef, replace);
+            after.accept(oldRef, old, replaceRef, replace);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbService.java
new file mode 100644
index 0000000..98ca2ab
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbService.java
@@ -0,0 +1,25 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+/**
+ * Represents a callback(Service) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbService<S> {
+    /**
+     * Handles the given argument.
+     * @param service a Service
+     */
+    void accept(S service);
+
+    default CbService<S> andThen(CbService<S> after) {
+        Objects.requireNonNull(after);
+        return (S service) -> {
+            accept(service);
+            after.accept(service);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbServiceDict.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbServiceDict.java
new file mode 100644
index 0000000..0d88a18
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbServiceDict.java
@@ -0,0 +1,27 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Dictionary;
+import java.util.Objects;
+
+/**
+ * Represents a callback(Service, Dictionary) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbServiceDict<S> {
+    /**
+     * Handles the given arguments.
+     * @param service a Service
+     * @param properties a Dictionary
+     */
+    void accept(S service, Dictionary<String, Object> properties);
+
+    default CbServiceDict<S> andThen(CbServiceDict<S> after) {
+        Objects.requireNonNull(after);
+        return (S service, Dictionary<String, Object> properties) -> {
+            accept(service, properties);
+            after.accept(service, properties);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbServiceMap.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbServiceMap.java
new file mode 100644
index 0000000..ae1d6c0
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbServiceMap.java
@@ -0,0 +1,27 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Represents a callback(Service, Map) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbServiceMap<S> {
+    /**
+     * Handles the given arguments.
+     * @param service a Service 
+     * @param properties a Map
+     */
+    void accept(S service, Map<String, Object> properties);
+
+    default CbServiceMap<S> andThen(CbServiceMap<S> after) {
+        Objects.requireNonNull(after);
+        return (S service, Map<String, Object> properties) -> {
+            accept(service, properties);
+            after.accept(service, properties);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbServiceService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbServiceService.java
new file mode 100644
index 0000000..02c4d94
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbServiceService.java
@@ -0,0 +1,26 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+/**
+ * Represents a callback(Service, Service) on an Object instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbServiceService<S> extends SerializableLambda {
+    /**
+     * Handles the given argument
+     * @param old a Service
+     * @param replace a Service
+     */
+    void accept(S old, S replace);
+
+    default CbServiceService<S> andThen(CbServiceService<S> after) {
+        Objects.requireNonNull(after);
+        return (S old, S replace) -> {
+            accept(old, replace);
+            after.accept(old, replace);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeBundle.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeBundle.java
new file mode 100644
index 0000000..aa6c444
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeBundle.java
@@ -0,0 +1,29 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * Represents a callback(Bundle) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeBundle<T> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param bundle the callback parameter
+     */
+    void accept(T instance, Bundle bundle);
+
+    default CbTypeBundle<T> andThen(CbTypeBundle<? super T> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Bundle bundle) -> {
+            accept(instance, bundle);
+            after.accept(instance, bundle);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponent.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponent.java
new file mode 100644
index 0000000..9bed1bd
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponent.java
@@ -0,0 +1,29 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+
+/**
+ * Represents a callback(Component) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeComponent<T> extends SerializableLambda {
+    /**
+     * Handles the given arguments
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param component the callback parameter 
+     */
+    void accept(T instance, Component component);
+
+    default CbTypeComponent<T> andThen(CbTypeComponent<T> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Component component) -> {
+            accept(instance, component);
+            after.accept(instance, component);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentBundle.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentBundle.java
new file mode 100644
index 0000000..7bee3c3
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentBundle.java
@@ -0,0 +1,31 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+import org.osgi.framework.Bundle;
+
+/**
+ * Represents a callback(Component, Bundle) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeComponentBundle<T> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param component the first callback parameter
+     * @param bundle the second callback parameter
+     */
+    void accept(T instance, Component component, Bundle bundle);
+
+    default CbTypeComponentBundle<T> andThen(CbTypeComponentBundle<? super T> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Component component, Bundle bundle) -> {
+            accept(instance, component, bundle);
+            after.accept(instance, component, bundle);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentDictionary.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentDictionary.java
new file mode 100644
index 0000000..f84c71b
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentDictionary.java
@@ -0,0 +1,31 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Dictionary;
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+
+/**
+ * Represents a callback(Component, Dictionary) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeComponentDictionary<T> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param component the first callback parameter
+     * @param conf the second callback parameter
+     */
+    void accept(T instance, Component component, Dictionary<String, Object> conf);
+
+    default CbTypeComponentDictionary<T> andThen(CbTypeComponentDictionary<? super T> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Component component, Dictionary<String, Object> conf) -> {
+            accept(instance, component, conf);
+            after.accept(instance, component, conf);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentRef.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentRef.java
new file mode 100644
index 0000000..19bcb7d
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentRef.java
@@ -0,0 +1,31 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(Component, ServiceReference) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeComponentRef<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param c the first callback parameter
+     * @param ref the second callback parameter
+     */
+    void accept(T instance, Component c, ServiceReference<S> ref);
+
+    default CbTypeComponentRef<T, S> andThen(CbTypeComponentRef<T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Component c, ServiceReference<S> ref) -> {
+            accept(instance, c, ref);
+            after.accept(instance, c, ref);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentRefService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentRefService.java
new file mode 100644
index 0000000..c11e1a5
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentRefService.java
@@ -0,0 +1,32 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(Component, ServiceReference, Service) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeComponentRefService<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param c the first callback parameter
+     * @param ref the second callback parameter
+     * @param service the third callback parameter
+     */
+    void accept(T instance, Component c, ServiceReference<S> ref, S service);
+
+    default CbTypeComponentRefService<T, S> andThen(CbTypeComponentRefService<T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Component c, ServiceReference<S> ref, S service) -> {
+            accept(instance, c, ref, service);
+            after.accept(instance, c, ref, service);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentRefServiceRefService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentRefServiceRefService.java
new file mode 100644
index 0000000..43ac90a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentRefServiceRefService.java
@@ -0,0 +1,35 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(Component, ServiceReference, Service, ServiceReference, Service) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeComponentRefServiceRefService<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param c first callback param
+     * @param oldRef second callback param
+     * @param old third callback param
+     * @param replaceRef fourth callback param
+     * @param replace fifth callback param
+     */
+    void accept(T instance, Component c, ServiceReference<S> oldRef, S old, ServiceReference<S> replaceRef, S replace);
+
+    default CbTypeComponentRefServiceRefService<T, S> andThen(CbTypeComponentRefServiceRefService<? super T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Component c, ServiceReference<S> oldRef, S old, ServiceReference<S> replaceRef,
+            S replace) -> {
+            accept(instance, c, oldRef, old, replaceRef, replace);
+            after.accept(instance, c, oldRef, old, replaceRef, replace);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentService.java
new file mode 100644
index 0000000..705533d
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentService.java
@@ -0,0 +1,30 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+
+/**
+ * Represents a callback(Component, Service) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeComponentService<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param c first callback param
+     * @param service second callback param
+     */
+    void accept(T instance, Component c, S service);
+
+    default CbTypeComponentService<T, S> andThen(CbTypeComponentService<T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Component c, S s) -> {
+            accept(instance, c, s);
+            after.accept(instance, c, s);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentServiceDict.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentServiceDict.java
new file mode 100644
index 0000000..3fe4403
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentServiceDict.java
@@ -0,0 +1,32 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Dictionary;
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+
+/**
+ * Represents a callback(Component, ServiceReference, Dictionary) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeComponentServiceDict<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param c first callback param
+     * @param service second callback param
+     * @param props third callback param
+     */
+    void accept(T instance, Component c, S service, Dictionary<String, Object> props);
+
+    default CbTypeComponentServiceDict<T, S> andThen(CbTypeComponentServiceDict<T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Component c, S s, Dictionary<String, Object> props) -> {
+            accept(instance, c, s, props);
+            after.accept(instance, c, s, props);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentServiceMap.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentServiceMap.java
new file mode 100644
index 0000000..509cdc4
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentServiceMap.java
@@ -0,0 +1,32 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Map;
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+
+/**
+ * Represents a callback(Component, ServiceReference, Service, Service Reference, Service) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeComponentServiceMap<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param c first callback param
+     * @param service second callback param
+     * @param props third callback param
+     */
+    void accept(T instance, Component c, S service, Map<String, Object> props);
+
+    default CbTypeComponentServiceMap<T, S> andThen(CbTypeComponentServiceMap<T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Component c, S s, Map<String, Object> props) -> {
+            accept(instance, c, s, props);
+            after.accept(instance, c, s, props);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentServiceService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentServiceService.java
new file mode 100644
index 0000000..d234a91
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeComponentServiceService.java
@@ -0,0 +1,31 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.apache.felix.dm.Component;
+
+/**
+ * Represents a callback(Component, Service, Service) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeComponentServiceService<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param c first callback param
+     * @param old second callback param
+     * @param replace third callback param
+     */ 
+    void accept(T instance, Component c, S old, S replace);
+
+    default CbTypeComponentServiceService<T, S> andThen(CbTypeComponentServiceService<? super T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Component c, S old, S replace) -> {
+            accept(instance, c, old, replace);
+            after.accept(instance, c, old, replace);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeDictionary.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeDictionary.java
new file mode 100644
index 0000000..8d4ceb1
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeDictionary.java
@@ -0,0 +1,28 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Dictionary;
+import java.util.Objects;
+
+/**
+ * Represents a callback(Dictionary) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeDictionary<T> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param conf first callback param
+     */
+    void accept(T instance, Dictionary<String, Object> conf);
+
+    default CbTypeDictionary<T> andThen(CbTypeDictionary<? super T> after) {
+        Objects.requireNonNull(after);
+        return (T instance, Dictionary<String, Object> conf) -> {
+            accept(instance, conf);
+            after.accept(instance, conf);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeFuture.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeFuture.java
new file mode 100644
index 0000000..54b0d72
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeFuture.java
@@ -0,0 +1,28 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+/**
+ * Represents a callback that accepts the result of a CompletableFuture operation. The callback is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * The type of the result of the CompletableFuture is represented by the F generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeFuture<T, F> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param future the result of a CompletableFuture operation.
+     */
+    void accept(T instance, F future);
+
+    default CbTypeFuture<T, F> andThen(CbTypeFuture<? super T, F> after) {
+        Objects.requireNonNull(after);
+        return (T instance, F future) -> {
+            accept(instance, future);
+            after.accept(instance, future);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeRef.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeRef.java
new file mode 100644
index 0000000..36fa87c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeRef.java
@@ -0,0 +1,29 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(ServiceReference) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeRef<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param service first callback param
+     */
+    void accept(T instance, ServiceReference<S> service);
+
+    default CbTypeRef<T, S> andThen(CbTypeRef<? super T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, ServiceReference<S> ref) -> {
+            accept(instance, ref);
+            after.accept(instance, ref);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeRefService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeRefService.java
new file mode 100644
index 0000000..099416d
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeRefService.java
@@ -0,0 +1,30 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(ServiceReference, Service) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeRefService<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param ref first callback param
+     * @param service second callback param
+     */
+    void accept(T instance, ServiceReference<S> ref, S service);
+
+    default CbTypeRefService<T, S> andThen(CbTypeRefService<? super T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, ServiceReference<S> ref, S service) -> {
+            accept(instance, ref, service);
+            after.accept(instance, ref, service);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeRefServiceRefService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeRefServiceRefService.java
new file mode 100644
index 0000000..ccb9142
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeRefServiceRefService.java
@@ -0,0 +1,32 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Represents a callback(ServiceReference, Service, ServiceReference, Service) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeRefServiceRefService<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param oldRef first callback param
+     * @param old second callback param
+     * @param replaceRef third callback param
+     * @param replace fourth callback param
+     */
+    void accept(T instance, ServiceReference<S> oldRef, S old, ServiceReference<S> replaceRef, S replace);
+
+    default CbTypeRefServiceRefService<T, S> andThen(CbTypeRefServiceRefService<? super T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, ServiceReference<S> oldRef, S old, ServiceReference<S> replaceRef, S replace) -> {
+            accept(instance, oldRef, old, replaceRef, replace);
+            after.accept(instance, oldRef, old, replaceRef, replace);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeService.java
new file mode 100644
index 0000000..01f518b
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeService.java
@@ -0,0 +1,27 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+/**
+ * Represents a callback(Service) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeService<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param service first callback param
+     */
+    void accept(T instance, S service);
+
+    default CbTypeFuture<T, S> andThen(CbTypeFuture<? super T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, S service) -> {
+            accept(instance, service);
+            after.accept(instance, service);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeServiceDict.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeServiceDict.java
new file mode 100644
index 0000000..01c8abb
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeServiceDict.java
@@ -0,0 +1,29 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Dictionary;
+import java.util.Objects;
+
+/**
+ * Represents a callback(Component, Dictionary) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeServiceDict<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param service first callback param
+     * @param properties second callback param
+     */
+    void accept(T instance, S service, Dictionary<String, Object> properties);
+
+    default CbTypeServiceDict<T, S> andThen(CbTypeServiceDict<? super T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, S service, Dictionary<String, Object> properties) -> {
+            accept(instance, service, properties);
+            after.accept(instance, service, properties);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeServiceMap.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeServiceMap.java
new file mode 100644
index 0000000..bfe875e
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeServiceMap.java
@@ -0,0 +1,29 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Represents a callback(Component, Map) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeServiceMap<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param service first callback param
+     * @param properties second callback param
+     */
+    void accept(T instance, S service, Map<String, Object> properties);
+
+    default CbTypeServiceMap<T, S> andThen(CbTypeServiceMap<? super T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, S service, Map<String, Object> properties) -> {
+            accept(instance, service, properties);
+            after.accept(instance, service, properties);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeServiceService.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeServiceService.java
new file mode 100644
index 0000000..a81aa72
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/CbTypeServiceService.java
@@ -0,0 +1,28 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.util.Objects;
+
+/**
+ * Represents a callback(Service, Service) that is invoked on a Component implementation class. 
+ * The type of the class on which the callback is invoked on is represented by the T generic parameter.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@FunctionalInterface
+public interface CbTypeServiceService<T, S> extends SerializableLambda {
+    /**
+     * Handles the given arguments.
+     * @param instance the Component implementation instance on which the callback is invoked on. 
+     * @param old first callback param
+     * @param replace second callback param
+     */
+    void accept(T instance, S old, S replace);
+
+    default CbTypeServiceService<T, S> andThen(CbTypeServiceService<? super T, S> after) {
+        Objects.requireNonNull(after);
+        return (T instance, S old, S replace) -> {
+            accept(instance, old, replace);
+            after.accept(instance, old, replace);
+        };
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/SerializableLambda.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/SerializableLambda.java
new file mode 100644
index 0000000..b9427eb
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/SerializableLambda.java
@@ -0,0 +1,9 @@
+package org.apache.felix.dm.lambda.callbacks;
+
+import java.io.Serializable;
+
+/**
+ * Base interface for serializable lambdas. Some lambda must be serializable in order to allow to introspect their type and method signatures.
+ */
+public interface SerializableLambda extends Serializable {
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/packageinfo b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/packageinfo
new file mode 100644
index 0000000..9ad81f6
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/callbacks/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/AdapterBase.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/AdapterBase.java
new file mode 100644
index 0000000..c884793
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/AdapterBase.java
@@ -0,0 +1,338 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.Dictionary;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import org.apache.felix.dm.lambda.BundleDependencyBuilder;
+import org.apache.felix.dm.lambda.ComponentBuilder;
+import org.apache.felix.dm.lambda.ConfigurationDependencyBuilder;
+import org.apache.felix.dm.lambda.FluentProperties;
+import org.apache.felix.dm.lambda.FutureDependencyBuilder;
+import org.apache.felix.dm.lambda.ServiceDependencyBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbComponent;
+import org.apache.felix.dm.lambda.callbacks.CbConsumer;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponent;
+
+/**
+ * Methods common to extended components like adapters or aspects.
+ * 
+ * TODO javadoc
+ */
+@SuppressWarnings({"unchecked"})
+public interface AdapterBase<B extends ComponentBuilder<B>> extends ComponentBuilder<B> {
+	
+    void andThenBuild(Consumer<ComponentBuilder<?>> builder);
+    
+    default B impl(Object impl) {
+        andThenBuild(compBuilder -> compBuilder.impl(impl));
+        return (B) this;
+    }
+    
+    default <U> B impl(Class<U> implClass) {        
+        andThenBuild(compBuilder -> compBuilder.impl(implClass));
+        return (B) this;
+    }
+
+    default B factory(Object factory, String createMethod) {
+        andThenBuild(compBuilder -> compBuilder.factory(factory, createMethod));
+        return (B) this;
+    }
+
+    default B factory(Supplier<?> create) {        
+        andThenBuild(compBuilder -> compBuilder.factory(create));
+        return (B) this;
+    }
+    
+    default <U, V> B factory(Supplier<U> factory, Function<U, V> create) {        
+        andThenBuild(compBuilder -> compBuilder.factory(factory, create));
+        return (B) this;
+    }
+        
+    default B factory(Supplier<?> factory, Supplier<Object[]> getComposition) {        
+        andThenBuild(compBuilder -> compBuilder.factory(factory, getComposition));
+        return (B) this;
+    }
+
+    default <U> B factory(Supplier<U> factory, Function<U, ?> create, Function<U, Object[]> getComposition) {       
+        andThenBuild(compBuilder -> compBuilder.factory(factory, create, getComposition));
+        return (B) this;
+    }
+
+    default B provides(Class<?>  iface) {
+        andThenBuild(compBuilder -> compBuilder.provides(iface));
+        return (B) this;
+    }
+    
+    default B provides(Class<?>  iface, String name, Object value, Object ... rest) {
+        andThenBuild(compBuilder -> compBuilder.provides(iface, name, value, rest));
+        return (B) this;
+    }
+    
+    default B provides(Class<?>  iface, FluentProperties ... properties) {
+        andThenBuild(compBuilder -> compBuilder.provides(iface, properties));
+        return (B) this;
+    }
+    
+    default B provides(Class<?>  iface, Dictionary<?,?> properties) {
+        andThenBuild(compBuilder -> compBuilder.provides(iface, properties));
+        return (B) this;
+    }
+    
+    default B provides(Class<?>[] ifaces) {
+        andThenBuild(compBuilder -> compBuilder.provides(ifaces));
+        return (B) this;
+    }
+    
+    default B provides(Class<?>[] ifaces, String name, Object value, Object ... rest) {
+        andThenBuild(compBuilder -> compBuilder.provides(ifaces, name, value, rest));
+        return (B) this;  
+    }
+    
+    default B provides(Class<?>[] ifaces, FluentProperties ... properties) {
+        andThenBuild(compBuilder -> compBuilder.provides(ifaces, properties));
+        return (B) this;
+    }
+    
+    default B provides(Class<?>[] ifaces, Dictionary<?,?> properties) {
+        andThenBuild(compBuilder -> compBuilder.provides(ifaces, properties));
+        return (B) this;
+    }
+    
+    default B provides(String  iface) {
+        andThenBuild(compBuilder -> compBuilder.provides(iface));
+        return (B) this;
+    }
+    
+    default B provides(String  iface, String name, Object value, Object ... rest) {
+        andThenBuild(compBuilder -> compBuilder.provides(iface, name, value, rest));
+        return (B) this;
+    }
+    
+    default B provides(String  iface, FluentProperties ... properties) {
+        andThenBuild(compBuilder -> compBuilder.provides(iface, properties));
+        return (B) this;
+    }
+    
+    default B provides(String  iface, Dictionary<?,?> properties) {
+        andThenBuild(compBuilder -> compBuilder.provides(iface, properties));
+        return (B) this;
+    }
+    
+    default B provides(String[] ifaces) {
+        andThenBuild(compBuilder -> compBuilder.provides(ifaces));
+        return (B) this;
+    }
+    
+    default B provides(String[] ifaces, String name, Object value, Object ... rest) {
+        andThenBuild(compBuilder -> compBuilder.provides(ifaces, name, value, rest));
+        return (B) this;  
+    }
+    
+    default B provides(String[] ifaces, FluentProperties ... properties) {
+        andThenBuild(compBuilder -> compBuilder.provides(ifaces, properties));
+        return (B) this;
+    }
+    
+    default B provides(String[] ifaces, Dictionary<?,?> properties) {
+        andThenBuild(compBuilder -> compBuilder.provides(ifaces, properties));
+        return (B) this;
+    }
+
+    default B properties(Dictionary<?, ?> properties) {
+        andThenBuild(compBuilder -> compBuilder.properties(properties));
+        return (B) this;
+    }
+
+    default B properties(String name, Object value, Object ... rest) {
+        andThenBuild(compBuilder -> compBuilder.properties(name, value, rest));
+        return (B) this;
+    }
+    
+    default B properties(FluentProperties ...properties) {
+        andThenBuild(compBuilder -> compBuilder.properties(properties));
+        return (B) this;
+    }
+    
+    default B withSrv(Class<?> service, String filter) {
+        andThenBuild(compBuilder -> compBuilder.withSrv(service, filter));
+        return (B) this;
+    }
+
+    default B withSrv(Class<?> ... services) {
+        andThenBuild(compBuilder -> compBuilder.withSrv(services));
+        return (B) this;
+    }
+
+    default <U> B withSrv(Class<U> service, Consumer<ServiceDependencyBuilder<U>> consumer) {
+        andThenBuild(compBuilder -> compBuilder.withSrv(service, consumer));
+        return (B) this;
+    }
+    
+    default B withCnf(Consumer<ConfigurationDependencyBuilder> consumer) {
+        andThenBuild(compBuilder -> compBuilder.withCnf(consumer));
+        return (B) this;
+    }
+    
+    default B withBundle(Consumer<BundleDependencyBuilder> consumer) {
+        andThenBuild(compBuilder -> compBuilder.withBundle(consumer));
+        return (B) this;
+    }
+    
+    default <U> B withFuture(CompletableFuture<U> future, Consumer<FutureDependencyBuilder<U>> consumer) {
+        andThenBuild(compBuilder -> compBuilder.withFuture(future, consumer));
+        return (B) this;
+    }
+    
+    default B init(String callback) {
+        andThenBuild(compBuilder -> compBuilder.init(callback));
+        return (B) this;
+    }
+    
+    default B start(String callback) {
+        andThenBuild(compBuilder -> compBuilder.start(callback));
+        return (B) this;
+    }
+
+    default B stop(String callback) {
+        andThenBuild(compBuilder -> compBuilder.stop(callback));
+        return (B) this;
+    }
+
+    default B destroy(String callback) {
+        andThenBuild(compBuilder -> compBuilder.destroy(callback));
+        return (B) this;
+    }
+    
+    default B init(Object callbackInstance, String callback) {
+        andThenBuild(compBuilder -> compBuilder.init(callbackInstance, callback));
+        return (B) this;
+    }
+    
+    default B start(Object callbackInstance, String callback) {
+        andThenBuild(compBuilder -> compBuilder.start(callbackInstance, callback));
+        return (B) this;
+    }
+
+    default B stop(Object callbackInstance, String callback) {
+        andThenBuild(compBuilder -> compBuilder.stop(callbackInstance, callback));
+        return (B) this;
+    }
+
+    default B destroy(Object callbackInstance, String callback) {
+        andThenBuild(compBuilder -> compBuilder.destroy(callbackInstance, callback));
+        return (B) this;
+    }
+    
+    default <U> B init(CbConsumer<U> callback) {
+        andThenBuild(compBuilder -> compBuilder.init(callback));
+        return (B) this;
+    }
+    
+    default <U> B start(CbConsumer<U> callback) {
+        andThenBuild(compBuilder -> compBuilder.start(callback));
+        return (B) this;
+    }
+
+    default <U> B stop(CbConsumer<U> callback) {
+        andThenBuild(compBuilder -> compBuilder.stop(callback));
+        return (B) this;
+    }
+
+    default <U> B destroy(CbConsumer<U> callback) {
+        andThenBuild(compBuilder -> compBuilder.destroy(callback));
+        return (B) this;
+    }
+        
+    default <U> B init(CbTypeComponent<U> callback) {
+        andThenBuild(compBuilder -> compBuilder.init(callback));
+        return (B) this;
+    }
+        
+    default <U> B start(CbTypeComponent<U> callback) {
+        andThenBuild(compBuilder -> compBuilder.start(callback));
+        return (B) this;
+    }
+        
+    default <U> B stop(CbTypeComponent<U> callback) {
+        andThenBuild(compBuilder -> compBuilder.stop(callback));
+        return (B) this;
+    }
+        
+    default <U> B destroy(CbTypeComponent<U> callback) {
+        andThenBuild(compBuilder -> compBuilder.destroy(callback));
+        return (B) this;
+    }
+        
+    default B initInstance(Runnable callback) {
+        andThenBuild(compBuilder -> compBuilder.initInstance(callback));
+        return (B) this;
+    }
+        
+    default B startInstance(Runnable callback) {
+        andThenBuild(compBuilder -> compBuilder.startInstance(callback));
+        return (B) this;
+    }
+        
+    default B stopInstance(Runnable callback) {
+        andThenBuild(compBuilder -> compBuilder.stopInstance(callback));
+        return (B) this;
+    }
+        
+    default B destroyInstance(Runnable callback) {
+        andThenBuild(compBuilder -> compBuilder.destroyInstance(callback));
+        return (B) this;
+    }
+        
+    default B initInstance(CbComponent callback) {
+        andThenBuild(compBuilder -> compBuilder.initInstance(callback));
+        return (B) this;
+    }
+
+    default B startInstance(CbComponent callback) {
+        andThenBuild(compBuilder -> compBuilder.startInstance(callback));
+        return (B) this;
+    }
+
+    default B stopInstance(CbComponent callback) {
+        andThenBuild(compBuilder -> compBuilder.stopInstance(callback));
+        return (B) this;
+    }
+
+    default B destroyInstance(CbComponent callback) {
+        andThenBuild(compBuilder -> compBuilder.destroyInstance(callback));
+        return (B) this;
+    }
+
+   default B autoConfig(Class<?> clazz, boolean autoConfig) {
+        andThenBuild(compBuilder -> compBuilder.autoConfig(clazz, autoConfig));
+        return (B) this;
+    }
+    
+    default B autoConfig(Class<?> clazz, String field) {
+        andThenBuild(compBuilder -> compBuilder.autoConfig(clazz, field));
+        return (B) this;
+    }
+    
+    default B debug(String label) {
+        andThenBuild(compBuilder -> compBuilder.debug(label));
+        return (B) this;
+    }
+    
+    default B composition(String getCompositionMethod) {
+        andThenBuild(compBuilder -> compBuilder.composition(getCompositionMethod));
+        return (B) this;
+    }
+
+    default B composition(Object instance, String getCompositionMethod) {
+        andThenBuild(compBuilder -> compBuilder.composition(instance, getCompositionMethod));
+        return (B) this;
+    }
+    
+    default B composition(Supplier<Object[]> getCompositionMethod) {
+        andThenBuild(compBuilder -> compBuilder.composition(getCompositionMethod));
+        return (B) this;
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleAdapterBuilderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleAdapterBuilderImpl.java
new file mode 100644
index 0000000..8cd257e
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleAdapterBuilderImpl.java
@@ -0,0 +1,260 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.lambda.BundleAdapterBuilder;
+import org.apache.felix.dm.lambda.ComponentBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbBundle;
+import org.apache.felix.dm.lambda.callbacks.CbComponentBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentBundle;
+import org.osgi.framework.Bundle;
+
+public class BundleAdapterBuilderImpl implements AdapterBase<BundleAdapterBuilder>, BundleAdapterBuilder {
+    private Consumer<ComponentBuilder<?>> m_compBuilder = (compBuilder -> {});
+    protected final Map<Cb, List<MethodRef<Object>>> m_refs = new HashMap<>();
+    private DependencyManager m_dm;
+    private boolean m_autoAdd;
+    private String m_added;
+    private String m_changed;
+    private String m_removed;
+    private String m_filter;
+    private int m_stateMask = -1;
+    private boolean m_propagate;
+    private Object m_callbackInstance;
+    private String m_add;
+    private String m_change;
+    private String m_remove;
+
+    enum Cb {
+        ADD,        
+        CHG,        
+        REM
+    };
+
+    @FunctionalInterface
+    interface MethodRef<I> {
+        public void accept(I instance, Component c, Bundle b);
+    }
+
+    public BundleAdapterBuilderImpl(DependencyManager dm) {
+        m_dm = dm;
+    }
+    
+    public void andThenBuild(Consumer<ComponentBuilder<?>> builder) {
+        m_compBuilder = m_compBuilder.andThen(builder);
+    }
+
+    @Override
+    public BundleAdapterBuilderImpl autoAdd(boolean autoAdd) {
+        m_autoAdd = autoAdd;
+        return this;
+    }
+        
+    public boolean isAutoAdd() {
+        return m_autoAdd;
+    }
+
+    public BundleAdapterBuilder mask(int mask) {
+        m_stateMask = mask;
+        return this;
+    }
+    
+    public BundleAdapterBuilder filter(String filter) {
+        m_filter = filter;
+        return this;
+    }
+
+    public BundleAdapterBuilder propagate(boolean propagate) {
+        m_propagate = propagate;
+        return this;
+    }
+    
+    public BundleAdapterBuilder propagate() {
+        m_propagate = true;
+        return this;
+    }
+
+    public BundleAdapterBuilder cb(String ... callbacks) {
+        return cbi(null, callbacks);
+    }
+    
+    public BundleAdapterBuilder cbi(Object callbackInstance, String ... callbacks) {
+        switch (callbacks.length) {
+        case 1:
+            return cbi(callbackInstance, callbacks[0], null, null);
+            
+        case 2:
+            return cbi(callbackInstance, callbacks[0], null, callbacks[1]);
+            
+        case 3:
+            return cbi(callbackInstance, callbacks[0], callbacks[1], callbacks[2]);
+            
+        default:
+            throw new IllegalArgumentException("wrong number of arguments: " + callbacks.length + ". " +
+                "Possible arguments: [add], [add, remove] or [add, change, remove]");
+        }
+    }
+    
+    private BundleAdapterBuilder cbi(Object callbackInstance, String add, String change, String remove) {
+        checkHasNoMethodRefs();
+        m_callbackInstance = callbackInstance;
+        m_add = add;
+        m_change = change;
+        m_remove = remove;
+        return this;
+    }
+    
+    public <T> BundleAdapterBuilder cb(CbTypeBundle<T> add) {
+        return cb(add, (CbTypeBundle<T>) null, (CbTypeBundle<T>) null);
+    }
+
+    public <T> BundleAdapterBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> remove) {
+        return cb(add, null, remove);
+    }
+
+    public <T> BundleAdapterBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> change, CbTypeBundle<T> remove) {
+        if (add != null) {
+            Class<T> type = Helpers.getLambdaArgType(add, 0);
+            setComponentCallbackRef(Cb.ADD, type, (instance, component, bundle) -> { add.accept((T) instance, bundle); });
+        }
+        if (change != null) {
+            Class<T> type = Helpers.getLambdaArgType(change, 0);
+            setComponentCallbackRef(Cb.CHG, type, (instance, component, bundle) -> { change.accept((T) instance, bundle); });
+        }
+        if (remove != null) {
+            Class<T> type = Helpers.getLambdaArgType(remove, 0);
+            setComponentCallbackRef(Cb.REM, type, (instance, component, bundle) -> { remove.accept((T) instance, bundle); });
+        }
+        return this;
+    }
+    
+    public BundleAdapterBuilder cbi(CbBundle add) {
+        return cbi(add, null, null);
+    }
+
+    public BundleAdapterBuilder cbi(CbBundle add, CbBundle remove) {
+        return cbi(add, null, remove);
+    }
+    
+    public BundleAdapterBuilder cbi(CbBundle add, CbBundle change, CbBundle remove) {
+        if (add != null) setInstanceCallbackRef(Cb.ADD, (instance, component, bundle) -> { add.accept(bundle); });
+        if (change != null) setInstanceCallbackRef(Cb.CHG, (instance, component, bundle) -> { change.accept(bundle); });
+        if (remove != null) setInstanceCallbackRef(Cb.REM, (instance, component, bundle) -> { remove.accept(bundle); });
+        return this;
+    }
+    
+    public <T> BundleAdapterBuilder cb(CbTypeComponentBundle<T> add) {
+        return cb((CbTypeComponentBundle<T>) add, (CbTypeComponentBundle<T>) null, (CbTypeComponentBundle<T>) null);
+    }
+    
+    public <T> BundleAdapterBuilder cb(CbTypeComponentBundle<T> add, CbTypeComponentBundle<T> remove) {
+        return cb(add, null, remove);
+    }
+    
+    public <T> BundleAdapterBuilder cb(CbTypeComponentBundle<T> add, CbTypeComponentBundle<T> change, CbTypeComponentBundle<T> remove) {
+        if (add != null) {
+            Class<T> type = Helpers.getLambdaArgType(add, 0);
+            return setComponentCallbackRef(Cb.ADD, type, (instance, component, bundle) -> { add.accept((T) instance, component, bundle); });
+        }
+        if (change != null) {
+            Class<T> type = Helpers.getLambdaArgType(change, 0);
+            return setComponentCallbackRef(Cb.CHG, type, (instance, component, bundle) -> { change.accept((T) instance, component, bundle); });
+        }
+        if (remove != null) {
+            Class<T> type = Helpers.getLambdaArgType(remove, 0);
+            return setComponentCallbackRef(Cb.ADD, type, (instance, component, bundle) -> { remove.accept((T) instance, component, bundle); });
+        }
+        return this;
+    }
+    
+    public BundleAdapterBuilder cbi(CbComponentBundle add) {
+        return cbi(add, null, null);
+    }
+    
+    public BundleAdapterBuilder cbi(CbComponentBundle add, CbComponentBundle remove) {
+        return cbi(add, null, remove);
+    }
+
+    public BundleAdapterBuilder cbi(CbComponentBundle add, CbComponentBundle change, CbComponentBundle remove) {
+        if (add != null) setInstanceCallbackRef(Cb.ADD, (instance, component, bundle) -> { add.accept(component, bundle); });
+        if (change != null) setInstanceCallbackRef(Cb.CHG, (instance, component, bundle) -> { change.accept(component, bundle); });
+        if (remove != null) setInstanceCallbackRef(Cb.REM, (instance, component, bundle) -> { remove.accept(component, bundle); });
+        return this;
+    }
+
+    @Override
+    public Component build() { 
+        Component c = null;
+        
+        if (m_refs.size() > 0) {
+            @SuppressWarnings("unused")
+            Object wrapCallback = new Object() {
+                public void add(Component comp, Bundle bundle) {
+                    invokeMethodRefs(Cb.ADD, comp, bundle);
+                }
+                
+                public void change(Component comp, Bundle bundle) {
+                    invokeMethodRefs(Cb.CHG, comp, bundle);
+                }
+
+                public void remove(Component comp, Bundle bundle) {
+                    invokeMethodRefs(Cb.REM, comp, bundle);
+                }
+            };
+            c = m_dm.createBundleAdapterService(m_stateMask, m_filter, m_propagate, wrapCallback, "add", "change", "remove");
+        } else {
+            c = m_dm.createBundleAdapterService(m_stateMask, m_filter, m_propagate, m_callbackInstance, m_add, m_change, m_remove);
+        }
+        ComponentBuilderImpl cb = new ComponentBuilderImpl(c, false);
+        m_compBuilder.accept (cb);
+        return cb.build();        
+    }
+    
+    private <U> BundleAdapterBuilder setInstanceCallbackRef(Cb cbType, MethodRef<U> ref) {
+        checkHasNoReflectionCallbacks();
+        List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
+        list.add((instance, component, bundle) -> ref.accept(null, component, bundle));
+        return this;
+    }
+    
+    @SuppressWarnings("unchecked")
+    private <U> BundleAdapterBuilder setComponentCallbackRef(Cb cbType, Class<U> type, MethodRef<U> ref) {
+        checkHasNoReflectionCallbacks();
+        List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
+        list.add((instance, component, bundle) -> {
+            Object componentImpl = Stream.of(component.getInstances())
+                .filter(impl -> Helpers.getClass(impl).equals(type))
+                .findFirst()
+                .orElseThrow(() -> new IllegalStateException("The method reference " + ref + " does not match any available component impl classes."));           
+            ref.accept((U) componentImpl, component, bundle);
+        });
+        return this;
+    }
+    
+    private void invokeMethodRefs(Cb cbType, Component comp, Bundle bundle) {
+        m_refs.computeIfPresent(cbType, (k, mrefs) -> {
+            mrefs.forEach(mref -> mref.accept(null, comp, bundle));
+            return mrefs;
+         });
+     }
+
+    private void checkHasNoMethodRefs() {
+        if (m_refs.size() > 0) {
+            throw new IllegalStateException("Can't mix method references with reflection based callbacks");
+        }
+    }
+    
+    private void checkHasNoReflectionCallbacks() {
+        if (m_added != null || m_changed != null || m_removed != null) {
+            throw new IllegalStateException("Can't mix method references with reflection based callbacks");
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleDependencyBuilderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleDependencyBuilderImpl.java
new file mode 100644
index 0000000..fe77432
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleDependencyBuilderImpl.java
@@ -0,0 +1,359 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.BundleDependency;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.lambda.BundleDependencyBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbBundle;
+import org.apache.felix.dm.lambda.callbacks.CbComponentBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentBundle;
+import org.osgi.framework.Bundle;
+
+@SuppressWarnings("unchecked")
+public class BundleDependencyBuilderImpl implements BundleDependencyBuilder {
+	private String m_added;
+	private String m_changed;
+	private String m_removed;
+	private Object m_instance;
+	private boolean m_autoConfig = true;
+	private boolean m_autoConfigInvoked = false;
+	private boolean m_required = true;
+	private Bundle m_bundle;
+	private String m_filter;
+	private int m_stateMask = -1;
+	private boolean m_propagate;
+	private Object m_propagateInstance;
+	private String m_propagateMethod;
+	private Supplier<Dictionary<?, ?>> m_propagateSupplier;
+	private final Component m_component;
+    
+    enum Cb {
+        ADD,        
+        CHG,        
+        REM
+    };
+
+	private final Map<Cb, List<MethodRef<Object>>> m_refs = new HashMap<>();
+
+    @FunctionalInterface
+    interface MethodRef<I> {
+        public void accept(I instance, Component c, Bundle bundle);
+    }
+
+	/**
+	 * Class used to call a supplier that returns Propagated properties
+	 */
+	private class Propagate {
+		@SuppressWarnings("unused")
+		Dictionary<?, ?> propagate() {
+			return m_propagateSupplier.get();
+		}
+	}
+
+    public BundleDependencyBuilderImpl (Component component) {
+        m_component = component;
+    }
+
+    @Override
+    public BundleDependencyBuilder autoConfig(boolean autoConfig) {
+        m_autoConfig = autoConfig;
+        m_autoConfigInvoked = true;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder autoConfig() {
+        autoConfig(true);
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder required(boolean required) {
+        m_required = required;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder required() {
+        required(true);
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder bundle(Bundle bundle) {
+        m_bundle = bundle;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder filter(String filter) throws IllegalArgumentException {
+        m_filter = filter;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder mask(int mask) {
+        m_stateMask = mask;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder propagate(boolean propagate) {
+        m_propagate = propagate;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder propagate() {
+        propagate(true);
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder propagate(Object instance, String method) {
+        if (m_propagateSupplier != null || m_propagate) throw new IllegalStateException("Propagate callback already set.");
+        Objects.nonNull(method);
+        Objects.nonNull(instance);
+        m_propagateInstance = instance;
+        m_propagateMethod = method;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder propagate(Supplier<Dictionary<?, ?>> instance) {
+        if (m_propagateInstance != null || m_propagate) throw new IllegalStateException("Propagate callback already set.");
+        m_propagateSupplier = instance;
+        return this;
+    }
+        
+    public BundleDependencyBuilder cb(String ... callbacks) {
+        return cb(null, callbacks);
+    }
+    
+    @Override
+    public BundleDependencyBuilder cb(Object callbackInstance, String ... callbacks) {
+        switch (callbacks.length) {
+        case 1:
+            cbi(callbackInstance, callbacks[0], null, null);
+            break;
+            
+        case 2:
+            cbi(callbackInstance, callbacks[0], null, callbacks[1]);
+            break;
+            
+        case 3:
+            cbi(callbackInstance, callbacks[0], callbacks[1], callbacks[2]);
+            break;
+            
+        default:
+            throw new IllegalArgumentException("wrong number of arguments: " + callbacks.length + ". " +
+                "Possible arguments: [add], [add, remove] or [add, change, remove]");
+        }
+
+        return this;
+    }
+    
+    private BundleDependencyBuilder cbi(Object callbackInstance, String added, String changed, String removed) {
+        requiresNoMethodRefs();
+        m_instance = callbackInstance;
+        m_added = added != null ? added : m_added;
+        m_changed = changed != null ? changed : m_changed;
+        m_removed = removed != null ? removed : m_removed;
+        if (! m_autoConfigInvoked) m_autoConfig = false;
+        return this;
+    }
+
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeBundle<T> add) {
+        return cb(add, null, null);
+    }
+    
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> remove) {
+        return cb(add, null, remove);
+    }
+    
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> change, CbTypeBundle<T> remove) {
+        if (add != null) {
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, component, bundle) -> add.accept ((T) inst, bundle));
+        }
+        if (change != null) {
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, component, bundle) -> change.accept ((T) inst, bundle));
+        }
+        if (remove != null) {
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, component, bundle) -> remove.accept ((T) inst, bundle));
+        }
+        return this;
+    }
+
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeComponentBundle<T> add) {
+        return cb(add, null, null);
+    }
+    
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeComponentBundle<T> add, CbTypeComponentBundle<T> remove) {
+        return cb(add, null, remove);
+    }
+    
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeComponentBundle<T> add, CbTypeComponentBundle<T> change, CbTypeComponentBundle<T> remove) {
+        if (add != null) {
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, component, bundle) -> add.accept ((T) inst, component, bundle));
+        }
+        if (change != null) {
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, component, bundle) -> change.accept ((T) inst, component, bundle));
+        }
+        if (remove != null) {
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, component, bundle) -> remove.accept ((T) inst, component, bundle));
+        }
+        return this;  
+    }
+    
+    @Override
+    public BundleDependencyBuilder cbi(CbBundle add) {
+        return cbi(add, null, null);
+    }
+    
+    @Override
+    public BundleDependencyBuilder cbi(CbBundle add, CbBundle remove) {
+        return cbi(add, null, remove);
+    }
+    
+    @Override
+    public BundleDependencyBuilder cbi(CbBundle add, CbBundle change, CbBundle remove) {
+        if (add != null) setInstanceCallbackRef(Cb.ADD, (inst, component, bundle) -> add.accept(bundle));
+        if (change != null) setInstanceCallbackRef(Cb.CHG, (inst, component, bundle) -> change.accept(bundle));
+        if (remove != null) setInstanceCallbackRef(Cb.REM, (inst, component, bundle) -> remove.accept(bundle));
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder cbi(CbComponentBundle add) {
+        return cbi(add, null, null);
+    }
+    
+    @Override
+    public BundleDependencyBuilder cbi(CbComponentBundle add, CbComponentBundle remove) {
+        return cbi(add, null, remove);
+    }
+    
+    @Override
+    public BundleDependencyBuilder cbi(CbComponentBundle add, CbComponentBundle change, CbComponentBundle remove) {
+        if (add != null) setInstanceCallbackRef(Cb.ADD, (inst, component, bundle) -> add.accept(component, bundle));
+        if (change != null) setInstanceCallbackRef(Cb.CHG, (inst, component, bundle) -> change.accept(component, bundle));
+        if (remove != null) setInstanceCallbackRef(Cb.REM, (inst, component, bundle) -> remove.accept(component, bundle));
+        return this;
+    }
+
+	@Override
+	public BundleDependency build() {
+        DependencyManager dm = m_component.getDependencyManager();
+
+        BundleDependency dep = dm.createBundleDependency();
+        dep.setRequired(m_required);
+        
+        if (m_filter != null) {
+        	dep.setFilter(m_filter);
+        }
+        
+        if (m_bundle != null) {
+        	dep.setBundle(m_bundle);
+        }
+        
+        if (m_stateMask != -1) {
+        	dep.setStateMask(m_stateMask);
+        }
+        
+        if (m_propagate) {
+            dep.setPropagate(true);
+        } else if (m_propagateInstance != null) {
+            dep.setPropagate(m_propagateInstance, m_propagateMethod);
+        } else if (m_propagateSupplier != null) {
+        	dep.setPropagate(new Propagate(), "propagate");
+        }
+        
+        if (m_added != null || m_changed != null || m_removed != null) {
+            dep.setCallbacks(m_instance, m_added, m_changed, m_removed);
+        } else if (m_refs.size() > 0) {
+            Object cb = createCallbackInstance();
+            dep.setCallbacks(cb, "add", "change", "remove");
+        } 
+        
+        dep.setAutoConfig(m_autoConfig);
+        return dep;
+	}
+
+	private <T> BundleDependencyBuilder setInstanceCallbackRef(Cb cbType, MethodRef<T> ref) {
+		requiresNoStringCallbacks();
+		if (! m_autoConfigInvoked) m_autoConfig = false;
+		List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
+		list.add((instance, component, bundle) -> ref.accept(null, component, bundle));
+		return this;
+	}
+	
+	private <T> BundleDependencyBuilder setComponentCallbackRef(Cb cbType, Class<T> type, MethodRef<T> ref) {
+	    requiresNoStringCallbacks();
+		if (! m_autoConfigInvoked) m_autoConfig = false;
+		List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
+		list.add((instance, component, bundle) -> {
+            Object componentImpl = Stream.of(component.getInstances())
+                .filter(impl -> Helpers.getClass(impl).equals(type))
+                .findFirst()
+                .orElseThrow(() -> new IllegalStateException("The method reference " + ref + " does not match any available component impl classes."));           
+            ref.accept((T) componentImpl, component, bundle);
+		});
+		return this;
+	}
+	    
+	@SuppressWarnings("unused")
+	private Object createCallbackInstance() {
+		Object cb = null;
+
+		cb = new Object() {
+			void add(Component c, Bundle bundle) {
+				invokeMethodRefs(Cb.ADD, c, bundle);
+			}
+
+			void change(Component c, Bundle bundle) {
+				invokeMethodRefs(Cb.CHG, c, bundle);
+			}
+
+			void remove(Component c, Bundle bundle) {
+				invokeMethodRefs(Cb.REM, c, bundle);
+			}
+		};
+
+		return cb;
+	}
+
+	private void invokeMethodRefs(Cb cbType, Component c, Bundle bundle) {
+		m_refs.computeIfPresent(cbType, (k, mrefs) -> {
+			mrefs.forEach(mref -> mref.accept(null, c, bundle));
+			return mrefs;
+		});
+	}
+	
+	private void requiresNoStringCallbacks() {
+		if (m_added != null || m_changed != null || m_removed != null) {
+			throw new IllegalStateException("can't mix method references and string callbacks.");
+		}
+	}
+	
+	private void requiresNoMethodRefs() {
+		if (m_refs.size() > 0) {
+			throw new IllegalStateException("can't mix method references and string callbacks.");
+		}
+	}
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/CompletableFutureDependencyImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/CompletableFutureDependencyImpl.java
new file mode 100644
index 0000000..d41456f
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/CompletableFutureDependencyImpl.java
@@ -0,0 +1,241 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.context.AbstractDependency;
+import org.apache.felix.dm.context.DependencyContext;
+import org.apache.felix.dm.context.Event;
+import org.apache.felix.dm.context.EventType;
+import org.apache.felix.dm.lambda.FutureDependencyBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbFuture;
+import org.apache.felix.dm.lambda.callbacks.CbTypeFuture;
+import org.osgi.service.log.LogService;
+
+public class CompletableFutureDependencyImpl<F> extends AbstractDependency<CompletableFutureDependencyImpl<F>> implements FutureDependencyBuilder<F> {
+
+	private final CompletableFuture<F> m_future;
+	private Component m_comp;
+	private boolean m_async;
+	private Executor m_exec;
+    private CbFuture<F> m_accept = (future) -> {};
+    private CbTypeFuture<Object, F> m_accept2;
+    private Class<?> m_accept2Type;
+    
+	public CompletableFutureDependencyImpl(Component c, CompletableFuture<F> future) {
+		super.setRequired(true);
+		m_future = future;
+		m_comp = c;
+	}
+
+	/**
+	 * Create a new PathDependency from an existing prototype.
+	 * 
+	 * @param prototype
+	 *            the existing PathDependency.
+	 */
+	public CompletableFutureDependencyImpl(Component component, CompletableFutureDependencyImpl<F> prototype) {
+		super(prototype);
+		m_future = prototype.m_future;
+		m_comp = component;
+	}
+
+	@Override
+	public Dependency build() {
+		return this;
+	}
+
+	@Override
+    public FutureDependencyBuilder<F> cb(String callback) {
+	    return cbi(null, callback);
+	}
+	
+	@Override
+    public FutureDependencyBuilder<F> cbi(Object callbackInstance, String callback) {
+	    super.setCallbacks(callbackInstance, callback, null);
+	    return this;
+	}
+
+	@Override
+	public <T> FutureDependencyBuilder<F> cb(CbTypeFuture<T, ? super F> consumer) {
+	    return cb(consumer, false);
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public <T> FutureDependencyBuilder<F> cb(CbTypeFuture<T, ? super F> consumer, boolean async) {
+	    m_accept2Type = Helpers.getLambdaArgType(consumer, 0);;
+	    m_accept2 = (instance, result) -> consumer.accept((T) instance, result);
+	    m_async = async;
+	    return this;
+	}   
+
+	@Override
+	public <T> FutureDependencyBuilder<F> cb(CbTypeFuture<T, ? super F> consumer, Executor executor) {
+	    cb(consumer, true /* async */);
+	    m_exec = executor;
+	    return this;
+	}
+
+	@Override
+	public FutureDependencyBuilder<F> cbi(CbFuture<? super F> consumer) {
+	    cbi(consumer, false);
+		return this;
+	}
+	
+	@Override
+	public FutureDependencyBuilder<F> cbi(CbFuture<? super F> consumer, boolean async) {
+	    m_accept = m_accept.andThen(future -> consumer.accept(future));
+	    m_async = async;
+	    return this;
+	}   
+
+    @Override
+    public FutureDependencyBuilder<F> cbi(CbFuture<? super F> consumer, Executor executor) {
+        cbi(consumer, true /* async */);
+        m_exec = executor;
+        return this;
+    }
+
+	// ---------- DependencyContext interface ----------
+
+	@Override
+	public void start() {
+		try {
+			if (m_async) {
+				if (m_exec != null) {
+					m_future.whenCompleteAsync((result, error) -> completed(result, error), m_exec);
+				} else {
+					m_future.whenCompleteAsync((result, error) -> completed(result, error));
+				}
+			} else {
+				m_future.whenComplete((result, error) -> completed(result, error));
+			}
+		} catch (Throwable error) {
+			super.getComponentContext().getLogger().log(LogService.LOG_ERROR, "completable future failed", error);
+		}
+		super.start();
+	}
+
+	@Override
+	public DependencyContext createCopy() {
+		return new CompletableFutureDependencyImpl<F>(m_comp, this);
+	}
+
+	@Override
+	public Class<?> getAutoConfigType() {
+		return null; // we don't support auto config mode
+	}
+
+	// ---------- ComponentDependencyDeclaration interface -----------
+
+	/**
+	 * Returns the name of this dependency (a generic name with optional info
+	 * separated by spaces). The DM Shell will use this method when displaying
+	 * the dependency
+	 **/
+	@Override
+	public String getSimpleName() {
+		return m_future.toString();
+	}
+
+	/**
+	 * Returns the name of the type of this dependency. Used by the DM shell
+	 * when displaying the dependency.
+	 **/
+	@Override
+	public String getType() {
+		return "future";
+	}
+	
+	/**
+	 * Called by DM component implementation when all required dependencies are satisfied.
+	 */
+    @Override
+    public void invokeCallback(EventType type, Event ... events) {
+        try {
+            switch (type) {
+            case ADDED:
+                if (m_add != null) {
+                    // Inject result by reflection on a method name
+                    injectByReflection(events[0].getEvent());
+                    return;
+                }
+                F result = events[0].getEvent();
+                if (m_accept2 != null) {
+                    if (m_accept2Type != null) {
+                        // find the component instance that matches the given type
+                        Object componentInstance = Stream.of(getComponentContext().getInstances())
+                            .filter(instance -> Helpers.getClass(instance).equals(m_accept2Type))
+                            .findFirst()
+                            .orElseThrow(() -> new IllegalArgumentException(
+                                "accept callback is not on one of the component instances: " + m_accept2 + " (type=" + m_accept2Type + ")"));                                    
+
+                        m_accept2.accept(componentInstance, result);
+                    } else {
+                        // invoke a method in the main component instance that will handle the completed future.
+                        m_accept2.accept(getComponentContext().getInstance(), result);
+                    }
+                } else {
+                    // Just invoke the Consumer with the completed future
+                    m_accept.accept(result);
+                }
+                break;
+                
+            default:
+                break;
+            }
+        } catch (Throwable exc) {
+            super.getComponentContext().getLogger().log(LogService.LOG_ERROR, "completable future failed", exc);
+        }
+    }
+
+	// ---------- Private methods -----------
+
+    /**
+     * Triggers component activation when the future has completed.
+     * @param result
+     * @param error
+     */
+    private void completed(F result, Throwable error) {
+		if (error != null) {
+			super.getComponentContext().getLogger().log(LogService.LOG_ERROR, "completable future failed", error);
+		} else {
+		    // Will trigger component activation (if other dependencies are satisfied), and our invokeCallback method will then be called.
+		    m_component.handleEvent(this, EventType.ADDED, new Event(result));
+		}
+	}
+    
+    /**
+     * Injects the completed fiture result in a method by reflection.
+     * We try to find a method which has in its signature a parameter that is compatible with the future result
+     * (including any interfaces the result may implements).
+     * 
+     * @param result the result of the completable future.
+     */
+    private void injectByReflection(Object result) {
+        List<Class<?>> types = new ArrayList<>();
+        Class<?> currentClazz = result.getClass();
+        
+        while (currentClazz != null && currentClazz != Object.class) {
+            types.add(currentClazz);
+            Stream.of(currentClazz.getInterfaces()).forEach(types::add);
+            currentClazz = currentClazz.getSuperclass();
+        }
+        
+        Class<?>[][] classes = new Class<?>[types.size() + 1][1];
+        Object[][] results = new Object[types.size() + 1][1];
+        for (int i = 0; i < types.size(); i ++) {
+            classes[i] = new Class<?>[] { types.get(i) };
+            results[i] = new Object[] { result };
+        }
+        classes[types.size()] = new Class<?>[0];
+        results[types.size()] = new Object[0];        
+        m_component.invokeCallbackMethod(getInstances(), m_add, classes, results);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ComponentBuilderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ComponentBuilderImpl.java
new file mode 100644
index 0000000..73f2687
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ComponentBuilderImpl.java
@@ -0,0 +1,728 @@
+package org.apache.felix.dm.lambda.impl;
+
+import static org.apache.felix.dm.lambda.impl.ComponentBuilderImpl.ComponentCallback.DESTROY;
+import static org.apache.felix.dm.lambda.impl.ComponentBuilderImpl.ComponentCallback.INIT;
+import static org.apache.felix.dm.lambda.impl.ComponentBuilderImpl.ComponentCallback.START;
+import static org.apache.felix.dm.lambda.impl.ComponentBuilderImpl.ComponentCallback.STOP;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.lambda.BundleDependencyBuilder;
+import org.apache.felix.dm.lambda.ComponentBuilder;
+import org.apache.felix.dm.lambda.ConfigurationDependencyBuilder;
+import org.apache.felix.dm.lambda.DependencyBuilder;
+import org.apache.felix.dm.lambda.FluentProperties;
+import org.apache.felix.dm.lambda.FutureDependencyBuilder;
+import org.apache.felix.dm.lambda.ServiceDependencyBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbComponent;
+import org.apache.felix.dm.lambda.callbacks.CbConsumer;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponent;
+
+public class ComponentBuilderImpl implements ComponentBuilder<ComponentBuilderImpl> {
+    private final List<DependencyBuilder<?>> m_dependencyBuilders = new ArrayList<>();
+    private final Component m_component;
+    private final boolean m_componentUpdated;
+    private String[] m_serviceNames;
+    private Dictionary<Object, Object> m_properties;
+    private Object m_impl;
+    private Object m_factory;
+    private boolean m_factoryHasComposite;	
+    private boolean m_autoAdd = true;
+    protected final Map<ComponentCallback, List<MethodRef<Object>>> m_refs = new HashMap<>();
+    private Object m_compositionInstance;
+    private String m_compositionMethod;
+    private String m_init;
+    private String m_stop;
+    private String m_start;
+    private String m_destroy;
+    private Object m_callbackInstance;
+    private String m_factoryCreateMethod;
+    private boolean m_hasFactoryRef;   
+    private boolean m_hasFactory;   
+    
+    enum ComponentCallback { INIT, START, STOP, DESTROY };
+    
+    @FunctionalInterface
+    interface MethodRef<I> {
+        public void accept(I instance, Component c);
+    }
+
+    public ComponentBuilderImpl(DependencyManager dm) {
+        m_component = dm.createComponent();
+        m_componentUpdated = false;
+    }
+    
+    public ComponentBuilderImpl(Component component, boolean update) {
+        m_component = component;
+        m_componentUpdated = update;
+    }
+        
+    @Override
+    public ComponentBuilderImpl autoConfig(Class<?> clazz, boolean autoConfig) {
+        m_component.setAutoConfig(clazz, autoConfig);
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl autoConfig(Class<?> clazz, String instanceName) {
+        m_component.setAutoConfig(clazz, instanceName);
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl provides(Class<?> iface) {
+        m_serviceNames = new String[] {iface.getName()};
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl provides(Class<?>  iface, String name, Object value, Object ... rest) {
+        provides(iface);
+        properties(name, value, rest);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(Class<?>  iface, FluentProperties ... properties) {
+        provides(iface);
+        properties(properties);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(Class<?>  iface, Dictionary<?,?> properties) {
+        provides(iface);
+        properties(properties);
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl  provides(Class<?>[] ifaces) {
+        m_serviceNames = Stream.of(ifaces).map(c -> c.getName()).toArray(String[]::new);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(Class<?>[] ifaces, String name, Object value, Object ... rest) {
+        provides(ifaces);
+        properties(name, value, rest);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(Class<?>[] ifaces, FluentProperties ... properties) {
+        provides(ifaces);
+        properties(properties);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(Class<?>[] ifaces, Dictionary<?,?> properties) {
+        provides(ifaces);
+        properties(properties);
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl provides(String iface) {
+        m_serviceNames = new String[] {iface};
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl provides(String iface, String name, Object value, Object ... rest) {
+        provides(iface);
+        properties(name, value, rest);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(String iface, FluentProperties ... properties) {
+        provides(iface);
+        properties(properties);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(String  iface, Dictionary<?,?> properties) {
+        provides(iface);
+        properties(properties);
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl  provides(String[] ifaces) {
+        m_serviceNames = ifaces;
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(String[] ifaces, String name, Object value, Object ... rest) {
+        provides(ifaces);
+        properties(name, value, rest);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(String[] ifaces, FluentProperties ... properties) {
+        provides(ifaces);
+        properties(properties);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(String[] ifaces, Dictionary<?,?> properties) {
+        provides(ifaces);
+        properties(properties);
+        return this;
+    }    
+    
+    @SuppressWarnings("unchecked")
+    @Override
+    public ComponentBuilderImpl properties(Dictionary<?, ?> properties) {
+        m_properties = (Dictionary<Object, Object>) properties;
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl properties(String name, Object value, Object ... rest) {
+    	Objects.nonNull(name);
+    	Objects.nonNull(value);
+        Properties props = new Properties();
+        props.put(name,  value);
+        if ((rest.length & 1) != 0) {
+        	throw new IllegalArgumentException("Invalid number of specified properties (number of arguments must be even).");
+        }
+        for (int i = 0; i < rest.length - 1; i += 2) {
+            String k = rest[i].toString().trim();
+            Object v = rest[i+1];
+            props.put(k, v);
+        }
+        m_properties = props;
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl properties(FluentProperties ... properties) {
+    	Dictionary<Object, Object> props = new Hashtable<>();
+    	Stream.of(properties).forEach(property -> {
+    		String name = Helpers.getLambdaParameterName(property, 0);
+    		if (name.equals("arg0")) {
+    			throw new IllegalArgumentException("arg0 property name not supported"); 
+    		}
+    		Object value = property.apply(name);
+    		props.put(name, value);
+    	});
+        m_properties = props;
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl debug(String label) {
+        m_component.setDebug(label);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl autoAdd(boolean autoAdd) {
+        m_autoAdd = autoAdd;
+        return this;
+    }
+    
+    public ComponentBuilderImpl autoAdd() {
+        m_autoAdd = true;
+    	return this;
+    }
+
+    public boolean isAutoAdd() {
+        return m_autoAdd;
+    }
+
+    @Override
+    public ComponentBuilderImpl impl(Object instance) {
+        m_impl = instance;
+        return this;
+    }
+        
+    @Override
+    public ComponentBuilderImpl factory(Object factory, String createMethod) {
+        m_factory = factory;
+        m_factoryCreateMethod = createMethod;
+        ensureHasNoFactoryRef();
+        m_hasFactory = true;
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl factory(Supplier<?> create) {
+        Objects.nonNull(create);
+        ensureHasNoFactory();
+        m_hasFactoryRef = true;
+        m_factory = new Object() {
+            @SuppressWarnings("unused")
+            public Object create() {
+                return create.get();
+            }
+        };
+        return this;
+    }
+    
+    @Override
+    public <U, V> ComponentBuilderImpl factory(Supplier<U> supplier, Function<U, V> create) {
+        Objects.nonNull(supplier);
+        Objects.nonNull(create);
+        ensureHasNoFactory();
+        m_hasFactoryRef = true;
+
+        m_factory = new Object() {
+            @SuppressWarnings("unused")
+            public Object create() {
+                U factoryImpl = supplier.get();
+                return create.apply(factoryImpl);
+            }
+        }; 
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl factory(Supplier<?> create, Supplier<Object[]> getComposite) {
+        Objects.nonNull(create);
+        Objects.nonNull(getComposite);
+        ensureHasNoFactory();
+        m_hasFactoryRef = true;
+
+        m_factory = new Object() {
+            @SuppressWarnings("unused")
+            public Object create() { // Create Factory instance
+                return create.get();
+            }
+            
+            @SuppressWarnings("unused")
+            public Object[] getComposite() { // Create Factory instance
+                return getComposite.get();
+            }
+        };
+        m_factoryHasComposite = true;
+        return this;
+    }
+    
+    @Override
+    public <U> ComponentBuilderImpl factory(Supplier<U> factorySupplier, Function<U, ?> factoryCreate, Function<U, Object[]> factoryGetComposite) {
+        Objects.nonNull(factorySupplier);
+        Objects.nonNull(factoryCreate);
+        Objects.nonNull(factoryGetComposite);
+        ensureHasNoFactory();
+        m_hasFactoryRef = true;
+
+        m_factory = new Object() {
+            U m_factoryInstance;
+            
+            @SuppressWarnings("unused")
+            public Object create() { 
+                m_factoryInstance = factorySupplier.get();
+                return factoryCreate.apply(m_factoryInstance);
+            }
+            
+            @SuppressWarnings("unused")
+            public Object[] getComposite() { 
+                return factoryGetComposite.apply(m_factoryInstance);
+            }
+        }; 
+        m_factoryHasComposite = true;
+        return this;
+    }
+        
+    public ComponentBuilderImpl composition(String getCompositionMethod) {
+        return composition(null, getCompositionMethod);
+    }
+    
+    public ComponentBuilderImpl composition(Object instance, String getCompositionMethod) {
+        m_compositionInstance = instance;
+        m_compositionMethod = getCompositionMethod;
+        return this;
+    }
+    
+    public ComponentBuilderImpl composition(Supplier<Object[]> getCompositionMethod) {
+        m_compositionInstance = new Object() {
+            @SuppressWarnings("unused")
+            public Object[] getComposition() {
+                return getCompositionMethod.get();
+            }
+        };
+        m_compositionMethod = "getComposition";
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl withSrv(Class<?> service, String filter) {
+        return withSrv(service, srv->srv.filter(filter));
+    }   
+
+    @Override
+    public ComponentBuilderImpl withSrv(Class<?> ... services) {
+        for (Class<?> s : services) {
+            doWithService(s);
+        }
+        return this;
+    }   
+
+    private <U> void doWithService(Class<U> service) {
+        ServiceDependencyBuilder<U> dep = new ServiceDependencyBuilderImpl<>(m_component, service);
+        m_dependencyBuilders.add(dep);
+    }
+
+    @Override
+    public <U> ComponentBuilderImpl withSrv(Class<U> service, Consumer<ServiceDependencyBuilder<U>> consumer) {
+        ServiceDependencyBuilder<U> dep = new ServiceDependencyBuilderImpl<>(m_component, service);
+        consumer.accept(dep);
+        m_dependencyBuilders.add(dep);
+        return this;
+    }   
+    
+    @Override
+    public ComponentBuilderImpl withCnf(Consumer<ConfigurationDependencyBuilder> consumer) {
+        ConfigurationDependencyBuilder dep = new ConfigurationDependencyBuilderImpl(m_component);
+        consumer.accept(dep);
+        m_dependencyBuilders.add(dep);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl withBundle(Consumer<BundleDependencyBuilder> consumer) {
+    	BundleDependencyBuilder dep = new BundleDependencyBuilderImpl(m_component);
+        consumer.accept(dep);
+        m_dependencyBuilders.add(dep);
+        return this;
+    }
+           
+    @Override
+    public <V> ComponentBuilderImpl withFuture(CompletableFuture<V> future, Consumer<FutureDependencyBuilder<V>> consumer) {
+        FutureDependencyBuilder<V> dep = new CompletableFutureDependencyImpl<>(m_component, future);
+        consumer.accept(dep);
+        m_dependencyBuilders.add(dep);
+        return this;
+    }
+    
+    public ComponentBuilderImpl init(String callback) {
+        ensureHasNoLifecycleMethodRefs();
+        m_init = callback;
+        return this;
+    }
+    
+    public ComponentBuilderImpl start(String callback) {
+        ensureHasNoLifecycleMethodRefs();
+        m_start = callback;
+        return this;
+    }
+
+    public ComponentBuilderImpl stop(String callback) {
+        ensureHasNoLifecycleMethodRefs();
+        m_stop = callback;
+        return this;
+    }
+    
+    public ComponentBuilderImpl destroy(String callback) {
+        ensureHasNoLifecycleMethodRefs();
+        m_destroy = callback;
+        return this;
+    }
+    
+    public ComponentBuilderImpl init(Object callbackInstance, String callback) {
+        m_callbackInstance = callbackInstance;
+        return init(callback);
+    }    
+
+    public ComponentBuilderImpl start(Object callbackInstance, String callback) {
+        m_callbackInstance = callbackInstance;
+        return start(callback);
+    }    
+
+    public ComponentBuilderImpl stop(Object callbackInstance, String callback) {
+        m_callbackInstance = callbackInstance;
+        return stop(callback);
+    }    
+
+    public ComponentBuilderImpl destroy(Object callbackInstance, String callback) {
+        m_callbackInstance = callbackInstance;
+        return destroy(callback);
+    }    
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <U> ComponentBuilderImpl init(CbConsumer<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(INIT, Helpers.getLambdaArgType(callback, 0), (inst, component) -> callback.accept((U) inst));
+        }
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <U> ComponentBuilderImpl start(CbConsumer<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(START, Helpers.getLambdaArgType(callback, 0), (inst, component) -> callback.accept((U) inst));
+        }
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <U> ComponentBuilderImpl stop(CbConsumer<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(STOP, Helpers.getLambdaArgType(callback, 0), (inst, component) -> callback.accept((U) inst));
+        }
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <U> ComponentBuilderImpl destroy(CbConsumer<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(DESTROY, Helpers.getLambdaArgType(callback, 0), (inst, component) -> callback.accept((U) inst));
+        }
+        return this;
+    }
+
+   @SuppressWarnings("unchecked")
+   @Override
+    public <U> ComponentBuilderImpl init(CbTypeComponent<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(INIT, Helpers.getLambdaArgType(callback, 0), (inst, component) -> callback.accept((U) inst, component));
+        }
+        return this;
+    }
+            
+   @SuppressWarnings("unchecked")
+   @Override
+    public <U> ComponentBuilderImpl start(CbTypeComponent<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(START, Helpers.getLambdaArgType(callback, 0), (inst, component) -> callback.accept((U) inst, component));
+        }
+        return this;
+    }
+            
+   @SuppressWarnings("unchecked")
+   @Override
+    public <U> ComponentBuilderImpl stop(CbTypeComponent<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(STOP, Helpers.getLambdaArgType(callback, 0), (inst, component) -> callback.accept((U) inst, component));
+        }
+        return this;
+    }
+            
+   @SuppressWarnings("unchecked")
+   @Override
+    public <U> ComponentBuilderImpl destroy(CbTypeComponent<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(DESTROY, Helpers.getLambdaArgType(callback, 0), (inst, component) -> callback.accept((U) inst, component));
+        }
+        return this;
+    }
+            
+    @Override
+    public ComponentBuilderImpl initInstance(Runnable callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(INIT, (inst, component) -> callback.run());
+        }
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl startInstance(Runnable callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(START, (inst, component) -> callback.run());
+        }
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl stopInstance(Runnable callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(STOP, (inst, component) -> callback.run());
+        }
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl destroyInstance(Runnable callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(DESTROY, (inst, component) -> callback.run());
+        }
+        return this;
+    }
+        
+    @Override
+    public ComponentBuilderImpl initInstance(CbComponent callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(INIT, (inst, component) -> callback.accept(component));
+        }
+        return this;
+    }
+  
+    @Override
+    public ComponentBuilderImpl startInstance(CbComponent callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(START, (inst, component) -> callback.accept(component));
+        }
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl stopInstance(CbComponent callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(STOP, (inst, component) -> callback.accept(component));
+        }
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl destroyInstance(CbComponent callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(DESTROY, (inst, component) -> callback.accept(component));
+        }
+        return this;
+    }
+    
+    public Component build() {
+        if (m_serviceNames != null) {
+            m_component.setInterface(m_serviceNames, m_properties);
+        } 
+        
+        if (m_properties != null) {
+            m_component.setServiceProperties(m_properties);
+        }
+                
+        if (! m_componentUpdated) { // Don't override impl or set callbacks if component is being updated
+           if (m_impl != null) {               
+               m_component.setImplementation(m_impl);
+               m_component.setComposition(m_compositionInstance, m_compositionMethod);
+           } else {
+               Objects.nonNull(m_factory);
+               if (m_hasFactoryRef) {
+                   m_component.setFactory(m_factory, "create");
+                   if (m_factoryHasComposite) {
+                       m_component.setComposition(m_factory, "getComposite");
+                   }
+               } else {
+                   m_component.setFactory(m_factory, m_factoryCreateMethod);
+               }
+           }
+            
+           if (m_refs.size() > 0) {
+        	   setLifecycleMethodRefs();
+           } else if (hasLifecleMethods()) {
+               m_component.setCallbacks(m_callbackInstance, m_init, m_start, m_stop, m_destroy);
+           }
+        }
+        
+        if (m_dependencyBuilders.size() > 0) {
+            // add atomically in case we are building some component dependencies from a component init method.
+            // We first transform the list of builders into a stream of built Dependencies, then we collect the result 
+            // to an array of Dependency[].
+            m_component.add(m_dependencyBuilders.stream().map(builder -> builder.build()).toArray(Dependency[]::new));
+        }
+        return m_component;
+    }
+
+    private boolean hasLifecleMethods() {
+        return m_init != null || m_start != null || m_stop != null || m_destroy != null;
+    }
+    
+    private boolean hasLifecleMethodRefs() {
+        return m_refs.size() > 0;
+    }
+    
+    private void ensureHasNoLifecycleMethods() {
+        if (hasLifecleMethods()) {
+            throw new IllegalStateException("Can't mix method references and name names for lifecycle callbacks");
+        }
+    }
+    
+    private void ensureHasNoLifecycleMethodRefs() {
+        if (hasLifecleMethodRefs()) {
+            throw new IllegalStateException("Can't mix method references and name names for lifecycle callbacks");
+        }
+    }
+
+    protected <U> ComponentBuilderImpl setInstanceCallbackRef(ComponentCallback cbType, MethodRef<U> ref) {
+        ensureHasNoLifecycleMethods();
+        List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
+        list.add((instance, component) -> {
+            ref.accept(null, component);
+        });
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    private <U> ComponentBuilderImpl setComponentCallbackRef(ComponentCallback cbType, Class<U> type, MethodRef<U> callback) {
+        ensureHasNoLifecycleMethods();
+        if (type.equals(Object.class)) {
+            throw new IllegalStateException("callback does not seam to be one from the possible component implementation classes");
+        }
+        List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
+        list.add((instance, component) -> {
+            Object componentImpl = Stream.of(component.getInstances())
+                .filter(impl -> Helpers.getClass(impl).equals(type))
+                .findFirst()
+                .orElseThrow(() -> new IllegalStateException("The method reference " + callback + " does not match any available component impl classes."));   
+            callback.accept((U) componentImpl, component);
+        });
+        return this;
+    }
+        
+    @SuppressWarnings("unused")
+    private void setLifecycleMethodRefs() {
+        Object cb = new Object() {
+            void init(Component comp) {
+            	invokeLfcleCallbacks(ComponentCallback.INIT, comp);
+            }
+
+            void start(Component comp) {
+            	invokeLfcleCallbacks(ComponentCallback.START, comp);
+            }
+
+            void stop(Component comp) {
+            	invokeLfcleCallbacks(ComponentCallback.STOP, comp);
+            }
+
+            void destroy(Component comp) {
+            	invokeLfcleCallbacks(ComponentCallback.DESTROY, comp);
+            }
+        };
+        m_component.setCallbacks(cb, "init", "start", "stop", "destroy");
+    }
+    
+    private void invokeLfcleCallbacks(ComponentCallback cbType, Component component) {
+        m_refs.computeIfPresent(cbType, (k, mrefs) -> {
+            mrefs.forEach(mref -> mref.accept(null, component));
+            return mrefs;
+         });
+    }
+
+    private void ensureHasNoFactoryRef() {
+        if (m_hasFactoryRef) {
+            throw new IllegalStateException("Can't mix factory method name and factory method reference");
+        }
+    }
+    
+    private void ensureHasNoFactory() {
+        if (m_hasFactory) {
+            throw new IllegalStateException("Can't mix factory method name and factory method reference");
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ConfigurationDependencyBuilderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ConfigurationDependencyBuilderImpl.java
new file mode 100644
index 0000000..89f48c6
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ConfigurationDependencyBuilderImpl.java
@@ -0,0 +1,162 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.ConfigurationDependency;
+import org.apache.felix.dm.lambda.ConfigurationDependencyBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeDictionary;
+
+public class ConfigurationDependencyBuilderImpl implements ConfigurationDependencyBuilder {
+    private String m_pid;
+    private boolean m_propagate;
+    private final Component m_component;
+    private String m_updateMethodName;
+    private Object m_updateCallbackInstance;
+    private boolean m_hasMethodRefs;
+    private boolean m_hasReflectionCallback;
+    private final List<MethodRef<Object>> m_refs = new ArrayList<>();
+    private boolean m_hasComponentCallbackRefs;
+    private boolean m_needsInstance = false;
+    
+    @FunctionalInterface
+    interface MethodRef<I> {
+        public void accept(I instance, Component c, Dictionary<String, Object> props);
+    }
+    
+    public ConfigurationDependencyBuilderImpl(Component component) {
+        m_component = component;
+    }
+
+    @Override
+    public ConfigurationDependencyBuilder pid(String pid) {
+        m_pid = pid;
+        return this;
+    }
+
+    @Override
+    public ConfigurationDependencyBuilder pid(Class<?> pidClass) {
+        m_pid = pidClass.getName();
+        return this;
+    }
+
+    @Override
+    public ConfigurationDependencyBuilder propagate() {
+        m_propagate = true;
+        return this;
+    }
+
+    @Override
+    public ConfigurationDependencyBuilder propagate(boolean propagate) {
+        m_propagate = propagate;
+        return this;
+    }
+
+    public ConfigurationDependencyBuilder cb(String update) {
+        checkHasNoMethodRefs();
+        m_hasReflectionCallback = true;
+        m_updateMethodName = update;
+        return this;
+    }
+    
+    public ConfigurationDependencyBuilder cbi(Object callbackInstance, String update) {
+        m_updateCallbackInstance = callbackInstance;
+        cb(update);
+        return this;
+    }
+
+    public ConfigurationDependencyBuilder needsInstance(boolean needsInstance) {
+        m_needsInstance = needsInstance;
+        return this;
+    }
+
+    @Override
+    public <T> ConfigurationDependencyBuilder cb(CbTypeDictionary<T>  callback) {
+        Class<T> type = Helpers.getLambdaArgType(callback, 0);
+        return setComponentCallbackRef(type, (instance, component, props) -> { callback.accept((T) instance, props); });
+    }
+
+    @Override
+    public <T> ConfigurationDependencyBuilder cb(CbTypeComponentDictionary<T>  callback) {
+        Class<T> type = Helpers.getLambdaArgType(callback, 0);
+        return setComponentCallbackRef(type, (instance, component, props) -> { callback.accept((T) instance, component, props); });
+    }
+
+    @Override
+    public ConfigurationDependencyBuilder cbi(CbDictionary callback) {
+        return setInstanceCallbackRef((instance, component, props) -> { callback.accept(props); });
+    }
+    
+    @Override
+    public ConfigurationDependencyBuilder cbi(CbComponentDictionary callback) {
+        return setInstanceCallbackRef((instance, component, props) -> { callback.accept(component, props); });
+    }
+
+    @Override
+    public ConfigurationDependency build() {
+        ConfigurationDependency dep = m_component.getDependencyManager().createConfigurationDependency();
+        Objects.nonNull(m_pid);
+        dep.setPid(m_pid);
+        dep.setPropagate(m_propagate);
+        if (m_updateMethodName != null) {
+            if (m_updateCallbackInstance != null) {
+                dep.setCallback(m_updateCallbackInstance, m_updateMethodName, m_needsInstance);
+            } else {
+                dep.setCallback(m_updateMethodName);
+            }
+        } else if (m_refs.size() > 0) {
+            // setup an internal callback object. When config is updated, we have to call each registered 
+            // method references. 
+            // Notice that we need the component to be instantiated in case there is a mref on one of the component instances (unbound method ref), or is used
+            // called "needsInstance(true)".
+            dep.setCallback(new Object() {
+                @SuppressWarnings("unused")
+                void updated(Component comp, Dictionary<String, Object> props) {
+                    m_refs.forEach(mref -> mref.accept(null, comp, props));
+                }
+            }, "updated", m_hasComponentCallbackRefs||m_needsInstance);
+        }
+        return dep;
+    }
+    
+    private <T> ConfigurationDependencyBuilder setInstanceCallbackRef(MethodRef<T> ref) {
+        checkHasNoReflectionCallbacks();
+        m_hasMethodRefs = true;
+        m_refs.add((instance, component, props) -> ref.accept(null, component, props));
+        return this;
+    }
+    
+    @SuppressWarnings("unchecked")
+    private <T> ConfigurationDependencyBuilder setComponentCallbackRef(Class<T> type, MethodRef<T> ref) {
+        checkHasNoReflectionCallbacks();
+        m_hasMethodRefs = true;
+        m_hasComponentCallbackRefs = true;
+        m_refs.add((instance, component, props) -> {
+            Object componentImpl = Stream.of(component.getInstances())
+                .filter(impl -> Helpers.getClass(impl).equals(type))
+                .findFirst()
+                .orElseThrow(() -> new IllegalStateException("The method reference " + ref + " does not match any available component impl classes."));           
+            ref.accept((T) componentImpl, component, props);
+        });
+        return this;
+    }
+    
+    private void checkHasNoMethodRefs() {
+        if (m_hasMethodRefs) {
+            throw new IllegalStateException("Can't mix method references with reflection based callbacks");
+        }
+    }
+    
+    private void checkHasNoReflectionCallbacks() {
+        if (m_hasReflectionCallback) {
+            throw new IllegalStateException("Can't mix method references with reflection based callbacks");
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/FactoryPidAdapterBuilderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/FactoryPidAdapterBuilderImpl.java
new file mode 100644
index 0000000..c3ee095
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/FactoryPidAdapterBuilderImpl.java
@@ -0,0 +1,166 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.lambda.ComponentBuilder;
+import org.apache.felix.dm.lambda.FactoryPidAdapterBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeDictionary;
+
+public class FactoryPidAdapterBuilderImpl implements AdapterBase<FactoryPidAdapterBuilder>, FactoryPidAdapterBuilder {
+    private String m_factoryPid;
+    private boolean m_propagate;
+    private final DependencyManager m_dm;
+    private boolean m_autoAdd = true;
+    private String m_updateMethodName;
+    private Object m_updateCallbackInstance;
+    private boolean m_hasMethodRefs;
+    private boolean m_hasReflectionCallback;
+    private Consumer<ComponentBuilder<?>> m_compBuilder = (componentBuilder -> {});
+    private final List<MethodRef<Object>> m_refs = new ArrayList<>();
+
+    @FunctionalInterface
+    interface MethodRef<I> {
+        public void accept(I instance, Component c, Dictionary<String, Object> props);
+    }
+
+    public FactoryPidAdapterBuilderImpl(DependencyManager dm) {
+        m_dm = dm;
+    }
+    
+    public void andThenBuild(Consumer<ComponentBuilder<?>> builder) {
+        m_compBuilder = m_compBuilder.andThen(builder);
+    }
+
+    @Override
+    public FactoryPidAdapterBuilderImpl autoAdd(boolean autoAdd) {
+        m_autoAdd = autoAdd;
+        return this;
+    }
+        
+    public boolean isAutoAdd() {
+        return m_autoAdd;
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder factoryPid(String pid) {
+        m_factoryPid = pid;
+        return this;
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder factoryPid(Class<?> pidClass) {
+        m_factoryPid = pidClass.getName();
+        return this;
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder propagate() {
+        m_propagate = true;
+        return this;
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder propagate(boolean propagate) {
+        m_propagate = propagate;
+        return this;
+    }
+
+    public FactoryPidAdapterBuilder cb(String update) {
+        checkHasNoMethodRefs();
+        m_hasReflectionCallback = true;
+        m_updateMethodName = update;
+        return this;
+    }
+    
+    public FactoryPidAdapterBuilder cb(Object callbackInstance, String update) {
+        cb(update);
+        m_updateCallbackInstance = callbackInstance;
+        return this;
+    }
+    
+    @Override
+    public <U> FactoryPidAdapterBuilder cb(CbTypeDictionary<U> callback) {
+        Class<U> type = Helpers.getLambdaArgType(callback, 0);
+        return setComponentCallbackRef(type, (instance, component, props) -> { callback.accept((U) instance, props); });
+    }
+    
+    @Override
+    public <U> FactoryPidAdapterBuilder cb(CbTypeComponentDictionary<U> callback) {
+        Class<U> type = Helpers.getLambdaArgType(callback, 0);
+        return setComponentCallbackRef(type, (instance, component, props) -> { callback.accept((U) instance, component, props); });
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder cbi(CbDictionary callback) {
+        return setInstanceCallbackRef((instance, component, props) -> { callback.accept(props); });
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder cbi(CbComponentDictionary callback) {
+        return setInstanceCallbackRef((instance, component, props) -> { callback.accept(component, props); });
+    }
+
+    @Override
+    public Component build() {        
+        Objects.nonNull(m_factoryPid);
+        Component c = null;
+        
+        if (m_hasMethodRefs) {
+            Object wrapCallback = new Object() {
+                @SuppressWarnings("unused")
+                public void updated(Component comp, Dictionary<String, Object> conf) {
+                    m_refs.forEach(mref -> mref.accept(null, comp, conf));
+                }
+            };
+            c = m_dm.createFactoryConfigurationAdapterService(m_factoryPid, "updated", m_propagate, wrapCallback);
+        } else {
+            c = m_dm.createFactoryConfigurationAdapterService(m_factoryPid, m_updateMethodName, m_propagate, m_updateCallbackInstance);
+        }
+        ComponentBuilderImpl cb = new ComponentBuilderImpl(c, false);
+        m_compBuilder.accept (cb);
+        return cb.build();
+    }
+    
+    private <U> FactoryPidAdapterBuilder setInstanceCallbackRef(MethodRef<U> ref) {
+        checkHasNoReflectionCallbacks();
+        m_hasMethodRefs = true;
+        m_refs.add((instance, component, props) -> ref.accept(null, component, props));
+        return this;
+    }
+    
+    @SuppressWarnings("unchecked")
+    private <U> FactoryPidAdapterBuilder setComponentCallbackRef(Class<U> type, MethodRef<U> ref) {
+        checkHasNoReflectionCallbacks();
+        m_hasMethodRefs = true;
+        m_refs.add((instance, component, props) -> {
+            Object componentImpl = Stream.of(component.getInstances())
+                .filter(impl -> Helpers.getClass(impl).equals(type))
+                .findFirst()
+                .orElseThrow(() -> new IllegalStateException("The method reference " + ref + " does not match any available component impl classes."));
+            ref.accept((U) componentImpl, component, props);
+        });
+        return this;
+    }
+
+    private void checkHasNoMethodRefs() {
+        if (m_hasMethodRefs) {
+            throw new IllegalStateException("Can't mix method references with reflection based callbacks");
+        }
+    }
+    
+    private void checkHasNoReflectionCallbacks() {
+        if (m_hasReflectionCallback) {
+            throw new IllegalStateException("Can't mix method references with reflection based callbacks");
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/Helpers.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/Helpers.java
new file mode 100644
index 0000000..50eb73c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/Helpers.java
@@ -0,0 +1,147 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.lang.invoke.SerializedLambda;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.lambda.callbacks.SerializableLambda;
+
+/**
+ * Various helper methods related to generics and lambda expressions.
+ */
+public class Helpers {
+	private final static Pattern LAMBDA_INSTANCE_METHOD_TYPE = Pattern.compile("(L[^;]+)+");
+
+	/**
+	 * Gets the class name of a given object.
+	 * @param obj the object whose class has to be returned.
+	 */
+	public static Class<?> getClass(Object obj) {
+		Class<?> clazz = obj.getClass();
+		if (Proxy.isProxyClass(clazz)) {
+			return Proxy.getProxyClass(clazz.getClassLoader(), clazz);
+		}
+		return clazz;
+	}
+	
+	/**
+	 * Extracts the type of a given generic lambda parameter.
+	 * Example: for "BiConsumer<String, Integer>", and with genericParamIndex=0, this method returns java.lang.String class.
+	 * 
+	 * @param lambda a lambda expression, which must extends @link {@link SerializableLambda} interface.
+	 * @param genericParamIndex the index of a given lambda generic parameter.
+	 * @return the type of the lambda generic parameter that corresponds to the <code>genericParamIndex</code>  
+	 */
+	@SuppressWarnings("unchecked")
+    public static <T> Class<T> getLambdaArgType(SerializableLambda lambda, int genericParamIndex) {
+	    String[] lambdaParams = getGenericTypeStrings(lambda);
+	    Class<?> clazz;
+        try {
+            clazz = lambda.getClass().getClassLoader().loadClass(lambdaParams[genericParamIndex]);
+        } catch (ClassNotFoundException e) {
+           throw new RuntimeException("Can't load class " + lambdaParams[genericParamIndex]);
+        }
+	    return (Class<T>) clazz;
+	}
+	
+	/**
+	 * Extracts the first parameter of a lambda.
+	 */
+	public static String getLambdaParameterName(SerializableLambda lambda, int index) {
+		SerializedLambda serialized = getSerializedLambda(lambda);
+		Method m = getLambdaMethod(serialized, lambda.getClass().getClassLoader());
+		Parameter p = m.getParameters()[index];
+		
+        if (Objects.equals("arg0", p.getName())) {
+            throw new IllegalStateException("Can'f find lambda method name (Please check you are using javac -parameters option).");
+        }
+        return p.getName();
+	}
+	
+	/**
+	 * Returns the SerializedObject of a given lambda.
+	 */
+    private static SerializedLambda getSerializedLambda(SerializableLambda lambda) {
+	    if (lambda == null) {
+	        throw new IllegalArgumentException();
+	    }
+
+	    for (Class<?> clazz = lambda.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
+	        try {
+	            Method replaceMethod = clazz.getDeclaredMethod("writeReplace");
+	            replaceMethod.setAccessible(true);
+	            Object serializedForm = replaceMethod.invoke(lambda);
+
+	            if (serializedForm instanceof SerializedLambda) {
+	                return (SerializedLambda) serializedForm;
+	            }
+	        }
+	        catch (NoSuchMethodException e) {
+	            // fall through the loop and try the next class
+	        }
+	        catch (Throwable t) {
+	            throw new RuntimeException("Error while extracting serialized lambda", t);
+	        }
+	    }
+
+	    throw new RuntimeException("writeReplace method not found");
+	}
+
+    /**
+     * Finds a composite
+     * @param component
+     * @param type
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <U> U findCompositeInstance(Component component, Class<U> type) {
+        U instance = (U) Stream.of(component.getInstances())
+            .filter(inst -> Objects.equals(Helpers.getClass(inst), type))
+            .findFirst()
+            .orElseThrow(() -> new RuntimeException("Did not find a component instance matching type " + type));
+        return instance;                       
+    }
+
+    /**
+     * Extracts the actual types of all lambda generic parameters.
+     * Example: for "BiConsumer<String, Integer>", this method returns ["java.lang.String", "java.lang.Integer"].
+     */
+    private static String[] getGenericTypeStrings(SerializableLambda lambda) {
+        // The only portable way to get the actual lambda generic parameters can be done using SerializedLambda.
+        SerializedLambda sl = getSerializedLambda(lambda);
+        String lambdaMethodType = sl.getInstantiatedMethodType();
+        Matcher m = LAMBDA_INSTANCE_METHOD_TYPE.matcher(lambdaMethodType);
+        List<String> results = new ArrayList<>();
+        while (m.find()) {
+            results.add(m.group().substring(1).replace("/", "."));
+        }
+        return results.toArray(new String[0]);
+    }
+    
+    /**
+     * Extracts the actual java method from a given lambda.
+     */
+    private static Method getLambdaMethod(SerializedLambda lambda, ClassLoader loader) {
+        String implClassName = lambda.getImplClass().replace('/', '.');
+        Class<?> implClass;
+        try {
+            implClass = loader.loadClass(implClassName);
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException("Lambda Method not found (can not instantiate class " + implClassName);
+        }
+
+        return Stream.of(implClass.getDeclaredMethods())
+            .filter(method -> Objects.equals(method.getName(), lambda.getImplMethodName()))
+            .findFirst()
+            .orElseThrow(() -> new RuntimeException("Lambda Method not found"));
+    }
+    
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsDictionary.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsDictionary.java
new file mode 100644
index 0000000..4e14d9a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsDictionary.java
@@ -0,0 +1,94 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Maps a ServiceReference to a Dictionary.
+ */
+public class SRefAsDictionary extends Dictionary<String, Object> {
+    private final ServiceReference<?> m_ref;
+    private volatile int m_size = -1;
+
+    public SRefAsDictionary(ServiceReference<?> ref) {
+        m_ref = ref;
+    }
+    
+    @Override
+    public Object get(Object key) {
+        return m_ref.getProperty(key.toString());
+    }
+    
+    @Override
+    public int size() {
+        return m_size != -1 ? m_size : (m_size = m_ref.getPropertyKeys().length);
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return size() == 0;
+    }
+
+    @Override
+    public Enumeration<String> keys() {
+        return Collections.enumeration(Arrays.asList(m_ref.getPropertyKeys())); 
+    }
+
+    @Override
+    public Enumeration<Object> elements() {
+        final String[] keys = m_ref.getPropertyKeys();
+        
+        return new Enumeration<Object>() {
+            int m_index = 0;
+            
+            @Override
+            public boolean hasMoreElements() {
+                return m_index < keys.length;
+            }
+
+            @Override
+            public Object nextElement() {
+                if (m_index >= keys.length) {
+                    throw new NoSuchElementException();
+                }
+                return m_ref.getProperty(keys[m_index ++]);
+            }
+        };
+    }
+
+    @Override
+    public Object remove(Object key) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object put(String key, Object value) {
+        throw new UnsupportedOperationException();
+    }
+    
+    public String toString() {
+        int max = size() - 1;
+        if (max == -1)
+            return "{}";
+
+        StringBuilder sb = new StringBuilder();
+        String[] keys = m_ref.getPropertyKeys();
+        sb.append('{');
+        for (int i = 0; ; i++) {
+            String key = keys[i];
+            Object value = m_ref.getProperty(key);
+            sb.append(key);
+            sb.append('=');
+            sb.append(value == this ? "(this Dictionary)" : value.toString());
+
+            if (i == max)
+                return sb.append('}').toString();
+            sb.append(", ");
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsMap.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsMap.java
new file mode 100644
index 0000000..40f411a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsMap.java
@@ -0,0 +1,84 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Maps a ServiceReference to a Map.
+ */
+public class SRefAsMap extends AbstractMap<String, Object> {
+    private final ServiceReference<?> m_ref;
+
+    public SRefAsMap(ServiceReference<?> ref) {
+        m_ref = ref;
+    }
+    
+    public Object get(Object key) {
+        return m_ref.getProperty(key.toString());
+    }
+
+    @Override
+    public Set<Entry<String, Object>> entrySet() {
+        return new AbstractSet<Entry<String, Object>>() {
+            @Override
+            public Iterator<Entry<String, Object>> iterator() {
+                final Enumeration<String> e = Collections.enumeration(Arrays.asList(m_ref.getPropertyKeys()));
+                
+                return new Iterator<Entry<String, Object>>() {
+                    private String key;
+
+                    public boolean hasNext() {
+                        return e.hasMoreElements();
+                    }
+
+                    public Entry<String, Object> next() {
+                        key = e.nextElement();
+                        return new KeyEntry(key);
+                    }
+
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                };
+            }
+
+            @Override
+            public int size() {
+                return m_ref.getPropertyKeys().length;
+            }
+        };
+    }
+
+    @Override
+    public Object put(String key, Object value) {
+        throw new UnsupportedOperationException();
+    }
+
+    class KeyEntry implements Map.Entry<String, Object> {
+        private final String key;
+
+        KeyEntry(String key) {
+            this.key = key;
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public Object getValue() {
+            return m_ref.getProperty(key);
+        }
+
+        public Object setValue(Object value) {
+            return SRefAsMap.this.put(key, value);
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAdapterBuilderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAdapterBuilderImpl.java
new file mode 100644
index 0000000..01d6270
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAdapterBuilderImpl.java
@@ -0,0 +1,83 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.Objects;
+import java.util.function.Consumer;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.lambda.ComponentBuilder;
+import org.apache.felix.dm.lambda.ServiceAdapterBuilder;
+
+public class ServiceAdapterBuilderImpl<T> extends ServiceCallbacksBuilderImpl<T, ServiceAdapterBuilder<T>> implements 
+    AdapterBase<ServiceAdapterBuilder<T>>, ServiceAdapterBuilder<T> 
+{	
+    private final Class<T> m_adapteeType;
+    private String m_adapteeFilter;
+    private boolean m_propagate = true;
+    private final DependencyManager m_dm;
+    private boolean m_autoAdd = true;
+    private Consumer<ComponentBuilder<?>> m_compBuilder = (componentBuilder -> {});
+
+    public ServiceAdapterBuilderImpl(DependencyManager dm, Class<T> adapterType) {
+        super(adapterType);
+        m_dm = dm;
+        m_adapteeType = adapterType;
+    }    
+
+    @Override
+    public void andThenBuild(Consumer<ComponentBuilder<?>> after) {
+        m_compBuilder = m_compBuilder.andThen(after);        
+    }
+
+    @Override
+    public ServiceAdapterBuilderImpl<T> autoAdd(boolean autoAdd) {
+        m_autoAdd = autoAdd;
+        return this;
+    }
+    
+    public ServiceAdapterBuilderImpl<T> autoAdd() {
+        m_autoAdd = true;
+        return this;
+    }
+
+    public boolean isAutoAdd() {
+        return m_autoAdd;
+    }
+    
+    @Override
+    public ServiceAdapterBuilder<T> filter(String adapteeFilter) {
+        m_adapteeFilter = adapteeFilter;
+        return this;
+    }
+
+    @Override
+    public ServiceAdapterBuilder<T> propagate(boolean propagate) {
+        m_propagate = propagate;
+        return this;
+    }
+
+    @Override
+    public Component build() {
+        Objects.nonNull(m_adapteeFilter);
+        
+        String add = getAdded(), change = getChanged(), remove = getRemoved(), swap = getSwapped();
+        Object cbInstance = getCallbackInstance();
+        
+        if (hasRefs()) {
+            // if some method references have been set, use our own callback proxy to redispatch events to method refs.        
+        	cbInstance = createCallbackInstance();
+            add = "add";
+            change = "change";
+            remove = "remove";
+            swap = m_swapRefs.size() > 0 ? "swap" : null;
+        } 
+
+        Component c = m_dm.createAdapterService
+        		(m_adapteeType, m_adapteeFilter, getAutoConfigField(), cbInstance, add, change, remove, swap, m_propagate);
+        
+        ComponentBuilderImpl cb = new ComponentBuilderImpl(c, false);
+        // m_compBuilder is a composed consumer that calls in sequence all necessary component builder methods. 
+        m_compBuilder.accept (cb);
+        return cb.build();
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAspectBuilderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAspectBuilderImpl.java
new file mode 100644
index 0000000..48274f6
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAspectBuilderImpl.java
@@ -0,0 +1,86 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.Objects;
+import java.util.function.Consumer;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.lambda.ComponentBuilder;
+import org.apache.felix.dm.lambda.ServiceAspectBuilder;
+
+public class ServiceAspectBuilderImpl<T> extends ServiceCallbacksBuilderImpl<T, ServiceAspectBuilder<T>> implements 
+    AdapterBase<ServiceAspectBuilder<T>>, ServiceAspectBuilder<T> 
+{    
+    private final DependencyManager m_dm;
+    private final Class<T> m_aspectType;
+    private String m_aspectFilter;
+    private int m_aspectRanking;
+    private boolean m_autoAdd = true;
+    private Consumer<ComponentBuilder<?>> m_compBuilder = (componentBuilder -> {});
+
+    public ServiceAspectBuilderImpl(DependencyManager dm, Class<T> aspectType) {
+        super(aspectType);
+        m_dm = dm;
+        m_aspectType = aspectType;
+    }
+
+    @Override
+    public void andThenBuild(Consumer<ComponentBuilder<?>> after) {
+        m_compBuilder = m_compBuilder.andThen(after);        
+    }
+
+    @Override
+    public ServiceAspectBuilderImpl<T> autoAdd(boolean autoAdd) {
+        m_autoAdd = autoAdd;
+        return this;
+    }
+    
+    public boolean isAutoAdd() {
+        return m_autoAdd;
+    }
+
+    @Override
+    public ServiceAspectBuilder<T> filter(String aspectFilter) {
+        m_aspectFilter = aspectFilter;
+        return this;
+    }
+
+    @Override
+    public ServiceAspectBuilder<T> rank(int ranking) {
+        m_aspectRanking = ranking;
+        return this;
+    }
+    
+    @Override
+    public Component build() {
+        Objects.nonNull(m_aspectType);
+        
+        if (getAutoConfigField() != null && (hasRefs()|| hasCallbacks())) {
+            throw new IllegalStateException("Can't mix autoConfig fields and aspect callbacks.");
+        }
+        
+        Component c = null;
+        if (getAutoConfigField() != null) {
+            c = m_dm.createAspectService(m_aspectType, m_aspectFilter, m_aspectRanking, getAutoConfigField());
+        } else if (hasRefs()) {        
+            Object cbInstance = createCallbackInstance();
+            String add = "add";
+            String change = "change";
+            String remove = "remove";
+            String swap = m_swapRefs.size() > 0 ? "swap" : null;        
+            c = m_dm.createAspectService(m_aspectType, m_aspectFilter, m_aspectRanking, cbInstance, add, change, remove, swap);
+        } else if (hasCallbacks()) {
+            String add = getAdded();
+            String change = getChanged();
+            String remove = getRemoved();
+            String swap = getSwapped();
+            c = m_dm.createAspectService(m_aspectType, m_aspectFilter, m_aspectRanking, add, change, remove, swap);
+        } else {
+            c = m_dm.createAspectService(m_aspectType, m_aspectFilter, m_aspectRanking);
+        }
+        ComponentBuilderImpl cb = new ComponentBuilderImpl(c, false);
+        // m_compBuilder is a composed consumer that calls in sequence all necessary component builder methods. 
+        m_compBuilder.accept (cb);
+        return cb.build();
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceCallbacksBuilderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceCallbacksBuilderImpl.java
new file mode 100644
index 0000000..33188ac
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceCallbacksBuilderImpl.java
@@ -0,0 +1,651 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.lambda.ServiceCallbacksBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbComponent;
+import org.apache.felix.dm.lambda.callbacks.CbComponentRef;
+import org.apache.felix.dm.lambda.callbacks.CbComponentRefService;
+import org.apache.felix.dm.lambda.callbacks.CbComponentRefServiceRefService;
+import org.apache.felix.dm.lambda.callbacks.CbComponentService;
+import org.apache.felix.dm.lambda.callbacks.CbComponentServiceService;
+import org.apache.felix.dm.lambda.callbacks.CbRef;
+import org.apache.felix.dm.lambda.callbacks.CbRefService;
+import org.apache.felix.dm.lambda.callbacks.CbRefServiceRefService;
+import org.apache.felix.dm.lambda.callbacks.CbService;
+import org.apache.felix.dm.lambda.callbacks.CbServiceDict;
+import org.apache.felix.dm.lambda.callbacks.CbServiceMap;
+import org.apache.felix.dm.lambda.callbacks.CbServiceService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponent;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentRef;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentRefService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentRefServiceRefService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentServiceService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeRef;
+import org.apache.felix.dm.lambda.callbacks.CbTypeRefService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeRefServiceRefService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeService;
+import org.apache.felix.dm.lambda.callbacks.CbTypeServiceDict;
+import org.apache.felix.dm.lambda.callbacks.CbTypeServiceMap;
+import org.apache.felix.dm.lambda.callbacks.CbTypeServiceService;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Service Dependency Callback management.
+ *
+ * @param <S> the type of the service dependency
+ * @param <B> the type of the sub-classes which may extend this class
+ */
+@SuppressWarnings({"unchecked", "unused"})
+public class ServiceCallbacksBuilderImpl<S, B extends ServiceCallbacksBuilder<S, B>> implements ServiceCallbacksBuilder<S, B> {
+    protected boolean m_autoConfig = true;
+    protected boolean m_autoConfigInvoked = false;
+    protected String m_autoConfigField;
+    protected Object m_callbackInstance;
+    protected String m_added;
+    protected String m_changed;
+    protected String m_removed;
+    protected String m_swapped;
+    protected final Class<S> m_serviceClass;
+    
+    enum Cb {
+        ADD,        
+        CHG,        
+        REM
+    };
+    
+	/**
+	 * List of service (add/change/remove) callbacks.
+	 */
+    protected final Map<Cb, List<MethodRef<Object, S>>> m_refs = new HashMap<>();
+
+	/**
+	 * List of swap callbacks
+	 */
+	protected final List<SwapMethodRef<?, S>> m_swapRefs = new ArrayList<>();
+	
+	/**
+	 * This interface (lambda) is called when we want to invoke a method reference. the lambda is called with all necessary service dependency 
+	 * informations.
+	 * 
+	 * When the lambda is called, it will invoke the proper callback on the given component instance.
+	 *
+	 * @param <I> type of a component instance
+	 * @param <T> service dependency type
+	 */
+	@FunctionalInterface
+    interface MethodRef<I, S> {
+    	public void accept(I instance, Component c, ServiceReference<S> ref, S service);
+    }
+
+	/**
+	 * This interface (lambda) is called when we want to invoke a swap method reference. the lambda is called with all necessary swap info.
+	 * When the lambda is called, it will invoke the proper swap callback on the given component instance.
+	 *
+	 * @param <I> type of a component instance
+	 * @param <T> service dependency type
+	 */
+	@FunctionalInterface
+	interface SwapMethodRef<I, S> {
+    	public void accept(I instance, Component c, ServiceReference<S> oldRef, S oldService, ServiceReference<S> newRef, S newService);
+    }
+	  
+	public ServiceCallbacksBuilderImpl(Class<S> serviceClass) {
+	    m_serviceClass = serviceClass;
+	}
+	
+    public B autoConfig() {
+        autoConfig(true);
+        return (B) this;
+    }
+
+    public  B autoConfig(String field) {
+        m_autoConfigField = field;
+        m_autoConfigInvoked = true;
+        return (B) this;
+    }
+
+    public B autoConfig(boolean autoConfig) {
+        m_autoConfig = autoConfig;
+        m_autoConfigInvoked = true;
+        return (B) this;
+    }
+	
+    public B cb(String ... callbacks) {
+        return cbi(null, callbacks);
+    }
+    
+    public B cbi(Object callbackInstance, String ... callbacks) {
+        Objects.nonNull(callbacks);
+        switch (callbacks.length) {
+        case 1:
+            cb(callbackInstance, callbacks[0], null, null, null);
+            break;
+            
+        case 2:
+            cb(callbackInstance, callbacks[0], null, callbacks[1], null);
+            break;
+            
+        case 3:
+            cb(callbackInstance, callbacks[0], callbacks[1], callbacks[2], null);
+            break;
+            
+        case 4:
+            cb(callbackInstance, callbacks[0], callbacks[1], callbacks[2], callbacks[3]);
+            break;
+            
+        default:
+            throw new IllegalArgumentException("wrong number of arguments: " + callbacks.length + ". " +
+                "Possible arguments: [add], [add, remove], [add, change, remove], or [add, change, remove, swap]");
+        }
+        return (B) this;
+    }
+    
+    private B cb(Object callbackInstance, String added, String changed, String removed, String swapped) {
+		requiresNoMethodRefs();
+        m_callbackInstance = callbackInstance;
+		m_added = added != null ? added : m_added;
+		m_changed = changed != null ? changed : m_changed;
+		m_removed = removed != null ? removed : m_removed;
+		m_swapped = swapped != null ? swapped : m_swapped;
+        if (! m_autoConfigInvoked) m_autoConfig = false;
+		return (B) this;
+	}
+
+    public <T> B cb(CbTypeService<T, S> add) {
+        return cb(add, null, null);
+    }
+    
+    public <T> B cb(CbTypeService<T, S> add, CbTypeService<T, S> remove) {
+        return cb(add, null, remove);
+    }
+    
+    public <T> B cb(CbTypeService<T, S> add, CbTypeService<T, S> change, CbTypeService<T, S> remove) {
+        if (add != null)
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, srv));
+        if (change != null)
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, srv));
+        if (remove != null)
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, srv));
+        return (B) this;
+    }
+
+    public B cbi(CbService<S> add) {
+        return cbi(add, null, null);
+    }
+    
+    public B cbi(CbService<S> add, CbService<S> remove) {
+        return cbi(add, null, remove);
+    }
+
+    public B cbi(CbService<S> add, CbService<S> change, CbService<S> remove) {
+        if (add != null)
+            setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(srv));
+        if (change != null)
+            setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(srv));
+        if (remove != null)
+            setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(srv));
+        return (B) this;        
+    }
+    
+    public <T> B cb(CbTypeServiceMap<T, S> add) {
+        return cb(add, null, null);
+    }
+    
+    public <T> B cb(CbTypeServiceMap<T, S> add, CbTypeServiceMap<T, S> remove) {
+        return cb(add, null, remove);
+    }
+
+    public <T> B cb(CbTypeServiceMap<T, S> add, CbTypeServiceMap<T, S> change, CbTypeServiceMap<T, S> remove) {
+        if (add != null)
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, srv, new SRefAsMap(ref)));
+        if (change != null)
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, srv, new SRefAsMap(ref)));
+        if (remove != null)
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, srv, new SRefAsMap(ref)));
+        return (B) this;        
+    }
+    
+    public B cbi(CbServiceMap<S> add) {
+        return cbi(add, null, null);
+    }
+    
+    public B cbi(CbServiceMap<S> add, CbServiceMap<S> remove) {
+        return cbi(add, null, remove);
+    }
+
+    public B cbi(CbServiceMap<S> add, CbServiceMap<S> change, CbServiceMap<S> remove) {
+        if (add != null)
+            setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(srv, new SRefAsMap(ref)));   
+        if (change != null)
+            setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(srv, new SRefAsMap(ref)));   
+        if (remove != null)
+            setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(srv, new SRefAsMap(ref)));
+        return (B) this;        
+    }
+
+    public <T> B cb(CbTypeServiceDict<T, S> add) {
+        return cb(add, null, null);
+    }
+
+    public <T> B cb(CbTypeServiceDict<T, S> add, CbTypeServiceDict<T, S> remove) {
+        return cb(add, null, remove);
+    }
+    
+    public <T> B cb(CbTypeServiceDict<T, S> add, CbTypeServiceDict<T, S> change, CbTypeServiceDict<T, S> remove) {
+        if (add != null)
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, srv, new SRefAsDictionary(ref)));
+        if (change != null) 
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, srv, new SRefAsDictionary(ref)));
+        if (remove != null)
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, srv, new SRefAsDictionary(ref))); 
+        return (B) this;  
+    }
+
+    public B cbi(CbServiceDict<S> add) {
+        return cbi(add, null, null);
+    }
+    
+    public B cbi(CbServiceDict<S> add, CbServiceDict<S> remove) {
+        return cbi(add, null, remove);
+    }
+
+    public B cbi(CbServiceDict<S> add, CbServiceDict<S> change, CbServiceDict<S> remove) {
+        if (add != null)
+            setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(srv, new SRefAsDictionary(ref)));   
+        if (change != null)
+            setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(srv, new SRefAsDictionary(ref)));   
+        if (remove != null)
+            setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(srv, new SRefAsDictionary(ref)));
+        return (B) this;        
+    }
+
+    public <T> B cb(CbTypeRefService<T, S> add) {
+        return cb(add, null, null);
+    }
+
+    public <T> B cb(CbTypeRefService<T, S> add, CbTypeRefService<T, S> remove) {
+        return cb(add, null, remove);
+    }
+
+    public <T> B cb(CbTypeRefService<T, S> add, CbTypeRefService<T, S> change, CbTypeRefService<T, S> remove) {
+        if (add != null)
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, ref, srv)); 
+        if (change != null)
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, ref, srv)); 
+        if (remove != null)
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, ref, srv)); 
+        return (B) this;
+    }
+
+    public B cbi(CbRefService<S> add) {
+        return cbi(add, null, null);
+    }
+
+    public B cbi(CbRefService<S> add, CbRefService<S> remove) {
+        return cbi(add, null, remove);
+    }
+
+    public B cbi(CbRefService<S> add, CbRefService<S> change, CbRefService<S> remove) {
+        if (add != null)
+            setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(ref, srv)); 
+        if (change != null)
+            setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(ref, srv)); 
+        if (remove != null)
+            setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(ref, srv)); 
+        return (B) this;
+    }
+    
+    public <T> B cb(CbTypeRef<T, S> add) {
+        return cb(add, null, null);
+    }
+
+    public <T> B cb(CbTypeRef<T, S> add, CbTypeRef<T, S> remove) {
+        return cb(add, null, remove);
+    }
+
+    public <T> B cb(CbTypeRef<T, S> add, CbTypeRef<T, S> change, CbTypeRef<T, S> remove) {
+        if (add != null)
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, ref));
+        if (change != null)
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, ref)); 
+        if (remove != null)
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, ref)); 
+        return (B) this;
+    }
+
+    public B cbi(CbRef<S> add) {
+        return cbi(add, null, null);
+    }
+
+    public B cbi(CbRef<S> add, CbRef<S> remove) {
+        return cbi(add, null, remove);
+    }
+
+    public B cbi(CbRef<S> add, CbRef<S> change, CbRef<S> remove) {
+        if (add != null)
+            setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(ref)); 
+        if (change != null)
+            setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(ref)); 
+        if (remove != null)
+            setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(ref)); 
+        return (B) this;
+    }
+
+    public <T> B cb(CbTypeComponent<T> add) {
+        return cb(add, null, null);
+    }
+
+    public <T> B cb(CbTypeComponent<T> add, CbTypeComponent<T> remove) {
+        return cb(add, null, remove);
+    }
+
+    public <T> B cb(CbTypeComponent<T> add, CbTypeComponent<T> change, CbTypeComponent<T> remove) {
+        if (add != null)
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, comp));              
+        if (change != null)
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, comp));              
+        if (remove != null)
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, comp)); 
+        return (B) this;
+    }
+
+    public B cbi(CbComponent add) {
+        return cbi(add, null, null);
+    }
+
+    public B cbi(CbComponent add, CbComponent remove) {
+        return cbi(add, null, remove);
+    }
+
+    public B cbi(CbComponent add, CbComponent change, CbComponent remove) {
+        if (add != null)
+            setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(comp)); 
+        if (change != null)
+            setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(comp)); 
+        if (remove != null)
+            setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(comp)); 
+        return (B) this;
+    }
+
+    public <T> B cb(CbTypeComponentRef<T, S>  add) {
+        return cb(add, null, null);
+    }
+
+    public <T> B cb(CbTypeComponentRef<T, S>  add, CbTypeComponentRef<T, S>  remove) {
+        return cb(add, null, remove);
+    }
+
+    public <T> B cb(CbTypeComponentRef<T, S>  add, CbTypeComponentRef<T, S>  change, CbTypeComponentRef<T, S>  remove) {
+        if (add != null)
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, comp, ref));              
+        if (change != null)
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, comp, ref)); 
+        if (remove != null)
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, comp, ref)); 
+        return (B) this;      
+    }
+
+    public B cbi(CbComponentRef<S> add) {
+        return cbi(add, null, null);
+    }
+
+    public B cbi(CbComponentRef<S> add, CbComponentRef<S> remove) {
+        return cbi(add, null, remove);
+    }
+
+    public B cbi(CbComponentRef<S> add, CbComponentRef<S> change, CbComponentRef<S> remove) {
+        if (add != null)
+            setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(comp, ref));
+        if (change != null)
+            setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(comp, ref));
+        if (remove != null)
+            setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(comp, ref));
+        return (B) this;
+    }
+
+    public <T> B cb(CbTypeComponentService<T, S>  add) {
+        return cb(add, null, null);
+    }
+
+    public <T> B cb(CbTypeComponentService<T, S>  add, CbTypeComponentService<T, S>  remove) {
+        return cb(add, null, remove);
+    }
+
+    public <T> B cb(CbTypeComponentService<T, S>  add, CbTypeComponentService<T, S>  change, CbTypeComponentService<T, S>  remove) {
+        if (add != null)
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, comp, srv)); 
+        if (change != null)
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, comp, srv)); 
+        if (remove != null)
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, comp, srv)); 
+        return (B) this;
+    }
+
+    public B cbi(CbComponentService<S> add) {
+        return cbi(add, null, null);
+    }
+
+    public B cbi(CbComponentService<S> add, CbComponentService<S> remove) {
+        return cbi(add, null, remove);
+    }
+
+    public B cbi(CbComponentService<S> add, CbComponentService<S> change, CbComponentService<S> remove) {
+        if (add != null)
+            setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(comp, srv));
+        if (change != null)
+            setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(comp, srv));
+        if (remove != null)
+            setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(comp, srv));
+        return (B) this;
+    }
+
+    public <T> B cb(CbTypeComponentRefService<T, S>  add) {
+        return cb(add, null, null);
+    }
+
+    public <T> B cb(CbTypeComponentRefService<T, S>  add, CbTypeComponentRefService<T, S>  remove) {
+        return cb(add, null, remove);
+    }
+
+    public <T> B cb(CbTypeComponentRefService<T, S>  add, CbTypeComponentRefService<T, S>  change, CbTypeComponentRefService<T, S>  remove) {
+        if (add != null)
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, comp, ref, srv)); 
+        if (change != null)
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, comp, ref, srv)); 
+        if (remove != null)
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, comp, ref, srv)); 
+        return (B) this;
+    }
+
+    public B cbi(CbComponentRefService<S> add) {
+        return cbi(add, null, null);
+    }
+
+    public B cbi(CbComponentRefService<S> add, CbComponentRefService<S> remove) {
+        return cbi(add, null, remove);
+    }
+
+    public B cbi(CbComponentRefService<S> add, CbComponentRefService<S> change, CbComponentRefService<S> remove) {
+        if (add != null)
+            setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(comp, ref, srv));
+        if (change != null)
+            setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(comp, ref, srv));
+        if (remove != null)
+            setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(comp, ref, srv));
+        return (B) this;
+    }
+
+    public <T> B sw(CbTypeServiceService<T, S> swap) {
+        Class<T> type = Helpers.getLambdaArgType(swap, 0);
+        return setComponentSwapCallbackRef(type, (inst, component, oref, oserv, nref, nserv) ->
+            swap.accept((T) inst, oserv, nserv));                              
+    }
+
+    public <T> B sw(CbTypeComponentServiceService<T, S> swap) {
+        Class<T> type = Helpers.getLambdaArgType(swap, 0);
+        return setComponentSwapCallbackRef(type, (inst, component, oref, oserv, nref, nserv) ->
+            swap.accept((T) inst, component, oserv, nserv));                              
+    }
+
+    public <T> B sw(CbTypeRefServiceRefService<T, S> swap) {
+        Class<T> type = Helpers.getLambdaArgType(swap, 0);
+        return setComponentSwapCallbackRef(type, (inst, component, oref, oserv, nref, nserv) ->
+            swap.accept((T) inst, oref, oserv, nref, nserv));                              
+    }
+    
+    public <T> B sw(CbTypeComponentRefServiceRefService<T, S> swap) {
+        Class<T> type = Helpers.getLambdaArgType(swap, 0);
+        return setComponentSwapCallbackRef(type, (inst, component, oref, oserv, nref, nserv) ->
+            swap.accept((T) inst, component, oref, oserv, nref, nserv));                              
+    }
+    
+    public B swi(CbServiceService<S> swap) {
+        return setInstanceSwapCallbackRef((inst, component, oref, oserv, nref, nserv) -> swap.accept(oserv, nserv));
+    }
+
+    public B swi(CbComponentServiceService<S> swap) {
+        return setInstanceSwapCallbackRef((inst, component, oref, oserv, nref, nserv) -> swap.accept(component, oserv, nserv));
+    }
+
+    public B swi(CbRefServiceRefService<S> swap) {
+        return setInstanceSwapCallbackRef((inst, component, oref, oserv, nref, nserv) -> swap.accept(oref, oserv, nref, nserv));
+    }
+    
+    public B swi(CbComponentRefServiceRefService<S> swap) {
+        return setInstanceSwapCallbackRef((inst, component, oref, oserv, nref, nserv) -> swap.accept(component, oref, oserv, nref, nserv));
+    }
+    
+    protected <I> B setComponentCallbackRef(Cb cbType, Class<I> type, MethodRef<I, S> ref) {
+       requiresNoCallbacks();
+       if (! m_autoConfigInvoked) m_autoConfig = false;
+       List<MethodRef<Object, S>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
+       list.add((instance, component, sref, service) -> {           
+           Object componentImpl = Stream.of(component.getInstances())
+               .filter(impl -> Helpers.getClass(impl).equals(type))
+               .findFirst()
+               .orElseThrow(() -> new IllegalStateException("The method reference " + ref + " does not match any available component impl classes."));           
+           ref.accept((I) componentImpl, component, sref, service);           
+       });
+       return (B) this;
+    }
+
+    protected <T> B setInstanceCallbackRef(Cb cbType, MethodRef<T, S> ref) {
+        requiresNoCallbacks();
+        if (! m_autoConfigInvoked) m_autoConfig = false;
+        List<MethodRef<Object, S>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
+        list.add((instance, component, sref, service) -> {
+            ref.accept((T) component.getInstance(), component, sref, service);
+        });
+        return (B) this;
+    }
+
+    public <I> B setComponentSwapCallbackRef(Class<I> type, SwapMethodRef<I, S> ref) {
+       requiresNoCallbacks();
+       if (! m_autoConfigInvoked) m_autoConfig = false;
+       m_swapRefs.add((instance, component, oref, oservice, nref, nservice) -> {
+           Object componentImpl = Stream.of(component.getInstances())
+               .filter(impl -> Helpers.getClass(impl).equals(type))
+               .findFirst()
+               .orElseThrow(() -> new IllegalStateException("The method reference " + ref + " does not match any available component impl classes."));
+           ref.accept((I) componentImpl, component, oref, oservice, nref, nservice);
+       });
+       return (B) this;
+    }
+
+    public <I> B setInstanceSwapCallbackRef(SwapMethodRef<I, S> ref) {
+        requiresNoCallbacks();
+        if (! m_autoConfigInvoked) m_autoConfig = false;
+        m_swapRefs.add((instance, component, oref, oservice, nref, nservice) -> {
+            ref.accept((I) component.getInstance(), component, oref, oservice, nref, nservice);
+        });
+        return (B) this;
+     }
+    
+    Object createCallbackInstance() {
+       Object cb = null;
+       
+       cb = new Object() {
+           void add(Component c, ServiceReference<S> ref, Object service) {
+               invokeMethodRefs(Cb.ADD, c, ref, (S) service);
+           }
+
+           void change(Component c, ServiceReference<S> ref, Object service) {
+               invokeMethodRefs(Cb.CHG, c, ref, (S) service);
+           }
+
+           void remove(Component c, ServiceReference<S> ref, Object service) {
+               invokeMethodRefs(Cb.REM, c, ref, (S) service);
+           }
+
+           void swap(Component c, ServiceReference<S> oldRef, Object oldSrv, ServiceReference<S> newRef, Object newSrv) {                
+               invokeSwapMethodRefs(c, oldRef, (S) oldSrv, newRef, (S) newSrv);
+           }
+       };
+
+       return cb;
+    }
+    
+    boolean hasRefs() {
+       return m_refs.size() > 0 || m_swapRefs.size() > 0;
+    }
+    
+    boolean hasCallbacks() {
+       return m_callbackInstance != null || m_added != null || m_changed != null || m_removed != null || m_swapped != null;
+    }
+    
+    String getAutoConfigField() {
+        return m_autoConfigField;
+    }
+    
+    Object getCallbackInstance() {
+        return m_callbackInstance;
+    }
+    
+    String getAdded() {
+        return m_added;
+    }
+    
+    String getChanged() {
+        return m_changed;
+    }
+    
+    String getRemoved() {
+        return m_removed;
+    }
+    
+    String getSwapped() {
+        return m_swapped;
+    }
+     
+    private void invokeMethodRefs(Cb cbType, Component comp, ServiceReference<S> ref, S service) {
+	   m_refs.computeIfPresent(cbType, (k, mrefs) -> {
+		   mrefs.forEach(mref -> mref.accept(null, comp, ref, service));
+		   return mrefs;
+		});
+    }
+   
+    private void invokeSwapMethodRefs(Component c, ServiceReference<S> oref, S osrv, ServiceReference<S> nref, S nsrv) {
+	   m_swapRefs.forEach(ref -> ref.accept(null, c, oref, osrv, nref, nsrv));
+    }   
+   
+    private void requiresNoCallbacks() {
+	   if (hasCallbacks()) { 
+		   throw new IllegalStateException("can't mix method references and string callbacks.");
+	   }
+    }
+   
+    private void requiresNoMethodRefs() {
+	   if (hasRefs()) {
+		   throw new IllegalStateException("can't mix method references and string callbacks.");
+	   }
+    }   
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceDependencyBuilderImpl.java b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceDependencyBuilderImpl.java
new file mode 100644
index 0000000..6892b1b
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceDependencyBuilderImpl.java
@@ -0,0 +1,148 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.Dictionary;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ServiceDependency;
+import org.apache.felix.dm.lambda.ServiceDependencyBuilder;
+import org.osgi.framework.ServiceReference;
+
+public class ServiceDependencyBuilderImpl<S> extends ServiceCallbacksBuilderImpl<S, ServiceDependencyBuilder<S>> implements ServiceDependencyBuilder<S> {
+    private final Class<S> m_serviceIface;
+    private final Component m_component;
+    private String m_filter;
+    private ServiceReference<S> m_ref;
+    private boolean m_required = true;
+    private String m_debug;
+    private boolean m_propagate;
+    private Object m_propagateInstance;
+    private String m_propagateMethod;
+    private Object m_defaultImpl;
+    private long m_timeout = -1;
+
+    public ServiceDependencyBuilderImpl(Component component, Class<S> service) {
+        super(service);
+        m_serviceIface = service;
+        m_component = component;
+    }
+
+    public ServiceDependencyBuilder<S> filter(String filter) {
+        m_filter = filter;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<S> ref(ServiceReference<S> ref) {
+        m_ref = ref;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<S> optional() {
+        return required(false);
+    }
+
+    public ServiceDependencyBuilder<S> required() {
+        return required(true);
+    }
+
+    public ServiceDependencyBuilder<S> required(boolean required) {
+        m_required = required;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<S> debug(String label) {
+        m_debug = label;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<S> propagate() {
+        return propagate(true);
+    }
+
+    public ServiceDependencyBuilder<S> propagate(boolean propagate) {
+        m_propagate = propagate;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<S> propagate(Object instance, String method) {
+        m_propagateInstance = instance;
+        m_propagateMethod = method;
+        return this;
+    }
+    
+    public ServiceDependencyBuilder<S> propagate(Function<ServiceReference<S>, Dictionary<String, Object>> propagate) {
+        Object wrappedCallback = new Object() {
+            @SuppressWarnings("unused")
+            Dictionary<String, Object> propagate(ServiceReference<S> ref) {
+                return propagate.apply(ref);
+            }
+        };
+        propagate(wrappedCallback, "propagate");
+        return this;
+    }    
+
+    public ServiceDependencyBuilder<S> propagate(BiFunction<ServiceReference<S>, S, Dictionary<String, Object>> propagate) {
+        Object wrappedCallback = new Object() {
+            @SuppressWarnings("unused")
+            Dictionary<String, Object> propagate(ServiceReference<S> ref, S service) {
+                return propagate.apply(ref, service);
+            }
+        };
+        propagate(wrappedCallback, "propagate");
+        return this;
+    }    
+
+    public ServiceDependencyBuilder<S> defImpl(Object defaultImpl) {
+        m_defaultImpl = defaultImpl;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<S> timeout(long timeout) {
+        m_timeout = timeout;
+        return this;
+    }
+
+   	// Build final ServiceDependency object.
+    @Override
+    public ServiceDependency build() {
+        DependencyManager dm = m_component.getDependencyManager();
+        if (m_ref != null && m_filter != null) {
+            throw new IllegalArgumentException("Can not set ref and filter at the same time");
+        }
+        ServiceDependency sd = m_timeout > -1 ? dm.createTemporalServiceDependency(m_timeout) : dm.createServiceDependency();
+        if (m_ref != null) {
+            sd.setService(m_serviceIface, m_ref);
+        } else {
+            sd.setService(m_serviceIface, m_filter);
+        }
+        sd.setRequired(m_required);
+        sd.setDefaultImplementation(m_defaultImpl);
+        if (m_debug != null) {
+            sd.setDebug(m_debug);
+        }
+        if (m_propagate) {
+            sd.setPropagate(true);
+        } else if (m_propagateInstance != null) {
+            if (m_propagateMethod == null) {
+                throw new IllegalArgumentException("propagate instance can't be null");
+            }
+            sd.setPropagate(m_propagateInstance, m_propagateMethod);
+        }
+        if (hasCallbacks()) {
+            sd.setCallbacks(m_callbackInstance, m_added, m_changed, m_removed, m_swapped);
+        } else if (hasRefs()) {
+            Object cb = createCallbackInstance();
+            sd.setCallbacks(cb, "add", "change", "remove", m_swapRefs.size() > 0 ? "swap" : null);
+        }
+        
+        if (m_autoConfigField != null) {
+            sd.setAutoConfig(m_autoConfigField);
+        } else {
+            sd.setAutoConfig(m_autoConfig);
+        }
+        return sd;
+    }
+    
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/packageinfo b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/packageinfo
new file mode 100644
index 0000000..e252556
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/test/.gitignore b/dependencymanager/org.apache.felix.dependencymanager.lambda/test/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/test/.gitignore
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd
index 69ef111..870d53c 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd
@@ -32,7 +32,7 @@
 	org.apache.felix.dependencymanager.shell;version=latest,\
 	biz.aQute.junit;version=3.0.0	
 -runee: JavaSE-1.7
--runfw: org.apache.felix.framework;version='[4.4.0,4.4.0]'
+-runfw: org.apache.felix.framework;version='[5.2.0,5.2.0]'
 -runsystempackages: \
 	sun.reflect
 -runvm:-ea
@@ -42,6 +42,11 @@
 	org.apache.felix.dm.itest.util
 -plugin: org.apache.felix.dm.annotation.plugin.bnd.AnnotationPlugin;log=debug;\
 		 path:=${workspace}/org.apache.felix.dependencymanager.annotation/generated/org.apache.felix.dependencymanager.annotation.jar
+-runproperties:  \
+	org.apache.felix.dependencymanager.loglevel=2,\
+	org.apache.felix.log.maxSize=100000,\
+	org.apache.felix.log.storeDebug=true,\
+	gosh.args=--noshutdown
 Test-Cases:  \
 	${classes;CONCRETE;EXTENDS;junit.framework.TestCase}
 Bundle-Name: Apache Felix Dependency Manager Runtime integration tests