I came across an instance where Dagger-2 wouldn't let me lazy inject. It seems that it still requires me to supply the object at compile time. Why is that?
The stacktrace:
[Dagger/MissingBinding] @javax.inject.Named("htfModel") de.wimj.core.Applications.IModel cannot be provided without an @Provides-annotated method.
[ERROR] @javax.inject.Named("htfModel") de.wimj.core.Applications.IModel is injected at
[ERROR] de.wimj.ui.Mt5Painter.<init>(…, htfTradeModel, …)
[ERROR] dagger.Lazy<de.wimj.ui.Mt5Painter> is injected at
[ERROR] de.wimj.core.Applications.ModelMqlBased.<init>(…, mt5Painter, …)
[ERROR] dagger.Lazy<de.wimj.core.Applications.ModelMqlBased> is injected at
[ERROR] de.wimj.di.components.trademodel.ModelModule.iModel(modelMqlBased, …)
[ERROR] de.wimj.core.Applications.IModel is provided at
[ERROR] de.wimj.di.components.trademodel.ModelComponent.createModel()
The code for the stacktrace:
//Got it, Dagger-2 wants me to provide a IModel here
@ModelScope
@Component(modules = { ModelModule.class }, dependencies = { ClientComponent.class })
public interface ModelComponent {
IModel createModel();
@Component.Builder
interface Builder {
ModelComponent build();
Builder clientComponent(ClientComponent clientComponent); //MT5Trader comes from this component
}
}
//At this point I will provide the IModel. I do NOT get, why Dagger-2 forces
//me to provide a "ModelMqlBased" though. I obviously lazy-inject it.
//I used this pattern in other cases as well (providing an interface and
//lazy-injecting the possible instantiations as params)
@Module
public class ModelModule {
@Provides
@ModelScope
IModel iModel( Lazy<ModelMqlBased> modelMqlBased, //lazy-injection here!
ModelFileBased modelFileBased,
@Named("configClientType")String clientType) {
switch (clientType) {
case "mqlBot":
return modelMqlBased.get();
case "fileBot":
return modelFileBased;
default:
throw new RuntimeException();
}
}
}
The following code should be irrelevant (the crux is the ModelModule), but for the sake of completion:
@ModelScope
public class ModelMqlBased implements IModel {
@Inject
public ModelMqlBased( Lazy<Mt5Painter> mt5Painter) {
super();
this.mt5Painter = mt5Painter.get();
}
}
//this one sits in a "higher-scoped" component
@ClientScope
public class Mt5Painter {
private IModel htfModel;
private IModel ltfModel;
@Inject
public Mt5Painter(@Named("htfModel") Lazy<IModel> htfTradeModel, @Named("ltfModel") Lazy<IModel> ltfTradeModel) {
super();
this.htfModel = htfTradeModel.get();
this.ltfModel = ltfTradeModel.get();
}