Improve configuration error detection and reporting of service dependency (FELIX-4243 Define the dependency configuration matrix and improve error detection)
Added test about FELIX-4250 Specification deduction broken when the method does not start with the 'bind' prefix

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1527496 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/runtime/core-it/ipojo-core-service-dependency-optional-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/CheckServiceProvider.java b/ipojo/runtime/core-it/ipojo-core-service-dependency-optional-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/CheckServiceProvider.java
index 6c631f5..b708d80 100644
--- a/ipojo/runtime/core-it/ipojo-core-service-dependency-optional-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/CheckServiceProvider.java
+++ b/ipojo/runtime/core-it/ipojo-core-service-dependency-optional-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/CheckServiceProvider.java
@@ -45,28 +45,28 @@
 

     public Properties getProps() {

         Properties props = new Properties();

-        props.put("voidB", new Integer(simpleB));

-        props.put("objectB", new Integer(objectB));

-        props.put("refB", new Integer(refB));

-        props.put("bothB", new Integer(bothB));

-        props.put("voidU", new Integer(simpleU));

-        props.put("objectU", new Integer(objectU));

-        props.put("refU", new Integer(refU));

-        props.put("bothU", new Integer(bothU));

-        props.put("mapB", new Integer(mapB));

-        props.put("dictB", new Integer(dictB));

-        props.put("mapU", new Integer(mapU));

-        props.put("dictU", new Integer(dictU));

+        props.put("voidB", simpleB);

+        props.put("objectB", objectB);

+        props.put("refB", refB);

+        props.put("bothB", bothB);

+        props.put("voidU", simpleU);

+        props.put("objectU", objectU);

+        props.put("refU", refU);

+        props.put("bothU", bothU);

+        props.put("mapB", mapB);

+        props.put("dictB", dictB);

+        props.put("mapU", mapU);

+        props.put("dictU", dictU);

         if (fs != null) {

             // If nullable = false and proxy, a runtime exception may be launched here

             // catch the exception and add this to props.

             try {

                 props.put("exception", Boolean.FALSE); // Set exception to false for checking.

-                props.put("result", new Boolean(fs.foo()));

-                props.put("boolean", new Boolean(fs.getBoolean()));

-                props.put("int", new Integer(fs.getInt()));

-                props.put("long", new Long(fs.getLong()));

-                props.put("double", new Double(fs.getDouble()));

+                props.put("result", fs.foo());

+                props.put("boolean", fs.getBoolean());

+                props.put("int", fs.getInt());

+                props.put("long", fs.getLong());

+                props.put("double", fs.getDouble());

                 if(fs.getObject() != null) { props.put("object", fs.getObject()); }

             } catch (RuntimeException e) {

                 props.put("exception", Boolean.TRUE);

@@ -77,7 +77,7 @@
         

         

         // Add modified

-        props.put("modified", new Integer(modified));

+        props.put("modified", modified);

         

         return props;

     }

@@ -95,7 +95,7 @@
             System.err.println("Bind receive null !!! ");

             return;

         }

-        if(o != null && o instanceof FooService) { objectB++; }

+        objectB++;

     }

     

     protected void objectModify(FooService o) {

@@ -103,7 +103,7 @@
             System.err.println("Bind receive null !!! [" + modified + "]");

             return;

         }

-        if(o != null && o instanceof FooService) { modified++; }

+        modified++;

     }

     

     public void refBind(ServiceReference sr) {

@@ -115,30 +115,30 @@
     }

     

     public void bothBind(FooService o, ServiceReference sr) {

-        if(sr != null && o != null && o instanceof FooService) { bothB++; }

+        if(sr != null && o != null) { bothB++; }

     }

     

     public void bothModify(FooService o, ServiceReference sr) {

-        if(sr != null && o != null && o instanceof FooService) { modified++; }

+        if(sr != null && o != null) { modified++; }

     }

     

     protected void propertiesDictionaryBind(FooService o, Dictionary props) {

-        if(props != null && o != null && o instanceof FooService && props.size() > 0) { dictB++; }

+        if(props != null && o != null && props.size() > 0) { dictB++; }

         fs = o;

     }   

     

     protected void propertiesDictionaryModify(FooService o, Dictionary props) {

-        if(props != null && o != null && o instanceof FooService && props.size() > 0) { modified++; }

+        if(props != null && o != null && props.size() > 0) { modified++; }

         fs = o;

     }   

     

     protected void propertiesMapBind(FooService o, Map props) {

-        if(props != null && o != null && o instanceof FooService && props.size() > 0) { mapB++; }

+        if(props != null && o != null && props.size() > 0) { mapB++; }

         fs = o;

     } 

     

     protected void propertiesMapModify(FooService o, Map props) {

-        if(props != null && o != null && o instanceof FooService && props.size() > 0) { modified++; }

+        if(props != null && o != null && props.size() > 0) { modified++; }

         fs = o;

     } 

 

diff --git a/ipojo/runtime/core-it/ipojo-core-service-dependency-optional-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/exceptions/ExceptionAwareCheckServiceProvider.java b/ipojo/runtime/core-it/ipojo-core-service-dependency-optional-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/exceptions/ExceptionAwareCheckServiceProvider.java
index 55ed5f0..9f8a9b2 100644
--- a/ipojo/runtime/core-it/ipojo-core-service-dependency-optional-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/exceptions/ExceptionAwareCheckServiceProvider.java
+++ b/ipojo/runtime/core-it/ipojo-core-service-dependency-optional-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/exceptions/ExceptionAwareCheckServiceProvider.java
@@ -59,7 +59,7 @@
             fs.foo();
             return true; // always return true, to detect the exception case.
         } catch (NoServiceException e) {
-            return true;
+            return false;
         }
     }
 
diff --git a/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/context/ContextualFilterConsumer.java b/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/context/ContextualFilterConsumer.java
index 4415210..d234467 100644
--- a/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/context/ContextualFilterConsumer.java
+++ b/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/context/ContextualFilterConsumer.java
@@ -36,7 +36,7 @@
 @Provides
 public class ContextualFilterConsumer implements CheckService {
 
-    @Requires(nullable = false, id = "foo")
+    @Requires(id = "foo")
     private FooService foo;
 
     @Override
diff --git a/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/identification/ComponentWithCustomMethods.java b/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/identification/ComponentWithCustomMethods.java
new file mode 100644
index 0000000..b76b34d
--- /dev/null
+++ b/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/identification/ComponentWithCustomMethods.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.ipojo.runtime.core.test.components.identification;
+
+import org.apache.felix.ipojo.annotations.Bind;
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Unbind;
+import org.apache.felix.ipojo.runtime.core.test.services.Call;
+import org.apache.felix.ipojo.runtime.core.test.services.FooService;
+
+import java.util.Set;
+
+/**
+ * A component reproducing FELIX-4250 - Specification deduction broken when the method does not start with the 'bind'
+ * prefix (https://issues.apache.org/jira/browse/FELIX-4250).
+ *
+ * The add and remove methods should be attached to the same dependency (id = MyService)
+ * The set and unset methods should be attached to the same dependency (id = MyOtherService)
+ */
+@Component
+public class ComponentWithCustomMethods {
+
+    Set<FooService> myServices;
+
+    Set<Call> myOtherServices;
+
+    @Bind(optional=true, aggregate=true)
+    public void addMyService(FooService newService) {
+        myServices.add(newService);
+    }
+
+    @Unbind
+    public void removeMyService(FooService oldService) {
+        myServices.remove(oldService);
+    }
+
+
+    @Bind(optional=true, aggregate=true)
+    public void setMyOtherService(Call newService) {
+        myOtherServices.add(newService);
+    }
+
+    @Unbind
+    public void unsetMyOtherService(Call oldService) {
+        myOtherServices.remove(oldService);
+    }
+}
diff --git a/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/Common.java b/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/Common.java
index 46e0f65..8af42c8 100644
--- a/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/Common.java
+++ b/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/Common.java
@@ -19,11 +19,16 @@
 
 package org.apache.felix.ipojo.runtime.core.test.dependencies;
 
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.OptionUtils;
 import org.ow2.chameleon.testing.helpers.BaseTest;
 
 import java.util.Arrays;
 import java.util.List;
 
+import static org.ops4j.pax.exam.CoreOptions.maven;
+import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
+
 /**
  * Bootstrap the test from this project
  */
@@ -36,4 +41,12 @@
         );
     }
 
+    @Override
+    protected Option[] getCustomOptions() {
+        return new Option[] {
+                wrappedBundle(maven("org.easytesting", "fest-assert").versionAsInProject()),
+                wrappedBundle(maven("org.easytesting", "fest-util").versionAsInProject())
+        };
+    }
+
 }
diff --git a/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/identification/TestDependencyIdDetection.java b/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/identification/TestDependencyIdDetection.java
new file mode 100644
index 0000000..630058d
--- /dev/null
+++ b/ipojo/runtime/core-it/ipojo-core-service-dependency-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/identification/TestDependencyIdDetection.java
@@ -0,0 +1,108 @@
+/*

+ * 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.ipojo.runtime.core.test.dependencies.identification;

+

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.annotations.HandlerDeclaration;

+import org.apache.felix.ipojo.architecture.HandlerDescription;

+import org.apache.felix.ipojo.handlers.dependency.DependencyCallback;

+import org.apache.felix.ipojo.handlers.dependency.DependencyDescription;

+import org.apache.felix.ipojo.handlers.dependency.DependencyHandlerDescription;

+import org.apache.felix.ipojo.runtime.core.test.dependencies.Common;

+import org.junit.Test;

+

+import static org.fest.assertions.Assertions.assertThat;

+

+public class TestDependencyIdDetection extends Common {

+    String factory = "org.apache.felix.ipojo.runtime.core.test.components.identification.ComponentWithCustomMethods";

+

+    @Test

+    public void testSetAndUnSetMethods() {

+        ComponentInstance instance = ipojoHelper.createComponentInstance(factory);

+        DependencyHandlerDescription dh = (DependencyHandlerDescription) instance.getInstanceDescription()

+                .getHandlerDescription("org.apache.felix.ipojo:requires");

+

+        DependencyDescription dd = findDependencyById(dh, "MyOtherService");

+        assertThat(dd).isNotNull();

+

+        DependencyCallback[] callbacks = dd.getDependency().getDependencyCallbacks();

+        assertThat(callbacks).isNotNull();

+

+        DependencyCallback bind = getBindCallback(callbacks);

+        DependencyCallback unbind = getUnbindCallback(callbacks);

+

+        assertThat(bind).isNotNull();

+        assertThat(unbind).isNotNull();

+

+        assertThat(bind.getMethodName()).isEqualTo("setMyOtherService");

+        assertThat(unbind.getMethodName()).isEqualTo("unsetMyOtherService");

+    }

+

+    @Test

+    public void testAddAndRemoveMethods() {

+        ComponentInstance instance = ipojoHelper.createComponentInstance(factory);

+        DependencyHandlerDescription dh = (DependencyHandlerDescription) instance.getInstanceDescription()

+                .getHandlerDescription("org.apache.felix.ipojo:requires");

+

+        DependencyDescription dd = findDependencyById(dh, "MyService");

+        assertThat(dd).isNotNull();

+

+        DependencyCallback[] callbacks = dd.getDependency().getDependencyCallbacks();

+        assertThat(callbacks).isNotNull();

+

+        DependencyCallback bind = getBindCallback(callbacks);

+        DependencyCallback unbind = getUnbindCallback(callbacks);

+

+        assertThat(bind).isNotNull();

+        assertThat(unbind).isNotNull();

+

+        assertThat(bind.getMethodName()).isEqualTo("addMyService");

+        assertThat(unbind.getMethodName()).isEqualTo("removeMyService");

+    }

+

+    private DependencyCallback getBindCallback(DependencyCallback[] callbacks) {

+        for (DependencyCallback callback : callbacks) {

+            if (callback.getMethodType() == DependencyCallback.BIND) {

+                return callback;

+            }

+        }

+        return null;

+    }

+

+    private DependencyCallback getUnbindCallback(DependencyCallback[] callbacks) {

+        for (DependencyCallback callback : callbacks) {

+            if (callback.getMethodType() == DependencyCallback.UNBIND) {

+                return callback;

+            }

+        }

+        return null;

+    }

+

+    private DependencyDescription findDependencyById(DependencyHandlerDescription dh, String id) {

+        for (DependencyDescription dd : dh.getDependencies()) {

+            if (dd.getId().equals(id)) {

+                return dd;

+            }

+        }

+        return null;

+    }

+

+

+}

diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
index 0383ce3..660ceba 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
@@ -187,7 +187,7 @@
         } catch (Throwable e) { // All others exception are handled here.
             // As for the previous case, the instance is stopped.
             instance.stop();
-            m_logger.log(Logger.ERROR, e.getMessage(), e);
+            m_logger.log(Logger.INFO, "An error occurred when creating an instance of " + getFactoryName(), e);
             throw new ConfigurationException(e.getMessage(), e);
         }
 
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/AggregateDependencyInjectionType.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/AggregateDependencyInjectionType.java
new file mode 100644
index 0000000..56ba6ec
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/AggregateDependencyInjectionType.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.ipojo.handlers.dependency;
+
+import java.util.*;
+
+/**
+ * An enumeration listing the different possibility to inject an aggregate dependency in a field or constructor
+ * parameter.
+ */
+public enum AggregateDependencyInjectionType {
+
+    ARRAY,
+    LIST,
+    SET,
+    VECTOR;
+
+    public static List<String> AGGREGATE_TYPES =
+        Arrays.asList(
+                List.class.getName(),
+                Vector.class.getName(),
+                Set.class.getName(),
+                Collection.class.getName());
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
index 9017751..4f9c71a 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.felix.ipojo.handlers.dependency;
 
 import org.apache.felix.ipojo.*;
@@ -80,10 +81,11 @@
      */
     private ServiceUsage m_usage;
     /**
-     * Type of the object to inject.
+     * Type of the object to inject in aggregate dependency. This value is used to determine what kind of object need
+     * to be injected for fields and constructor parameter for aggregate dependencies.
      * Cannot change once set.
      */
-    private int m_type;
+    private AggregateDependencyInjectionType m_type;
     /**
      * Nullable object.
      * Immutable once set.
@@ -107,6 +109,10 @@
      * -1 if not used.
      */
     private int m_index = -1;
+
+    /**
+     * The dependency timeout.
+     */
     private int m_timeout;
 
     /**
@@ -599,6 +605,16 @@
         }
     }
 
+
+    /**
+     * Gets the list of callbacks attached to the current dependency.
+     * @return the array of dependency callback, {@code null} if no callbacks are attached to the current dependency.
+     */
+    public DependencyCallback[] getDependencyCallbacks() {
+        return m_callbacks;
+    }
+
+
     /**
      * Called by the proxy to get  service objects to delegate a method.
      * On aggregate dependencies, it returns a list.
@@ -690,7 +706,7 @@
     public Object onGet(Object pojo, String fieldName, Object value) {
 
         // Initialize the thread local object is not already touched.
-        Usage usage = (Usage) m_usage.get();
+        Usage usage = m_usage.get();
         if (usage.m_stack == 0) { // uninitialized usage.
             createServiceObject(usage);
             usage.inc(); // Start the caching, so set the stack level to 1
@@ -737,59 +753,60 @@
                 usage.m_object = getService(ref);
             }
         } else {
-            if (m_type == 0) { // Array
-                try {
+            switch(m_type) {
+                case ARRAY:
+                    try {
+                        if (refs == null) {
+                            usage.m_object = (Object[]) Array.newInstance(getSpecification(), 0); // Create an empty array.
+                        } else {
+                            //  Use a reflective construction to avoid class cast exception. This method allows setting the component type.
+                            Object[] objs = (Object[]) Array.newInstance(getSpecification(), refs.length);
+                            for (int i = 0; i < refs.length; i++) {
+                                ServiceReference ref = refs[i];
+                                objs[i] = getService(ref);
+                            }
+                            usage.m_object = objs;
+                        }
+                    } catch (ArrayStoreException e) {
+                        throw new RuntimeException("Cannot create the array - Check that the bundle can access the service interface", e);
+                    }
+                    break;
+                case LIST:
                     if (refs == null) {
-                        usage.m_object = (Object[]) Array.newInstance(getSpecification(), 0); // Create an empty array.
+                        usage.m_object = Collections.emptyList();
                     } else {
-                        //  Use a reflective construction to avoid class cast exception. This method allows setting the component type.
-                        Object[] objs = (Object[]) Array.newInstance(getSpecification(), refs.length);
-                        for (int i = 0; i < refs.length; i++) {
-                            ServiceReference ref = refs[i];
-                            objs[i] = getService(ref);
+                        // Use a list to store service objects
+                        List<Object> objs = new ArrayList<Object>(refs.length);
+                        for (ServiceReference ref : refs) {
+                            objs.add(getService(ref));
                         }
                         usage.m_object = objs;
                     }
-                } catch (ArrayStoreException e) {
-                    m_handler.error("Cannot create the array - Check that the bundle can access the service interface", e);
-                    throw new RuntimeException("Cannot create the array - Check that the bundle can access the service interface", e);
-                }
-            } else if (m_type == DependencyHandler.LIST) {
-                if (refs == null) {
-                    usage.m_object = new ArrayList(0); // Create an empty list.
-                } else {
-                    // Use a list to store service objects
-                    List objs = new ArrayList(refs.length);
-                    for (int i = 0; refs != null && i < refs.length; i++) {
-                        ServiceReference ref = refs[i];
-                        objs.add(getService(ref));
+                    break;
+                case SET:
+                    if (refs == null) {
+                        usage.m_object = Collections.emptySet();
+                    } else {
+                        // Use a vector to store service objects
+                        Set<Object> objs = new HashSet<Object>(refs.length);
+                        for (ServiceReference ref : refs) {
+                            objs.add(getService(ref));
+                        }
+                        usage.m_object = objs;
                     }
-                    usage.m_object = objs;
-                }
-            } else if (m_type == DependencyHandler.VECTOR) {
-                if (refs == null) {
-                    usage.m_object = new Vector(0); // Create an empty vector.
-                } else {
-                    // Use a vector to store service objects
-                    Vector objs = new Vector(refs.length);
-                    for (int i = 0; refs != null && i < refs.length; i++) {
-                        ServiceReference ref = refs[i];
-                        objs.add(getService(ref));
+                    break;
+                case VECTOR:
+                    if (refs == null) {
+                        usage.m_object = new Vector(0); // Create an empty vector.
+                    } else {
+                        // Use a vector to store service objects
+                        Vector<Object> objs = new Vector<Object>(refs.length);
+                        for (ServiceReference ref : refs) {
+                            objs.add(getService(ref));
+                        }
+                        usage.m_object = objs;
                     }
-                    usage.m_object = objs;
-                }
-            } else if (m_type == DependencyHandler.SET) {
-                if (refs == null) {
-                    usage.m_object = new HashSet(0); // Create an empty vector.
-                } else {
-                    // Use a vector to store service objects
-                    Set objs = new HashSet(refs.length);
-                    for (int i = 0; refs != null && i < refs.length; i++) {
-                        ServiceReference ref = refs[i];
-                        objs.add(getService(ref));
-                    }
-                    usage.m_object = objs;
-                }
+                    break;
             }
         }
     }
@@ -841,7 +858,7 @@
      */
     public void onEntry(Object pojo, Member method, Object[] args) {
         if (m_usage != null) {
-            Usage usage = (Usage) m_usage.get();
+            Usage usage = m_usage.get();
             usage.incComponentStack(); // Increment the number of component access.
             if (usage.m_stack > 0) {
                 usage.inc();
@@ -884,13 +901,14 @@
      */
     public void onFinally(Object pojo, Member method) {
         if (m_usage != null) {
-            Usage usage = (Usage) m_usage.get();
+            Usage usage = m_usage.get();
             usage.decComponentStack();
             if (usage.m_stack > 0) {
                 if (usage.dec()) {
                     // Exit the method flow => Release all objects
                     usage.clear();
-                    m_usage.set(usage); // Set the Thread local as value has been modified
+                    // Also remove the thread local object.
+                    m_usage.remove();
                 }
             }
         }
@@ -902,7 +920,9 @@
      * @return true if the dependency is optional and supports nullable objects.
      */
     public boolean supportsNullable() {
-        return m_supportNullable;
+        return isOptional()
+                && ! isAggregate()
+                && m_supportNullable;
     }
 
     public String getDefaultImplementation() {
@@ -921,9 +941,9 @@
      * Set the type to inject.
      * This method set the dependency as aggregate.
      *
-     * @param type either list of vector
+     * @param type the type to inject.
      */
-    protected void setType(int type) {
+    protected void setAggregateType(AggregateDependencyInjectionType type) {
         setAggregate(true);
         m_type = type;
     }
@@ -974,11 +994,10 @@
         if (m_index == index && m_proxyObject != null) {
             if (isAggregate()) {
                 switch (m_type) {
-                    case DependencyHandler.LIST:
+                    case LIST:
                         return List.class;
-                    case DependencyHandler.SET:
+                    case SET:
                         return Set.class;
-                    //TODO We should also manage the Collection type.
                     default:
                         return null; // Should never happen, it was checked before.
                 }
@@ -990,6 +1009,18 @@
         }
     }
 
+    public String getException() {
+        return m_exception;
+    }
+
+    public int getTimeout() {
+        return m_timeout;
+    }
+
+    public AggregateDependencyInjectionType getAggregateType() {
+        return m_type;
+    }
+
     /**
      * Classloader for nullable objects.
      */
@@ -1173,7 +1204,7 @@
             Class declaringClass = method.getDeclaringClass();
             if (declaringClass == Object.class) {
                 if (method.equals(m_hashCodeMethod)) {
-                    return new Integer(this.hashCode());
+                    return this.hashCode();
                 } else if (method.equals(m_equalsMethod)) {
                     return proxy == args[0] ? Boolean.TRUE : Boolean.FALSE;
                 } else if (method.equals(m_toStringMethod)) {
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java
index 571a92c..a7b4c4b 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -18,20 +18,17 @@
  */
 package org.apache.felix.ipojo.handlers.dependency;
 
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
 import org.apache.felix.ipojo.util.Callback;
 import org.osgi.framework.ServiceReference;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+
 /**
  * This class allwos the creation of callback when service dependency arrives or
  * disappear.
- * 
+ *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class DependencyCallback extends Callback {
@@ -40,44 +37,38 @@
      * Bind method (called when a service arrives).
      */
     public static final int BIND = 0;
-
     /**
      * Unbind method (called when a service disappears).
      */
     public static final int UNBIND = 1;
-    
     /**
      * Updated method (called when a service is modified).
      */
     public static final int MODIFIED = 2;
-
     /**
      * Is the method a bind method or an unbind method ?
      */
     private int m_methodType;
-    
     /**
      * Arguments of the callback.
      */
     private String[] m_argument;
-
     /**
      * Callback method name.
      */
     private String m_method;
-    
     /**
-     * Service Dependency. 
+     * Service Dependency.
      */
     private Dependency m_dependency;
 
     /**
      * Constructor.
-     * 
-     * @param dep : the dependency attached to this dependency callback
-     * @param method : the method to call
+     *
+     * @param dep        : the dependency attached to this dependency callback
+     * @param method     : the method to call
      * @param methodType : is the method to call a bind method or an unbind
-     * method
+     *                   method
      */
     public DependencyCallback(Dependency dep, String method, int methodType) {
         super(method, (String[]) null, false, dep.getHandler().getInstanceManager());
@@ -86,23 +77,23 @@
         m_method = method;
     }
 
-
     public int getMethodType() {
         return m_methodType;
     }
-    
+
     public String getMethodName() {
         return m_method;
     }
-    
+
     /**
      * Set the argument type (Empty or the class name).
+     *
      * @param arg : the array of argument types.
      */
     public void setArgument(String[] arg) {
         m_argument = arg;
     }
-    
+
     /**
      * Search the method object in the POJO by analyzing present method.
      * If not found in the pojo it tests the parent classes.
@@ -111,11 +102,11 @@
     protected void searchMethod() {
         if (m_argument != null) {
             Method[] methods = m_dependency.getHandler().getInstanceManager().getClazz().getDeclaredMethods();
-            for (int i = 0; i < methods.length; i++) {
+            for (Method method : methods) {
                 // First check the method name
-                if (methods[i].getName().equals(m_method)) {
+                if (method.getName().equals(m_method)) {
                     // Check arguments
-                    Class[] clazzes = methods[i].getParameterTypes();
+                    Class[] clazzes = method.getParameterTypes();
                     if (clazzes.length == m_argument.length) { // Test size to avoid useless loop // NOPMD
                         int argIndex = 0;
                         for (; argIndex < m_argument.length; argIndex++) {
@@ -124,8 +115,8 @@
                             }
                         }
                         if (argIndex == m_argument.length) { // If the array was completely read.
-                            m_methodObj = methods[i]; // It is the looked method.
-                            if (! m_methodObj.isAccessible()) { 
+                            m_methodObj = method; // It is the looked method.
+                            if (!m_methodObj.isAccessible()) {
                                 // If not accessible, try to set the accessibility.
                                 m_methodObj.setAccessible(true);
                             }
@@ -136,22 +127,24 @@
                 }
             }
         }
-        
+
         // Not found => Try parent method.
         searchParentMethod();
-        
+
         if (m_methodObj == null) {
             // If not found, stop the instance (fatal error)
-            m_dependency.getHandler().error("The method " + m_method + " cannot be called : method not found");
+            m_dependency.getHandler().error("The dependency callback method " + m_method + " cannot be invoked - " +
+                    "reason: the method is not defined in the component class (" + m_dependency.getHandler()
+                    .getInstanceManager().getClazz().getName() + ")");
             m_dependency.getHandler().getInstanceManager().stop();
         } else {
-            if (! m_methodObj.isAccessible()) { 
+            if (!m_methodObj.isAccessible()) {
                 // If not accessible, try to set the accessibility.
                 m_methodObj.setAccessible(true);
             }
         }
     }
-    
+
     /**
      * Introspect parent class to find the method.
      */
@@ -174,14 +167,14 @@
                         if (clazzes[0].getName().equals(ServiceReference.class.getName())) {
                             // Callback with a service reference.
                             m_methodObj = methods[i];
-                            m_argument = new String[] { ServiceReference.class.getName() };
+                            m_argument = new String[]{ServiceReference.class.getName()};
                             return;
                         }
                         // The callback receives a Service object
                         if (clazzes[0].getName().equals(m_dependency.getSpecification().getName())) {
                             // Callback with the service object.
                             m_methodObj = methods[i];
-                            m_argument = new String[] { m_dependency.getSpecification().getName() };
+                            m_argument = new String[]{m_dependency.getSpecification().getName()};
                             return;
                         }
                         break;
@@ -190,21 +183,21 @@
                         if (clazzes[0].getName().equals(m_dependency.getSpecification().getName()) && clazzes[1].getName().equals(ServiceReference.class.getName())) {
                             // Callback with two arguments.
                             m_methodObj = methods[i];
-                            m_argument = new String[] { m_dependency.getSpecification().getName(), ServiceReference.class.getName() };
+                            m_argument = new String[]{m_dependency.getSpecification().getName(), ServiceReference.class.getName()};
                             return;
                         }
                         // The callback receives the service object and the service properties (in a Map)
                         if (clazzes[0].getName().equals(m_dependency.getSpecification().getName()) && clazzes[1].getName().equals(Map.class.getName())) {
                             // Callback with two arguments.
                             m_methodObj = methods[i];
-                            m_argument = new String[] { m_dependency.getSpecification().getName(), Map.class.getName() };
+                            m_argument = new String[]{m_dependency.getSpecification().getName(), Map.class.getName()};
                             return;
                         }
                         // The callback receives the service object and the service properties (in a Dictionary)
                         if (clazzes[0].getName().equals(m_dependency.getSpecification().getName()) && clazzes[1].getName().equals(Dictionary.class.getName())) {
                             // Callback with two arguments.
                             m_methodObj = methods[i];
-                            m_argument = new String[] { m_dependency.getSpecification().getName(), Dictionary.class.getName() };
+                            m_argument = new String[]{m_dependency.getSpecification().getName(), Dictionary.class.getName()};
                             return;
                         }
                         break;
@@ -217,38 +210,38 @@
 
     /**
      * Call the callback method with a service reference.
-     * 
+     *
      * @param ref : the service reference to send to the method
      * @param obj : the service object
-     * @throws NoSuchMethodException : Method is not found in the class
+     * @throws NoSuchMethodException     : Method is not found in the class
      * @throws InvocationTargetException : The method is not static
-     * @throws IllegalAccessException : The method can not be invoked
+     * @throws IllegalAccessException    : The method can not be invoked
      */
     protected void call(ServiceReference ref, Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         if (m_methodObj == null) {
             searchMethod();
         }
         switch (m_argument.length) {
-            case 0 :
+            case 0:
                 call(new Object[0]);
                 break;
-            case 1 : 
+            case 1:
                 if (m_argument[0].equals(ServiceReference.class.getName())) {
-                    call(new Object[] {ref});
+                    call(new Object[]{ref});
                 } else {
-                    call(new Object[] {obj});
+                    call(new Object[]{obj});
                 }
                 break;
-            case 2 :
+            case 2:
                 if (m_argument[1].equals(ServiceReference.class.getName())) {
-                    call(new Object[] {obj, ref});
+                    call(new Object[]{obj, ref});
                 } else if (m_argument[1].equals(Dictionary.class.getName())) {
-                    call(new Object[] {obj, getPropertiesInDictionary(ref)});
+                    call(new Object[]{obj, getPropertiesInDictionary(ref)});
                 } else {
-                    call(new Object[] {obj, getPropertiesInMap(ref)});
+                    call(new Object[]{obj, getPropertiesInMap(ref)});
                 }
                 break;
-            default : 
+            default:
                 break;
         }
     }
@@ -256,6 +249,7 @@
     /**
      * Creates a {@link Dictionary} containing service properties of the
      * given service reference.
+     *
      * @param ref the service reference
      * @return a {@link Dictionary} containing the service properties.
      */
@@ -267,10 +261,11 @@
         }
         return dict;
     }
-    
+
     /**
      * Creates a {@link Map} containing service properties of the
      * given service reference.
+     *
      * @param ref the service reference
      * @return a {@link Map} containing the service properties.
      */
@@ -283,15 +278,14 @@
         return map;
     }
 
-
     /**
      * Call the callback on the given instance with the given argument.
-     * 
+     *
      * @param instance : the instance on which call the callback
-     * @param ref : the service reference to send to the callback
-     * @param obj : the service object
-     * @throws NoSuchMethodException : the method is not found
-     * @throws IllegalAccessException : the method could not be called
+     * @param ref      : the service reference to send to the callback
+     * @param obj      : the service object
+     * @throws NoSuchMethodException     : the method is not found
+     * @throws IllegalAccessException    : the method could not be called
      * @throws InvocationTargetException : an error happens in the called method
      */
     protected void callOnInstance(Object instance, ServiceReference ref, Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
@@ -299,26 +293,26 @@
             searchMethod();
         }
         switch (m_argument.length) {
-            case 0 :
+            case 0:
                 call(instance, new Object[0]);
                 break;
-            case 1 : 
+            case 1:
                 if (m_argument[0].equals(ServiceReference.class.getName())) {
-                    call(instance, new Object[] {ref});
+                    call(instance, new Object[]{ref});
                 } else {
-                    call(instance, new Object[] {obj});
+                    call(instance, new Object[]{obj});
                 }
                 break;
-            case 2 :
+            case 2:
                 if (m_argument[1].equals(ServiceReference.class.getName())) {
-                    call(instance, new Object[] {obj, ref});
+                    call(instance, new Object[]{obj, ref});
                 } else if (m_argument[1].equals(Dictionary.class.getName())) {
-                    call(instance, new Object[] {obj, getPropertiesInDictionary(ref)});
+                    call(instance, new Object[]{obj, getPropertiesInDictionary(ref)});
                 } else {
-                    call(instance, new Object[] {obj, getPropertiesInMap(ref)});
+                    call(instance, new Object[]{obj, getPropertiesInMap(ref)});
                 }
                 break;
-            default : 
+            default:
                 break;
         }
     }
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyConfigurationChecker.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyConfigurationChecker.java
new file mode 100644
index 0000000..ab84903
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyConfigurationChecker.java
@@ -0,0 +1,465 @@
+/*
+ * 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.ipojo.handlers.dependency;
+
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.FieldMetadata;
+import org.apache.felix.ipojo.parser.MethodMetadata;
+import org.apache.felix.ipojo.parser.PojoMetadata;
+import org.apache.felix.ipojo.util.DependencyModel;
+import org.osgi.framework.ServiceReference;
+
+import java.util.*;
+
+/**
+ * Utility class checking the configuration of a dependency.
+ */
+public class DependencyConfigurationChecker {
+
+    public static void ensure(Dependency dependency, Element metadata, PojoMetadata manipulation) throws
+            ConfigurationException {
+        ensureThatAtLeastOneInjectionIsSpecified(dependency);
+        ensureThatTheFieldIsInComponentClass(dependency, manipulation);
+        ensureThatTheConstructorParameterIsCoherent(dependency, manipulation);
+        ensureThatCallbacksAreCoherent(dependency, manipulation);
+        deduceAggregationFromTheInjectionPoints(dependency, manipulation);
+        deduceTheServiceSpecification(dependency, manipulation);
+        checkTheServiceUnavailableAction(dependency, metadata);
+        checkTheConsistencyOfTheFromAttribute(dependency, metadata);
+        disableProxyForInconsistentTypes(dependency);
+    }
+
+    /**
+     * Disables the proxy settings for types that does not support it: Vector, Array, and non interface specification.
+     * If the dependency is disabled, check that we are no constructor injection.
+     * @param dependency the dependency
+     */
+    private static void disableProxyForInconsistentTypes(Dependency dependency) throws ConfigurationException {
+        if (! dependency.getSpecification().isInterface()
+                || dependency.isAggregate()  && dependency.getAggregateType() == AggregateDependencyInjectionType.ARRAY
+                || dependency.isAggregate()  && dependency.getAggregateType() == AggregateDependencyInjectionType.VECTOR) {
+            dependency.setProxy(false);
+            if (dependency.getConstructorParameterIndex() != -1) {
+                throw new ConfigurationException("The dependency " + DependencyHandler.getDependencyIdentifier
+                        (dependency) + " has an inconsistent configuration. - reason: the service specification " +
+                        "or container do not support proxy, which is required for constructor injection");
+            }
+            dependency.getHandler().info("Proxy disabled for " + DependencyHandler.getDependencyIdentifier
+                    (dependency) + " - the service specification or container do not support proxy");
+        }
+    }
+
+    /**
+     * Checks that the dependency callbacks are consistent:
+     * <ul>
+     *     <li>have a supported 'type'</li>
+     *     <li>have a supported signature</li>
+     * </ul>
+     * If the method is not in the component class, a message is logged, as this verification cannot be used.
+     * If the method is found in the manipulation metadata, the callback parameters are set.
+     * @param dependency the dependency
+     * @param manipulation the manipulation
+     * @throws ConfigurationException if the methods do not obey to the previously mentioned rules.
+     */
+    private static void ensureThatCallbacksAreCoherent(Dependency dependency, PojoMetadata manipulation) throws
+            ConfigurationException {
+        DependencyCallback[] callbacks = dependency.getCallbacks();
+        if (callbacks != null) {
+            for (DependencyCallback callback : callbacks) {
+                MethodMetadata metadata = manipulation.getMethod(callback.getMethodName());
+                if (metadata == null) {
+                    dependency.getHandler().debug("A dependency callback " + callback.getMethodName() + " of " +
+                            DependencyHandler.getDependencyIdentifier(dependency) + " does not " +
+                            "exist in the implementation class, will try the parent classes");
+                } else {
+                    String[] parameters = metadata.getMethodArguments();
+                   switch(parameters.length) {
+                       case 0 : // Just a notification method.
+                            callback.setArgument(parameters);
+                            break;
+                       case 1 :
+                           // Can be the service object, service reference or properties
+                           callback.setArgument(parameters);
+                           break;
+                       case 2 :
+                           // Constraints on the second argument, must be a service reference, a dictionary or a map
+                           if (!ServiceReference.class.getName().equals(parameters[1])
+                               && ! Dictionary.class.getName().equals(parameters[1])
+                               && ! Map.class.getName().equals(parameters[1])) {
+                                throw new ConfigurationException("The method " + callback.getMethodName() + " of " +
+                                        DependencyHandler.getDependencyIdentifier(dependency) + " is not a valid " +
+                                        "dependency callback - reason: the second argument (" + parameters[1] +
+                                        ")  must be a service reference, a dictionary or a map.");
+                                }
+                           callback.setArgument(parameters);
+                           break;
+                       default:
+                           // Invalid signature.
+                           throw new ConfigurationException("The method " + callback.getMethodName() + " of " +
+                                   DependencyHandler.getDependencyIdentifier(dependency) + " is not a valid " +
+                                   "dependency callback - reason: the signature is invalid");
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Checks whether the constructor parameter injection is suitable. this check verified that the constructor has
+     * enough parameter.
+     * @param dependency the dependency
+     * @param manipulation the manipulation metadata
+     * @throws ConfigurationException if the constructor is not suitable
+     */
+    private static void ensureThatTheConstructorParameterIsCoherent(Dependency dependency,
+                                                                    PojoMetadata manipulation) throws
+            ConfigurationException {
+        if (dependency.getConstructorParameterIndex() != -1) {
+            MethodMetadata[] constructors = manipulation.getConstructors();
+            if (constructors == null  || constructors.length == 0) {
+                throw new ConfigurationException("The constructor parameter attribute of " + DependencyHandler
+                        .getDependencyIdentifier(dependency) + " is inconsistent - reason: there is no constructor in" +
+                        " the component class (" + dependency.getHandler().getInstanceManager().getClassName() + ")");
+            }
+
+            //TODO Consider only the first constructor. This is a limitation we should think about,
+            // how to determine which constructor to use. Only one constructor should have annotations,
+            // it could be use as hint.
+            MethodMetadata constructor = constructors[0];
+            if (! (constructor.getMethodArguments().length > dependency.getConstructorParameterIndex())) {
+                throw new ConfigurationException("The constructor parameter attribute of " + DependencyHandler
+                        .getDependencyIdentifier(dependency) + " is inconsistent - reason: the constructor with the " +
+                        "signature " + Arrays.toString(constructor.getMethodArguments()) + " has not enough " +
+                        "parameters");
+            }
+
+        }
+    }
+
+    /**
+     * Checks that the field used to inject the dependency is in the component class. If the dependency has no field,
+     * this method does nothing.
+     * @param dependency the dependency
+     * @param manipulation the manipulation metadata
+     * @throws ConfigurationException if the field used to inject the given dependency is not in the component class.
+     */
+    private static void ensureThatTheFieldIsInComponentClass(Dependency dependency, PojoMetadata manipulation) throws ConfigurationException {
+        if (dependency.getField() != null) {
+            FieldMetadata field = manipulation.getField(dependency.getField());
+            if (field == null) {
+                throw new ConfigurationException("Incorrect field injection for " + DependencyHandler
+                        .getDependencyIdentifier(dependency) + " - reason: the field " + dependency.getField() + " is" +
+                        " not in the component class (" + dependency.getHandler().getInstanceManager().getClassName()
+                      + ")");
+            }
+        }
+    }
+
+    /**
+     * Determines if the dependency is aggregate from the field or constructor parameter used to inject the dependency.
+     * If the dependency just uses methods, this method does nothing. This method also check that dependencies set to
+     * aggregate have a valid injection type.
+     * @param dependency the dependency
+     * @param manipulation the manipulation metadata
+     * @throws ConfigurationException if the type of the field or constructor parameter used to inject the dependency
+     * is not suitable for aggregate dependencies.
+     */
+    private static void deduceAggregationFromTheInjectionPoints(Dependency dependency, PojoMetadata manipulation) throws ConfigurationException {
+        if (dependency.getField() != null) {
+            FieldMetadata field = manipulation.getField(dependency.getField());
+            String type = field.getFieldType();
+            if (type.endsWith("[]")) {
+                dependency.setAggregateType(AggregateDependencyInjectionType.ARRAY);
+            } else if (Collection.class.getName().equals(type)  || List.class.getName().equals(type)) {
+                dependency.setAggregateType(AggregateDependencyInjectionType.LIST);
+            } else if (Set.class.getName().equals(type)) {
+                dependency.setAggregateType(AggregateDependencyInjectionType.SET);
+            } else if (Vector.class.getName().equals(type)) {
+                dependency.setAggregateType(AggregateDependencyInjectionType.VECTOR);
+            } else if (dependency.isAggregate()) {
+                // Something wrong. The dependency has a field that is not suitable for aggregate dependencies
+                throw new ConfigurationException("The dependency " + DependencyHandler.getDependencyIdentifier
+                        (dependency) + " cannot be an aggregate dependency - reason: the type " + field.getFieldType
+                        () + " of the field " + field.getFieldName() + " is not suitable for aggregate " +
+                        "dependencies. Compatible types are array, vector, list, set and collection.");
+            }
+        }
+        if (dependency.getConstructorParameterIndex() != -1) {
+            String type = manipulation.getConstructors()[0].getMethodArguments()[dependency
+                    .getConstructorParameterIndex()];
+            if (type.endsWith("[]")) {
+                dependency.setAggregateType(AggregateDependencyInjectionType.ARRAY);
+            } else if (Collection.class.getName().equals(type)  || List.class.getName().equals(type)) {
+                dependency.setAggregateType(AggregateDependencyInjectionType.LIST);
+            } else if (Set.class.getName().equals(type)) {
+                dependency.setAggregateType(AggregateDependencyInjectionType.SET);
+            } else if (Vector.class.getName().equals(type)) {
+                dependency.setAggregateType(AggregateDependencyInjectionType.VECTOR);
+            } else if (dependency.isAggregate()) {
+                // Something wrong. The dependency has a field that is not suitable for aggregate dependencies
+                throw new ConfigurationException("The dependency " + DependencyHandler.getDependencyIdentifier
+                        (dependency) + " cannot be an aggregate dependency - reason: the type " + type
+                        + " of the constructor parameter " + dependency.getConstructorParameterIndex() + " is not suitable for aggregate " +
+                        "dependencies. Compatible types are array, vector, list, set and collection.");
+            }
+        }
+        //TODO We may not cover some cases such as inconsistency between the constructor and the field. However this
+        // should be very rare.
+
+    }
+
+    /**
+     * Checks that the dependency has at least one injection point.
+     * @param dependency the dependency
+     * @throws ConfigurationException if the dependency has no injection point
+     */
+    private static void ensureThatAtLeastOneInjectionIsSpecified(Dependency dependency) throws ConfigurationException {
+        if (dependency.getField() == null
+                && (dependency.getCallbacks() == null  || dependency.getCallbacks().length == 0)
+                && dependency.getConstructorParameterIndex() == -1) {
+            throw new ConfigurationException("The dependency " + DependencyHandler.getDependencyIdentifier
+                    (dependency) + " is invalid - reason: no injection specified, at least a field, " +
+                    "a method or a constructor parameter index must be set");
+        }
+    }
+
+    /**
+     * Checks that the `from` attribute is used consistently:
+     * <ul>
+     * <li>Rule 1 : it cannot be used on aggregate dependency</li>
+     * <li>Rule 2 : it cannot be used in combination with the `comparator` attribute</li>
+     * <li>Rule 3 : it cannot be used in combination with the `dynamic-priority` binding policy</li>
+     * </ul>
+     *
+     * @param dependency the dependency
+     * @param metadata the dependency metadata
+     * @throws ConfigurationException if the `from` attribute is used inconsistently.
+     */
+    private static void checkTheConsistencyOfTheFromAttribute(Dependency dependency,
+                                                              Element metadata) throws ConfigurationException {
+        // Check if we have a from attribute.
+        if (metadata.getAttribute("from") != null) {
+            final String message = "The `from` attribute is not usable in " + DependencyHandler
+                    .getDependencyIdentifier(dependency) + " - reason: ";
+            // Rule 1
+            if (dependency.isAggregate()) {
+                throw new ConfigurationException(message + "the dependency is " +
+                        "aggregate");
+            }
+            // Rule 2
+            String comparator = metadata.getAttribute("comparator");
+            if (comparator != null) {
+                throw new ConfigurationException(message + "the dependency uses a comparator");
+            }
+            // Rule 3
+            if (dependency.getBindingPolicy() == DependencyModel.DYNAMIC_PRIORITY_BINDING_POLICY) {
+                throw new ConfigurationException(message + "the dependency uses the dynamic-priority " +
+                        "binding policy");
+            }
+        }
+    }
+
+    /**
+     * Checks that service unavailable actions are consistent.
+     * <ul>
+     * <li>Rule 1: Nullable, Exception, Default-Implementation... can only be used for scalar optional dependency</li>
+     * <li>Rule 2: Only one can be used</li>
+     * <li>Rule 3: Timeout can only be used on optional dependency</li>
+     * </ul>
+     *
+     * @param dependency the dependency
+     * @throws ConfigurationException if the dependency used inconsistent attributes
+     */
+    private static void checkTheServiceUnavailableAction(Dependency dependency,
+                                                         Element metadata) throws ConfigurationException {
+        if (metadata.containsAttribute("nullable") || dependency.getDefaultImplementation() != null  || dependency
+                .getException() != null) {
+            // Rule 1:
+            String message = "The `nullable`, `default-implementation` and `exception` attributes are not " +
+                    "usable in " + DependencyHandler.getDependencyIdentifier(dependency) + " - reason: ";
+            if (dependency.isAggregate()) {
+                throw  new ConfigurationException(message + "the dependency is aggregate");
+            }
+            if (! dependency.isOptional()) {
+                throw  new ConfigurationException(message + "the dependency is mandatory");
+            }
+
+            // At this point, we know that the dependency is scalar and optional, and at least one attribute is set
+
+            // Rule 2:
+            message = "Inconsistent use of the `nullable`, `default-implementation` and `exception` attributes are " +
+                    "not usable in " + DependencyHandler.getDependencyIdentifier(dependency) + " - reason: ";
+            if (metadata.containsAttribute("nullable")  && dependency.getDefaultImplementation() != null) {
+                throw new ConfigurationException(message + "`nullable` and `default-implementation` cannot be " +
+                        "combined");
+            }
+            if (metadata.containsAttribute("nullable") && dependency.getException() != null) {
+                throw new ConfigurationException(message + "`nullable` and `exception` cannot be combined");
+            }
+            if (dependency.getDefaultImplementation() != null  && dependency.getException() != null) {
+                throw new ConfigurationException(message + "`exception` and `default-implementation` cannot be " +
+                        "combined");
+            }
+        }
+
+        // Rule 3:
+        if (dependency.getTimeout() != 0  && ! dependency.isOptional()) {
+            throw new ConfigurationException("The `timeout` attribute is not usable in " + DependencyHandler
+                    .getDependencyIdentifier(dependency) + " - reason: the dependency is not optional");
+        }
+
+
+
+
+    }
+
+    /**
+     * Tries to determine the service specification to inject in the dependency.
+     * If the specification is already checked by the dependency, just checks the consistency.
+     *
+     * @param dependency   the dependency
+     * @param manipulation the manipulation metadata
+     * @throws ConfigurationException if the specification cannot be deduced, or when the set specification is not
+     *                                consistent.
+     */
+    private static void deduceTheServiceSpecification(Dependency dependency, PojoMetadata manipulation) throws
+            ConfigurationException {
+
+        // Deduction algorithm
+        String fieldType = null;
+        String callbackType = null;
+        String constructorType = null;
+        // First check the field
+        if (dependency.getField() != null) {
+           fieldType = extractSpecificationFromField(dependency.getField(), manipulation);
+        }
+        if (dependency.getCallbacks() != null  && dependency.getCallbacks().length != 0) {
+            callbackType = extractSpecificationFromMethods(dependency, dependency.getCallbacks(), manipulation);
+        }
+        if (dependency.getConstructorParameterIndex() != -1) {
+            constructorType = extractSpecificationFromConstructor(dependency.getConstructorParameterIndex(),
+                    manipulation);
+        }
+
+        if (dependency.getSpecification() == null
+                && fieldType == null  && callbackType == null  && constructorType == null) {
+            throw new ConfigurationException("The deduction of the service specification for " + DependencyHandler
+                    .getDependencyIdentifier(dependency) + " has failed - reason: when neither the field, " +
+                    "methods and constructor parameter have provided the service specification, " +
+                    "the `specification` attribute must be set");
+
+        }
+
+        // The Dependency.setSpecification method check whether the specification coming from the different sources
+        // are consistent.
+        if (fieldType != null) {
+            setSpecification(dependency, fieldType);
+        }
+        if (callbackType != null) {
+            setSpecification(dependency, callbackType);
+        }
+        if (constructorType != null) {
+            setSpecification(dependency, constructorType);
+        }
+    }
+
+    private static String extractSpecificationFromMethods(Dependency dependency, DependencyCallback[] callbacks,
+                                                          PojoMetadata manipulation) throws ConfigurationException {
+        String type = null;
+        for (DependencyCallback callback : callbacks) {
+            MethodMetadata metadata = manipulation.getMethod(callback.getMethodName());
+            if (metadata != null) {
+                String[] parameters = metadata.getMethodArguments();
+                if (parameters.length == 1  || parameters.length == 2) {
+                    if (! ServiceReference.class.getName().equals(parameters[0])
+                        && ! Dictionary.class.getName().equals(parameters[0])
+                        && ! Map.class.getName().equals(parameters[0])) {
+                        if (type == null) {
+                            type = parameters[0];
+                        } else {
+                            if (! type.equals(parameters[0])) {
+                                throw new ConfigurationException("The callbacks of " + DependencyHandler
+                                        .getDependencyIdentifier(dependency) + " have inconsistent parameters");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return type;
+    }
+
+    private static String extractSpecificationFromConstructor(int index, PojoMetadata manipulation) {
+        // We can write the following instructions as everything was previously checked.
+        String type = manipulation.getConstructors()[0].getMethodArguments()[index];
+        if (type.endsWith("[]")) {
+            return type.substring(0, type.length() - 2);
+        }
+        if (AggregateDependencyInjectionType.AGGREGATE_TYPES.contains(type)) {
+            return null; // It's an aggregate
+        }
+        return type;
+    }
+
+    /**
+     * Extracts the service specification from the field.
+     * When this method is called, we know that the field is containing in the component class.
+     * @param field the field
+     * @param manipulation the manipulation metadata
+     * @return the service specification, or {@code null} if is cannot be extracted.
+     */
+    private static String extractSpecificationFromField(String field, PojoMetadata manipulation) {
+        FieldMetadata metadata = manipulation.getField(field);
+        if (metadata.getFieldType().endsWith("[]")) {
+            return metadata.getFieldType().substring(0, metadata.getFieldType().length() - 2);
+        }
+        if (AggregateDependencyInjectionType.AGGREGATE_TYPES.contains(metadata.getFieldType())) {
+            return null; // It's an aggregate
+        }
+        return metadata.getFieldType();
+    }
+
+    /**
+     * Sets the dependency specification. If the dependency has already a specification set,
+     * throw an error if the current specification and the given one are not equal.
+     * @param dep the dependency
+     * @param className the service specification
+     * @throws ConfigurationException if the given specification is not loadable or if the dependency has already a
+     * specification set that is not the given one.
+     */
+    private static void setSpecification(Dependency dep, String className) throws ConfigurationException {
+        if (dep.getSpecification() != null  && ! dep.getSpecification().getName().equals(className)) {
+            throw new ConfigurationException("Inconsistent service specification for " + DependencyHandler
+                    .getDependencyIdentifier(dep) + " - reason: mismatch between the current specification (" + dep
+                    .getSpecification().getName() + ") and the discovered specification (" + className + ")");
+        } else if (dep.getSpecification() == null) {
+            // Set the specification
+            try {
+                dep.setSpecification(dep.getBundleContext().getBundle().loadClass(className));
+            } catch (ClassNotFoundException e) {
+                throw new ConfigurationException("Cannot set the service specification of " + DependencyHandler
+                        .getDependencyIdentifier(dep) + " - reason: the class " + className + " cannot be loaded from" +
+                        " the bundle " + dep.getBundleContext().getBundle().getBundleId(), e);
+            }
+        }
+    }
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java
index adbb126..9e95357 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
index 9af82c4..8c07b76 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.felix.ipojo.handlers.dependency;
 
 import java.util.*;
@@ -70,24 +71,6 @@
     public static final String PROXY_DISABLED = "disabled";
 
     /**
-     * Dependency field type : Vector
-     * The dependency will be injected as a vector.
-     */
-    protected static final int VECTOR = 2;
-
-    /**
-     * Dependency Field Type : List.
-     * The dependency will be injected as a list.
-     */
-    protected static final int LIST = 1;
-
-    /**
-     * Dependency Field Type : Set.
-     * The dependency will be injected as a set.
-     */
-    protected static final int SET = 3;
-
-    /**
      * List of dependencies of the component.
      */
     private final List<Dependency> m_dependencies = new ArrayList<Dependency>();
@@ -173,167 +156,6 @@
     }
 
     /**
-     * Check if the dependency given is valid in the sense that metadata are consistent.
-     * @param dep : the dependency to check
-     * @param manipulation : the component-type manipulation metadata
-     * @return true if the dependency is valid
-     * @throws ConfigurationException : the checked dependency is not correct
-     */
-    private boolean checkDependency(Dependency dep, PojoMetadata manipulation) throws ConfigurationException {
-        // Check the internal type of dependency
-        String field = dep.getField();
-        DependencyCallback[] callbacks = dep.getCallbacks();
-        int index = dep.getConstructorParameterIndex();
-
-        if (callbacks == null && field == null  && index == -1) {
-            throw new ConfigurationException("A service dependency requires at least binding methods, " +
-            		"a field or a constructor parameter " + getDependencyIdentifier(dep));
-        }
-
-        for (int i = 0; callbacks != null && i < callbacks.length; i++) {
-            MethodMetadata[] mets = manipulation.getMethods(callbacks[i].getMethodName());
-            if (mets.length == 0) {
-                debug("A dependency callback " + callbacks[i].getMethodName() + " does not exist in the " +
-                        "implementation class, will try the super classes " + getDependencyIdentifier(dep));
-            } else {
-                if (mets[0].getMethodArguments().length > 2) {
-                    throw new ConfigurationException("Requirement Callback : A requirement callback "
-                            + callbacks[i].getMethodName()
-                            + " must have 0, 1 or 2 arguments " + getDependencyIdentifier(dep));
-                }
-
-                callbacks[i].setArgument(mets[0].getMethodArguments());
-
-                if (mets[0].getMethodArguments().length == 1) {
-                    if (!mets[0].getMethodArguments()[0].equals(ServiceReference.class.getName())) {
-                        // The callback receives the service object.
-                        setSpecification(dep, mets[0].getMethodArguments()[0], false); // Just warn if a mismatch is discovered.
-                    }
-                } else if (mets[0].getMethodArguments().length == 2) {
-                    // The callback receives service object, service reference. Check that the second argument is a service reference
-                    if (!(mets[0].getMethodArguments()[1].equals(ServiceReference.class.getName()) // callback with (service object, service reference)
-                           || mets[0].getMethodArguments()[1].equals(Dictionary.class.getName()) // callback with (service object, service properties in a dictionary)
-                           || mets[0].getMethodArguments()[1].equals(Map.class.getName()))) { // callback with (service object, service properties in a map)
-                        String message =
-                                "The requirement callback " + callbacks[i].getMethodName() + " must have a " +
-                                        "ServiceReference, a Dictionary or a Map as the second argument " +
-                                        getDependencyIdentifier(dep);
-                        throw new ConfigurationException(message);
-                    }
-                    setSpecification(dep, mets[0].getMethodArguments()[0], false); // Just warn if a mismatch is discovered.
-                }
-            }
-
-        }
-
-        if (field != null) {
-            FieldMetadata meta = manipulation.getField(field);
-            if (meta == null) {
-                throw new ConfigurationException("Requirement Callback : A requirement field "
-                        + field
-                        + " does not exist in the implementation class " + getDependencyIdentifier(dep));
-            }
-            String type = meta.getFieldType();
-            if (type.endsWith("[]")) {
-                if (dep.isProxy()) {
-                    info("Arrays cannot be used for dependencies using proxies - Disabling the proxy mode " +
-                            getDependencyIdentifier(dep));
-                    dep.setProxy(false);
-                }
-                // Set the dependency to multiple
-                dep.setAggregate(true);
-                type = type.substring(0, type.length() - 2);
-            } else if (type.equals(List.class.getName()) || type.equals(Collection.class.getName())) {
-                dep.setType(LIST);
-                type = null;
-            } else if (type.equals(Vector.class.getName())) {
-                dep.setType(VECTOR);
-                if (dep.isProxy()) {
-                    warn("Vectors cannot be used for dependencies using proxies - Disabling the proxy mode " +
-                            getDependencyIdentifier(dep));
-                    dep.setProxy(false);
-                }
-                type = null;
-            } else if (type.equals(Set.class.getName())) {
-                dep.setType(SET);
-                type = null;
-            } else {
-                if (dep.isAggregate()) {
-                    throw new ConfigurationException("A required service is not correct : the field "
-                            + meta.getFieldName()
-                            + " must be an array or a collection to support aggregate injections " +
-                            getDependencyIdentifier(dep));
-                }
-            }
-            setSpecification(dep, type, true); // Throws an exception if the field type mismatch.
-        }
-
-        // Constructor parameter
-        if (index != -1) {
-        	if (! dep.isProxy()) {
-        		throw new ConfigurationException("Services injected into constructor must use proxies " +
-                        getDependencyIdentifier(dep));
-        	}
-
-    		MethodMetadata[] cts = manipulation.getConstructors();
-    		// If we don't have a type, try to get the first constructor and get the type of the parameter
-    		// we the index 'index'.
-    		if (cts.length > 0  && cts[0].getMethodArguments().length > index) {
-        		String type = cts[0].getMethodArguments()[index];
-        		if (type.endsWith("[]")) {
-                    throw new ConfigurationException("Services injected into constructor cannot be arrays " +
-                            getDependencyIdentifier(dep));
-                } else if (type.equals(List.class.getName()) || type.equals(Collection.class.getName())) {
-                    dep.setType(LIST);
-                    type = null;
-                } else if (type.equals(Vector.class.getName())) {
-                	throw new ConfigurationException("Services injected into constructor cannot be Vectors " +
-                            getDependencyIdentifier(dep));
-                } else if (type.equals(Set.class.getName())) {
-                    dep.setType(SET);
-                    type = null;
-                } else {
-                    if (dep.isAggregate()) {
-                        throw new ConfigurationException("A required service is not correct : the constructor parameter "
-                                + index
-                                + " must be an aggregate type to support aggregate injections " +
-                                getDependencyIdentifier(dep));
-                    }
-                }
-                setSpecification(dep, type, true); // Throws an exception if the field type mismatch.
-        	} else {
-        		throw new ConfigurationException("Cannot determine the specification of the dependency " + index +
-        				", please use the specification attribute " + getDependencyIdentifier(dep));
-        	}
-        }
-
-        // At this point we must have discovered the specification, it it's null, throw a ConfiguraitonException
-        if (dep.getSpecification() == null) {
-            String identifier = getDependencyIdentifier(dep);
-            throw new ConfigurationException("Cannot determine the targeted service specification for the dependency " +
-                    identifier);
-        }
-
-        // Disable proxy on scalar dependency targeting non-interface specification
-        if (! dep.isAggregate()  && dep.isProxy()) {
-        	if (! dep.getSpecification().isInterface()) {
-        		warn("Proxies cannot be used on service dependency targeting non interface " +
-        				"service specification " + getDependencyIdentifier(dep));
-        		dep.setProxy(false);
-        	}
-        }
-
-        // Disables proxy on null (nullable=false)
-//        if (dep.isProxy()  && dep.isOptional() && ! dep.supportsNullable()) {
-//            dep.setProxy(false);
-//            warn("Optional Null Dependencies do not support proxying - Disable the proxy mode");
-//        }
-
-        // Check that all required info are set
-        return dep.getSpecification() != null;
-    }
-
-    /**
      * Builds a description of this dependency to help the user to identify it. IT's not related to the Dependency
      * Description, it's just a string containing dependency information to spot it easily in the code.
      * @param dep the dependency
@@ -368,65 +190,6 @@
     }
 
     /**
-     * Check if we have to set the dependency specification with the given class name.
-     * @param dep : dependency to check
-     * @param className : class name
-     * @param error : set to true to throw an error if the set dependency specification and the given specification are different.
-     * @throws ConfigurationException : the specification class cannot be loaded correctly
-     */
-    private void setSpecification(Dependency dep, String className, boolean error) throws ConfigurationException {
-        if (className == null) {
-            // No found type (list and vector)
-            if (dep.getSpecification() == null) {
-                if (error) {
-                	String id = dep.getId();
-                	if (id == null) {
-                		id = dep.getField();
-                		if (id == null) {
-                			id = Integer.toString(dep.getConstructorParameterIndex());
-                		}
-                	}
-                    throw new ConfigurationException("Cannot discover the required specification for " +
-                            getDependencyIdentifier(dep));
-                } else {
-                    // If the specification is different, warn that we will override it.
-                    info("Cannot discover the required specification for " + dep.getField());
-                }
-            }
-        } else { // In all other case, className is not null.
-            if (dep.getSpecification() == null || !dep.getSpecification().getName().equals(className)) {
-                if (dep.getSpecification() != null) {
-                    if (error) {
-                        throw new ConfigurationException("A required service is not correct : the discovered type ["
-                            + className
-                            + "] and the specified (or already discovered)  service interface ["
-                            + dep.getSpecification().getName()
-                            + "] are not the same " + getDependencyIdentifier(dep));
-                    } else {
-                        // If the specification is different, warn that we will override it.
-                        warn("["
-                            + getInstanceManager().getInstanceName()
-                            + "] The field type ["
-                            + className
-                            + "] and the required service interface ["
-                            + dep.getSpecification()
-                            + "] are not the same " + getDependencyIdentifier(dep));
-                    }
-                }
-
-                Bundle bundle = getInstanceManager().getContext().getBundle();
-                try {
-                    dep.setSpecification(bundle.loadClass(className));
-                } catch (ClassNotFoundException e) {
-                    throw new ConfigurationException("The required service interface (" + className
-                            + ") cannot be loaded from bundle " + bundle.getBundleId() + " " +
-                            getDependencyIdentifier(dep), e);
-                }
-            }
-        }
-    }
-
-    /**
      * Configure the handler.
      * @param componentMetadata : the component type metadata
      * @param configuration : the instance configuration
@@ -497,14 +260,14 @@
             	dep.addConstructorInjection(index);
             }
 
-            // Check the dependency :
-            if (checkDependency(dep, manipulation)) {
-                m_dependencies.add(dep);
-                if (dep.getField() != null) {
-                    getInstanceManager().register(manipulation.getField(dep.getField()), dep);
-                    atLeastOneField = true;
-                }
+            // Check the dependency, throws an exception on error.
+            DependencyConfigurationChecker.ensure(dep, dependencyElement, manipulation);
+            m_dependencies.add(dep);
+            if (dep.getField() != null) {
+                getInstanceManager().register(manipulation.getField(dep.getField()), dep);
+                atLeastOneField = true;
             }
+
         }
 
         if (atLeastOneField) { // Does register only if we have fields
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
index a29b18b..74c6e09 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/NullableObject.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/NullableObject.java
index b11419f..4d9ddd7 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/NullableObject.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/NullableObject.java
@@ -1,4 +1,4 @@
-/* 

+/*

  * 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

diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ProxyGenerator.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ProxyGenerator.java
index 1dd2cf3..345afee 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ProxyGenerator.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ProxyGenerator.java
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.felix.ipojo.handlers.dependency;
 
 
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceCollection.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceCollection.java
index 369ad94..0273895 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceCollection.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceCollection.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java
index 3757e77..365fa01 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java
@@ -1,4 +1,4 @@
-/* 

+/*

  * 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

@@ -24,7 +24,7 @@
  * 

  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

  */

-public class ServiceUsage extends ThreadLocal {

+public class ServiceUsage extends ThreadLocal<ServiceUsage.Usage> {

     

     /**

      * Structure contained in the Thread Local.

@@ -93,7 +93,7 @@
      * @return an empty Usage object.

      * @see java.lang.ThreadLocal#initialValue()

      */

-    public Object initialValue() {

+    public Usage initialValue() {

         return new Usage();

     }   

 

diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java
index 1040787..c27e439 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java
@@ -21,6 +21,7 @@
 import org.apache.felix.ipojo.ComponentInstance;

 import org.apache.felix.ipojo.IPOJOServiceFactory;

 import org.apache.felix.ipojo.dependency.impl.ServiceReferenceManager;

+import org.apache.felix.ipojo.handlers.dependency.DependencyCallback;

 import org.osgi.framework.BundleContext;

 import org.osgi.framework.Filter;

 import org.osgi.framework.InvalidSyntaxException;