1

I'm trying to inject some classes while passing some parameters in the constructor. To achive that, I've found this questions (1, 2) saying that this could be achived by using Assisted Injection with a Factory. This is how my code looks like, following the examples provided and some modifications after reading the related documentation.

gradle script

dependencies { 
    compile 'org.roboguice:roboguice:3.+'
    provided 'org.roboguice:roboblender:3.+'
    compile 'com.google.inject.extensions:guice-assistedinject:3.+' 
}

Factory interface with create method that accepts parameters

public interface ICustomObjectFactory {
    ICustomObject create(Callback callback);
}

Class that implements the interface

public class CustomObject implements ICustomObject {
    protected String name;

    @AssistedInject
    public CustomObject(@Assisted Callback callback){
       this.callback = callback;
    }
}

Module used and called from the Aplication class

public class SomeModule extends Module {

    @Override
    protected void configure() {
         install(new FactoryModuleBuilder()
            .implement(ICustomObject.class, CustomObject.class)
            .build(ICustomObjectFactory.class));
    }
}

Injection Module registered from the Application class

@Override
public void onCreate() {
    super.onCreate();

    RoboGuice.getOrCreateBaseApplicationInjector(this, RoboGuice.DEFAULT_STAGE,
            RoboGuice.newDefaultRoboModule(this), new SomeModule(this));
}

Use of the Factory

public class SomeClass implements Callback {

    @Inject ICustomObjectFactory factory;

    public SomeClass () {
        ICustomObject first = this.factory.create(this);
    }
}

With all like this, I'm getting this error when I try to use the factory, as it's been used in SomeClass

java.lang.IllegalStateException: Factories.create() factories cannot be used until they're initialized by Guice.
        at com.google.inject.internal.util.$Preconditions.checkState(Preconditions.java:142)
        at com.google.inject.assistedinject.FactoryProvider2.getBindingFromNewInjector(FactoryProvider2.java:564)
        at com.google.inject.assistedinject.FactoryProvider2.invoke(FactoryProvider2.java:625)
        at java.lang.reflect.Proxy.invoke(Proxy.java:397)
        at $Proxy12.create(Unknown Source)

Someone knows why the Factory it's no initialized? I understand that should be initialized by the module, and I'm sure that the module it's been called.

The most remarcable difference between my code and the code from the questions linked is that in the questions, the constructor is annotated with @Inject, not @AssistedInject. Before this modification, I was getting this error compiling the app.

Error:Execution failed for task ':app:compileDebugJavaWithJavac'. java.lang.ClassCastException: com.sun.tools.javac.code.Type cannot be cast to javax.lang.model.type.DeclaredType dle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.) Re-download dependencies and sync project (requires network)

  • The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem. Stop Gradle build processes (requires restart)
  • Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.
  • In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.

    Maybe this isn't the best approach to achieve what I need. If it isn't, could someone point me the right direction?

    Thank you all for your help

    Community
    • 1
    • 1
    Jofre Mateu
    • 2,390
    • 15
    • 26

    2 Answers2

    0

    At the end, I make it work by adding RoboGuice.setUseAnnotationDatabases(false) in the Application class:

    @Override
    public void onCreate() {
        super.onCreate();
    
        RoboGuice.setUseAnnotationDatabases(false);
        RoboGuice.getOrCreateBaseApplicationInjector(this, RoboGuice.DEFAULT_STAGE,
                RoboGuice.newDefaultRoboModule(this), new SomeModule(this));
    }
    
    Jofre Mateu
    • 2,390
    • 15
    • 26
    0

    AssistedInject is not supported for Roboguice 3+

    I'm glad you could get it working with disabling the AnnotationsDatabase. Your previous error:

    com.sun.tools.javac.code.Type cannot be cast to javax.lang.model.type.DeclaredType
    

    was occurring from using @Inject on a constructor with primitive types in the signature. See this answer

    A simple solution that should allow you to use the AnnotationsDatabase is to use Provider<T> that, unlike AssistedInject, is supported in Roboguice 3+. So, in the module:

    binder.bind(CustomObject.class).toProvider(CustomObjectProvider.class);
    

    then inject into the Provider thus:

    public class CustomObjectProvider implements Provider<CustomObject> {
    
        Callback callback;
    
        @Inject
        public CustomObjectProvider(Callback callback) {
            this.callback = callback;
        }
    
        @Override
        public CustomObject get() {
            return new CustomObject(callback);
        }
    }
    
    David Rawson
    • 20,912
    • 7
    • 88
    • 124