dagger-reflect icon indicating copy to clipboard operation
dagger-reflect copied to clipboard

Crash on java.lang.ClassNotFoundException: dagger.android.ContributesAndroidInjector

Open roxrook opened this issue 5 years ago • 3 comments

It crashed when I use this on server side application which has no Android deps. Is there a way to exclude Android specific dependencies?

Edited to add stacktrace:

java.lang.NoClassDefFoundError: dagger/android/ContributesAndroidInjector
	at dagger.reflect.ReflectiveModuleParser.parse(ReflectiveModuleParser.java:78)
	at dagger.reflect.ComponentScopeBuilder.get(ComponentScopeBuilder.java:124)
	at dagger.reflect.ComponentBuilderInvocationHandler.invoke(ComponentBuilderInvocationHandler.java:98)

roxrook avatar Apr 24 '20 05:04 roxrook

Yes. It's actually supposed to be set up to guard against this already...

JakeWharton avatar Apr 24 '20 05:04 JakeWharton

Do you have an extra abstract method / interface method that's not @Binds nor @Multibinds somewhere in a @Module? (based on the if-else-if structure this is the only way to get this exception)

TWiStErRob avatar Apr 24 '20 13:04 TWiStErRob

So I actually went through the source code, and @TWiStErRob is absolutely right about that. I actually have an interface Logging in one of the modules 🤦. Apparently, regular Dagger does not complain about this at all, not sure if this is worth a change, however debugging it at the beginning is quite challenging due to kapt, I have to switch to the full reflect version to see that method.

          if (method.getAnnotation(Binds.class) != null) {
            Key key = Key.of(qualifier, returnType);
            Binding binding = new UnlinkedBindsBinding(method);
            addBinding(scopeBuilder, key, binding, annotations);
          } else if (method.getAnnotation(BindsOptionalOf.class) != null) {
            try {
              Key key =
                  Key.of(
                      qualifier,
                      new ParameterizedTypeImpl(null, Optional.class, boxIfNecessary(returnType)));
              Binding binding = new UnlinkedJavaOptionalBinding(method);
              addBinding(scopeBuilder, key, binding, annotations);
            } catch (NoClassDefFoundError ignored) {
            }
            try {
              Key key =
                  Key.of(
                      qualifier,
                      new ParameterizedTypeImpl(
                          null, com.google.common.base.Optional.class, boxIfNecessary(returnType)));
              Binding binding = new UnlinkedGuavaOptionalBinding(method);
              addBinding(scopeBuilder, key, binding, annotations);
            } catch (NoClassDefFoundError ignored) {
            }
          } else if (method.getAnnotation(Multibinds.class) != null) {
            Key key = Key.of(qualifier, returnType);
            if (method.getReturnType() == Set.class) {
              scopeBuilder.createSetBinding(key);
            } else if (method.getReturnType() == Map.class) {
              scopeBuilder.createMapBinding(key);
            } else {
              throw new IllegalStateException(
                  "@Multibinds return type must be Set or Map: " + returnType);
            }
          } else {
            ContributesAndroidInjector contributesAndroidInjector =
                method.getAnnotation(ContributesAndroidInjector.class);
            if (contributesAndroidInjector != null) {
              // TODO check return type is a supported type? not parameterized? something else?
              Class<?>[] modules = contributesAndroidInjector.modules();
              Class<?> androidType = (Class<?>) returnType;
              Binding.UnlinkedBinding binding =
                  new UnlinkedAndroidInjectorFactoryBinding(
                      modules, androidType, findScopes(annotations));
              addAndroidMapBinding(scopeBuilder, returnType, binding);
            }
          }
        } else {
          if (method.getAnnotation(Provides.class) != null) {
            ensureNotPrivate(method);
            if (!Modifier.isStatic(method.getModifiers()) && instance == null) {
              ensureNotAbstract(moduleClass);
              // Try to just-in-time create an instance of the module using a default constructor.
              instance = maybeInstantiate(moduleClass);
              if (instance == null) {
                throw new IllegalStateException(moduleClass.getCanonicalName() + " must be set");
              }
            }

            Key key = Key.of(qualifier, returnType);
            Binding binding = new UnlinkedProvidesBinding(instance, method);
            addBinding(scopeBuilder, key, binding, annotations);
          }
        }```

roxrook avatar Apr 24 '20 17:04 roxrook