Dagger2 - Component hold as a static object in Application - java

In my Application class, I have my singleton Dagger Component as a static object and reach it via its static getter method.
public class MyApp extends Application {
private static UtilsComponent utilsComponent;
#Override
public void onCreate() {
......
}
public static UtilsComponent getUtilsComponent(){
if(utilsComponent == null){
utilsComponent = DaggerUtilsComponent.builder()
.formattersModule(new FormattersModule())
.build();
}
return utilsComponent;
}
}
What I want to know is that is this the right way to do this? Can it cause problems? If so, what are those?

It's okayish. But why would you put it in the Application class? Put it in standard singleton class called for example Injector. Still you might want to initialize that singleton in Application which is fine.

It is ok, but you will not be able to use inject Context- dependent objects in that way. For component, requiring Context, use non - static accessor in Application class.
Speaking more widely, there will be as many components as your want, but if if component provides #Singleton - annotated functionality, lifecycle of component should not be longer that one of feature using it.

Related

Dagger 2 singleton in multiple instances

I just tested out Dagger 2 and I am having some strange behaviour regarding the singleton annotation. I created some test code to show my problem.
My Module:
#Module
public class App {
#Provides
#Singleton
ThingA provideThingA(){
return new ConcreteThingA();
}
}
Interface of the thing I want in singleton:
public interface ThingA {
void showMyId();
}
Implementation:
public class ConcreteThingA implements ThingA {
#Override
public void showMyId() {
System.out.println(this);
}
}
Code that executes Dagger:
public void doStuff() {
ThingA thingA=DaggerThingAComponent.create().provideThingA();
ThingA thingB=DaggerThingAComponent.create().provideThingA();
System.out.println("Hello");
}
And here is a screenshot showing that I do not get the same instance when I ask for it twice. Have I missed something fundamental? ThingA is just a silly name and in my actual application I would like to have this singleton behaviour on my services.
The trick is that Dagger enforces scope/lifecycle through components, and you've created two separate components here:
ThingA thingA = DaggerThingAComponent.create().provideThingA();
ThingA thingB = DaggerThingAComponent.create().provideThingA();
Each time you create the new top-level #Singleton-annotated Component, Dagger creates a brand new object graph with a brand new container for each #Singleton object. You should have this instead:
ThingAComponent component = DaggerThingAComponent.create();
ThingA thingA = component.provideThingA();
ThingA thingB = component.provideThingA(); // thingA == thingB
Of course, anything further accessed through the dependency graph all comes from the same component, so this will preserve the singleton behavior you're looking for.
In most cases, you should not need to pass around the Component: The Component should be used for top-level components, and anything accessible through the injector should #Inject its dependencies (which means it shouldn't need a reference to the component itself). This might appear problematic during the migration to DI or Dagger, but creating multiple #Singleton components is not the way around it. Instead, try one of the following:
If you need multiple instances of something, you can always inject Provider<T> instead of T whether or not you've created a #Provides method. For that matter, you can inject a Lazy<T> if you only need zero or one copies of a particular dependency, particularly if the creation of that object is particularly heavy.
You can #Inject the component itself if you need it deep within the object graph, though it's always preferable to #Inject Provider<T> tProvider instead of #Inject YourComponent just to call YourComponent.getT.
In some cases, including Android, it may make sense to save the component to a globally-accessible field, either as an instance field in your Application or as a static field somewhere else. This is specifically because Android creates objects on its own, reflectively, rather than getting injected instances from the graph. For all other cases, inject your dependencies to avoid needing to pass around the component.
See also: Bindings in the graph from the Dagger 2 Users Guide

dagger 2 circular dependency

In a project I am working on I have 2 classes that are highly dependent on one another:
#Singleton
class WorkExecutor {
#Inject Provider<ExecutionServices> services;
...
public void execute(Work w){
w.execute(services.get());
...
}
...
}
class ExecutionServicesImpl implements ExecutionServices {
#Inject WorkExecutor executor;
...
}
The idea is that when executing a work, the work has access to several services - one of them is the executor itself so that a work will be able to execute sub works.
As one can see, there is a circular dependency here, but one that I found very hard to break.
The main problem is that the WorkExecutor does not actually need an instance of ExecutionServices object at graph-constructing time but only a provider to be used later. sadly, Dagger does not know that the WorkExecutor will not call the ExecutionServices provider from the constructor of the class so it guesses that ExecutionServices depends on WorkExecutor and vice versa.
One possible solution that I found is to define a module and component in the following way:
interface DelayedProvider<T> extends Provider<T>{}
#Module
class AppModule {
Provider<ExecutionServices> delayedProvider = null;
#Provides DelayedProvider<ExecutionServices> provideDelayed() {
return () -> delayedProvider.get();
}
#Provides #Named("late-binding-conf") Void latebindingConf(Provider<ExecutionServices> eager){
this.delayedProvider = eager;
return null; //notice we returning Void and not void
}
}
#Component(modules=AppModule.class)
interface AppComponent {
App app();
#Named("late-binding-conf") Void configureLateBinding();
}
and then I modifies the original classes to be:
#Singleton
class WorkExecutor {
#Inject DelayedProvider<ExecutionServices> services;
...
public void execute(Work w){
w.execute(services.get());
...
}
...
}
class ExecutionServicesImpl implements ExecutionServices {
#Inject WorkExecutor executor;
...
}
And then in order to create my app I have to do:
AppComponent acomp = DaggerAppComponent.create();
App = acomp.app();
acomp.configureLateBinding();
But I am not sure this is the proper course of action - Is there a better way?
I don't suspect OP will like this, as you want a way to make something 'wrong', work 'right'. That can't really be. Whenever you encounter a circular dependency, the "right" solution is to refactor to remove that dependency.
In your case, WorkExecutor is a singleton so it probably needs to remain as is. ExecutionServicesImpl should then be modified to remove the dependency on WorkExecutor. Without knowing the specifics of the code, one can't say too much more. However, having an ExecutionService be independent from it's "worker" is reduced coupling and likely a very good thing in the long run.
why does ExecutionServicesImpl depend on WorkExecutor?
Show more core, ExecutionServices sounds like a Singleton too, why does it depend on each other to work correctly?
WorkExecutor sounds like something that you can pass to the ExecutionService as WorkExecutor will be injected somewhere else, maybe the one that uses the Service.
I dont know, show more code and probably that's the answer, it looks complex.
I ran into a situation in a Swing project where a third-party object depended on a JFrame, and the JFrame depended on the third-party object to produce its content pane. I came up with this solution, but ultimately decided to close the loop in my main method after the object graph was constructed. Basically, I created two named JFrame providers, the second depending on the first and returning the same instance:
#Provides
#Singleton
#Named("DO_NOT_INJECT")
JFrame mainWindowIncomplete() {
return new JFrame(); // after setting it up
}
#Provides
#Singleton
CControl dockControl(#Named("DO_NOT_INJECT") JFrame mainWindow) {
return new CControl(mainWindow);
}
#Provides
#Singleton
#Named("MAIN_WINDOW")
JFrame mainWindow(#Named("DO_NOT_INJECT") JFrame mainWindow, CControl dockControl) {
mainWindow.add(dockControl.getContentArea());
return mainWindow;
}
For this to work, the second provider would have to be used at least once. You can ensure this by adding a package-private qualifier to the first one as described in this answer.

Using Guice with a custom class?

I'm working with a Guice enabled framework.
When using classes that were created by the framework (or subclasses that override existing bindings), I can instantiate framework provided variables very easily. Whatever I need, it's just a matter of
#Inject
FrameworkProvidedType variable;
However, in my custom created classes, that doesn't work. All of the injected variables are null.
It's my understanding that in order to use injection, my class has to have a binding.
If I'm subclassing an existing framework class, I can override the binding in my module class. That's pretty straightforward.
But I have a new class and I don't know how to bind it to the underlying framework.
public Class myCustomClass {
private String iNeedthis;
private Context thisToo;
#Inject
FrameWorkThing magic;
public myCustomClass(String iNeedThis, Context thisToo){
this.iNeedThis = iNeedThis;
this.thisToo = thisToo;
}
public void DoMagic(){
//null pointer error because magic was not injected
magic.doMagic(this.iNeedthis);
}
}
How do I Guice-enable this new class?
I tried this in my Runtime Module
public Class<myCustomClass> bindMyCustomClass(){
return MyCustomClass.class;
}
and failed miserably.
No thanks to #bmorris591 who dismissed and downvoted the question out of the gate, I found an answer.
#Inject-ing a field into a class means that the class instance needs to be created by Guice.
Step 1 is creating a factory for the class. This may not be necessary, but it worked for me.
public interface MyCustomClassFactory {
public MyCustomClass create(String iNeedThis, Context thisToo);
}
Step 2 is installing the factory into Guice
#Override
public void configure(Binder binder) {
super.configure(binder);
binder.install(new FactoryModuleBuilder().build(MyCustomClass.class));
}
In my particular case - the framework I'm working with provides a Module class that is an implementation of com.google.inject.Module.
Within that class is a "configure(Binder binder)" function that is called on startup.
Step 3 is actually annotating the constructor
#Inject
public myCustomClass(String iNeedThis, Context thisToo){
this.iNeedThis = iNeedThis;
this.thisToo = thisToo;
}
Useful and related web page that put me on the right track:
http://beust.com/weblog/2012/08/21/advanced-dependency-injection-with-guice/
This talks about assisted injection, but it gave enough information and a simple enough to understand example that taking the next step was pretty easy.

How to deal with special "constant" instances of object when using DI

My project is heavily using dependency injection, and I'm being very careful to avoid service locator antipattern. All objects are structured using constructor injection that allow easily identifiable list of dependencies. Now I'm building an object, and it has a special "constant" instance, which is basically static/singleton (consider example of something like Integer.MinValue). So my initial reflex was to create a static field with a static "getter" method, which would create the instance of the object if it wasn't previously created. The object itself has dependencies however, so I'm confused on what's the best practice for instantiating this "special instance". I'm looking for recommendations on how to best structure code in this scenario, ideally without having to call upon the container for resolution of dependencies. Some code:
public class PressureUnit extends DataUnit {
private static PressureUnit standardAtmosphere;
public static PressureUnit StandardAtmosphere() {
if(standardAtmosphere == null){
standardAtmosphere = new PressureUnit(1013.25); // this line is what is bothering me as I need to resolve other dependencies (have to use new as it's a static method and can't be injected like everywhere else)
}
return standardAtmosphere;
}
#AssistedInject
public PressureUnit(ITimeProvider timeProvider, IUnitProvider unitProvider, #Assisted double value) {
this(timeProvider, unitProvider, value, PressureUnits.hPa);
}
...
}
I really don't see any problem in your code since you are not newing up dependencies here and there, now with that being said i can give some suggestions:
If you specifically want the container to call an existing static factory method, you can use StaticFactoryExtension.
Why don't you use a factory.
Consider refactoring you design and removing the static method if possible.

Guice scenario where multiple injector references appear unavoidable

I have a use case where it appears that referencing a Guice injector from multiple locations is the only solution—though this is generally discouraged.
My application is built on top of Talend, an open source ETL platform. Most of my actual application is in Java classes that are called by Talend components. These components include Java snippets that I write and that, in turn, instantiate/invoke my classes.
Now I intend to use Guice throughout my Java classes but there is absolutely no way for me to inject dependencies into the Talend components (so that they would be available to the Java snippets). Instead, I need to actually create these dependencies. I’d like to at least have Guice control the instantiation, which means that instead of using new, it appears that the only way I can instantiate my classes (the ones with #Inject constructors) is to call injector.getInstance. This, in turn, implies that I need to keep the injector around, presumably using an old-fashioned factory that creates it in the first place and makes it available as a singleton.
I just can’t see any other way to handle this but perhaps I’m missing something.
Consider static injection. This will still hide persistent references to your injector across your app, but it will save you from having to pepper your code with injector.getInstance(...) calls. In any case you can inject Injector if you really need to.
class TalendDependencyModule extends AbstractModule {
#Override public void configure() {
requestStaticInjection(ExtractorDependencies.class);
requestStaticInjection(ProcessorDependencies.class);
}
}
public class ExtractorDependencies {
#Inject private static Provider<ParserService> parserServiceProvider;
#Inject private static Provider<SomethingElse> somethingElseProvider;
private ExtractorDependencies() { }
static ParserService getParserService() {
return parserServiceProvider.get();
}
/* ... */
}
I don't know how many Talend objects you have but you might want to consider using providers. For instance suppose you have your own class that you want Guice to manage creation of:
public interface INotTalendControlled {}
public class NotTalendControlled implements INotTalendControlled {}
This will be added to a Talend object whose dependencies cannot be injected via Guice (although I assume there is some manual process for doing so either constructor or setter):
public class TalendControlled {
private INotTalendControlled notTalendControlled;
private TalendControlled(INotTalendControlled notTalendControlled) {
this.notTalendControlled = notTalendControlled;
}
public INotTalendControlled getValue() {
return notTalendControlled;
}
}
If you want Guice to manage these lifecycles and the lifecycle of Talend controlled objects you can use a provider like so:
public static class TestModule extends AbstractModule {
#Override
protected void configure() {
bind(INotTalendControlled.class).to(NotTalendControlled.class);
}
#Provides
public TalendControlled provideInjectsToTalendObject(INotTalendControlled notTalendControlled) {
return new TalendControlled(notTalendControlled);
}
}
The #Provides method will hide of the use of new for all objects as you can now directly inject TalendControlled objects (#Inject TalenControlled talendControlled) and an explicit injector is not needed to construct their dependencies.

Categories

Resources