intro. new bindAllSingletons()
authorMichael Vorburger <mike@vorburger.ch>
Wed, 31 Oct 2018 17:25:51 +0000 (18:25 +0100)
committerMichael Vorburger <mike@vorburger.ch>
Wed, 1 Jul 2020 23:37:40 +0000 (01:37 +0200)
and use it in AlivenessMonitorWiring

This now also wires the HwVtepTunnelsStateHandler, which we forgot! ;)

That (to not forget to manually wire in any @Singleton) is the point.

PS: PacketProcessingListener didn't get wired, just like it should be.
Signed-off-by: Michael Vorburger <mike@vorburger.ch>
src/main/java/org/opendaylight/genius/simple/AlivenessMonitorWiring.java
src/main/java/org/opendaylight/infrautils/inject/ClassPathScanner.java
src/main/java/org/opendaylight/infrautils/inject/guice/GuiceClassPathBinder.java
src/test/java/org/opendaylight/infrautils/inject/tests/ClassPathScannerTest.java

index cb1811a98ec2b923d02e4f4ccda03c3fb3046eba..9ded349fbd16a0c1d11558f9df6780add8f858fd 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.genius.simple;
 
 import com.google.inject.AbstractModule;
 import org.opendaylight.infrautils.inject.guice.GuiceClassPathBinder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
 
 public class AlivenessMonitorWiring extends AbstractModule {
 
@@ -21,7 +20,6 @@ public class AlivenessMonitorWiring extends AbstractModule {
 
     @Override
     protected void configure() {
-        classPathBinder.bind(binder(), AlivenessMonitorService.class);
+        classPathBinder.bindAllSingletons("org.opendaylight.genius.alivenessmonitor", binder());
     }
-
 }
index 28244ec1ea3dfa01d75145021820220708d98321..16ffa3c7b5f3720481d0ceb7397682df9d94d0c8 100644 (file)
@@ -66,7 +66,29 @@ public class ClassPathScanner {
     }
 
     /**
-     * Binds the given interfaces in the given binder, using implementations discovered by scanning the class path.
+     * Binds all {@link Singleton} annotated classes discovered by scanning the class path to all their interfaces.
+     *
+     * @param prefix the package prefix of Singleton implementations to consider
+     * @param binder The binder (modeled as a generic consumer)
+     */
+    public void bindAllSingletons(String prefix, BiConsumer<Class, Class> binder) {
+        implementations.forEach((interfaceName, singletonClass) -> {
+            if (singletonClass.getName().startsWith(prefix)) {
+                try {
+                    Class interfaceClass = Class.forName(interfaceName);
+                    binder.accept(interfaceClass, singletonClass);
+                    // TODO later probably lower this info to debug, but for now it's very useful..
+                    LOG.info("Bound {} to {}", interfaceClass, singletonClass);
+                } catch (ClassNotFoundException e) {
+                    LOG.warn("ClassNotFoundException on Class.forName: {}", interfaceName, e);
+                }
+            }
+        });
+        // we do not want nor have to scan the @Singleton's @Inject annotated constructor; will also auto-discover.
+    }
+
+    /**
+     * Binds the given interfaces, using implementations discovered by scanning the class path.
      *
      * @param binder The binder (modeled as a generic consumer).
      * @param interfaces The requested interfaces.
@@ -83,6 +105,8 @@ public class ClassPathScanner {
         Class implementation = implementations.get(requestedInterface.getName());
         if (implementation != null) {
             binder.accept(requestedInterface, implementation);
+            // TODO later probably lower this info to debug, but for now it's very useful..
+            LOG.info("Bound {} to {}", requestedInterface, implementation);
             for (Constructor constructor : implementation.getDeclaredConstructors()) {
                 Annotation injectAnnotation = constructor.getAnnotation(Inject.class);
                 if (injectAnnotation != null) {
index cc20e636b3ea01a15752534c0ad658ac5a03c392..e4cc74cc00becbb04c832943680079228d509602 100644 (file)
@@ -29,4 +29,8 @@ public class GuiceClassPathBinder {
     public void bind(Binder binder, Class<?> requestedInterface) {
         scanner.bind((contract, implementation) -> binder.bind(contract).to(implementation), requestedInterface);
     }
+
+    public void bindAllSingletons(String prefix, Binder binder) {
+        scanner.bindAllSingletons(prefix, (contract, implementation) -> binder.bind(contract).to(implementation));
+    }
 }
index e95ec2fd6e222690d14e05c8f4ae7e054bba8eea..b3aea67ef7c82844e419ec74feb6a7cd96789341 100644 (file)
@@ -11,21 +11,26 @@ import static com.google.common.truth.Truth.assertThat;
 
 import java.util.HashMap;
 import java.util.Map;
-import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.infrautils.inject.ClassPathScanner;
 
 public class ClassPathScannerTest {
-    private final Map<Class<?>, Class<?>> bindings = new HashMap<>();
 
-    @Before
-    public void setup() {
-        new ClassPathScanner("org.opendaylight.infrautils.inject.tests").bind(bindings::put,
-            ClassPathScannerTestTopInterface.class);
+    private static final String PREFIX = "org.opendaylight.infrautils.inject.tests";
+
+    @Test
+    public void testExplicitBinding() {
+        Map<Class<?>, Class<?>> bindings = new HashMap<>();
+        new ClassPathScanner(PREFIX).bind(bindings::put,
+                ClassPathScannerTestTopInterface.class);
+        assertThat(bindings).containsExactly(
+                ClassPathScannerTestTopInterface.class, ClassPathScannerTestImplementation.class);
     }
 
     @Test
-    public void verifyImplementationBinding() {
+    public void testImplicitBinding() {
+        Map<Class<?>, Class<?>> bindings = new HashMap<>();
+        new ClassPathScanner(PREFIX).bindAllSingletons(PREFIX, bindings::put);
         assertThat(bindings).containsExactly(
                 ClassPathScannerTestTopInterface.class, ClassPathScannerTestImplementation.class);
     }