inject object without access to injector in Guice - java

I am working on an existing Java code base that uses Guice for Dependency Injection. I have a new class Foo that has one member field (bar) I wanted to inject in. Like this:
public class Foo {
#Inject
private Bar bar;
}
However, there are two things:
There is no direct access to the injector where the Foo is used.
The client wants to use "new" to create Foo.
Is it still possible to inject Bar into Foo object when the clients do:
myFoo = new Foo();
I am very new to DI and Guice, don't really understand how you can inject objects without calling injector.createInstance() on its class or its container class. It seems not working in my testing.

No DI tool works if you create your instances via "new" yourself. That's not guice specific. So unless you drop your constraint "2", you will have a hard time.

With Guice you can force the injection of fields if you have a reference to the injector. Like this:
injector.injectMembers(fooObject);
Your first point says you don't have access to the injector where Foo is used. Well, you can try to solve that giving Foo a static reference to the injector.
public class Foo {
#Inject private static Injector injector;
#Inject
private Bar bar;
public Foo() {
injector.injectMembers(this);
}
}
But wait, that won't work out of the box because the injector field would just be null. You need to inject it also but, as it is a static field, you just do it once. It is called static injection. Probably at application start where you have access to the Guice injector, in any of the guice modules.
There, you just execute this:
requestStaticInjection(Foo.class)

Related

Android Architecture Blueprints "todo‑mvp‑dagger", where is #Provides for TasksRepository?

Looking at the Android Architecture Blueprints "todo‑mvp‑dagger" from here: https://github.com/googlesamples/android-architecture.
I'm trying to understand the Dagger2 implementation and I can't seem to figure out how they are getting Dagger2 to provide the TasksRepository.
They have #Provides for "provideTasksLocalDataSource" and "provideTasksRemoteDataSource" but where is the one for the actual TaskRepository?
In the TodoApplication class they have this:
#Inject
TasksRepository tasksRepository;
How can it inject this without an #Provides for it anywhere?
If I try to use this same approach in my own app I get this error:
cannot be provided without an #Provides- or #Produces-annotated method
So I went looking everywhere in the Blueprints code but I can't see how they did it themselves. Is there some trick to it that allows them to not have an #Provides? It definitely builds so they've gotten around it somehow.
Someone has asked this same question on the actual github page but there are no answers at the time of writing. https://github.com/googlesamples/android-architecture/issues/561.
I'm on the latest commit which at the time of writing is "082bd72d62472f9caadd2979046067fb928bbfef".
In the repository you mentioned, Dagger 2 knows how to inject TasksRepository through the constructor being marked with #Inject. From the source:
#Inject
TasksRepository(#Remote TasksDataSource tasksRemoteDataSource,
#Local TasksDataSource tasksLocalDataSource) {
mTasksRemoteDataSource = tasksRemoteDataSource;
mTasksLocalDataSource = tasksLocalDataSource;
}
Since the constructor is annotated with #Inject, Dagger 2 will attempt to use the constructor to inject TasksRepository into consumers like TodoApplication.
Since TasksDataSource are already bound in TasksRepositoryModule there is enough information for Dagger 2 to perform injection without the burden of extra #Provides or #Binds methods.
Similarly, you can do the following:
class Foo {
private final Bar bar;
#Inject
Foo(Bar bar) {
this.bar = bar;
}
}
class Bar {
#Inject
Bar() {}
}
class Activity extends AppCompatActivity {
#Inject Foo foo;
}
And Dagger 2 will be able to inject Foo inside AppCompatActivity. Why?
Dagger 2 knows how to construct a Bar object (through calling the empty constructor)
Dagger 2 knows that when creating instances of Foo it must use the constructor annotated with #Inject with the single parameter Bar.
There are no other dependencies for Foo, in other words the complete object graph is available.

mocking an autowired object in a test

I have a Class that has a field that gets set through a spring bean and is annotated with #Autowired like so:
public class Foo {
....
#Autowired
private Bar bar;
....
}
I now want to setup a JUnit test that tests some functionality that at some point will create a Foo object. I am not in control of when this Foo object is generated. What is the easiest way to mock this object so that anytime Foo gets instantiated, this object get populated with the mocked item? I am using a 3rd party library to mock the Bar object nicely, so I would prefer to do all of this in the Java test class without using xml files.
Everything I have found online seems to either involve creating an xml file or mocking a specific instance of the Class. Thank you all for your help!
I would like something like the following:
public class Test {
private Bar mockedBar = createBar();
// somehow set 'mockedBar' so that any Foo object
// created always contains mockedBar
}
I have written uch test with help of JMOCKIT,
Please read it might help you.
You just need to create object with overriding required methods.
Then use
Deencapsulation.setfield(FIXTURE,new Bar(){
//#Override you methods
});
FIXTURE is Object in which you want Bar instance available with mocked methods.
With the JMockit mocking library, you could simply declare a mock field as #Capturing Bar anyBar in your test class. This should cause any current or future Bar instances to be mocked, even if they belong to some subclass of Bar.

Guice / DI and mixing injection and parameters passed in at runtime

I have a situation where when I initialize some of my classes, some of the fields I need to be injected (e.g. references to factories etc) whereas some others are dynamic and created at runtime (e.g. usernames etc). How do I construct such objects using the GUICE framework?
Simply annotating the fields I need injected as #Inject doesn't work as they seem to not be set up when creating an object using the constructor. For instance:
class C {
#Inject
private FactoryClass toBeInjected;
private ConfigurationField passedIn;
public C(ConfigurationField passedIn) {
this.passedIn = passedIn;
}
}
If my understanding is correct (and I could be wrong), the fact that I'm creating a new instance of C via new and not through Guice means that no injection will take place. I do need to pass these parameters in the constructor, but also want some fields injected -- so how do I solve this problem?
A feature specifically matching "mixing injection and parameters passed" would be Assisted Injection.
class C {
// Guice will automatically create an implementation of this interface.
// This can be defined anywhere, but I like putting it in the class itself.
interface Factory {
C create(ConfigurationField passedIn);
}
#Inject
private FactoryClass toBeInjected;
private ConfigurationField passedIn;
private SomeOtherDepIfYoudLike otherDep;
#Inject public C(#Assisted ConfigurationField passedIn,
SomeOtherDepIfYoudLike otherDep) {
this.passedIn = passedIn;
this.otherDep = otherDep;
}
}
Now in your module:
#Override public void configure() {
install(new FactoryModuleBuilder().build(C.Factory.class));
}
Now when someone wants to create a C, they can avoid calling the constructor directly; instead, they inject a C.Factory into which they pass a ConfigurationField instance of their choice and receive a fully-constructed, fully-injected C instance. (Like with most well-designed DI objects, they can call the constructor directly.)
Note that this design is especially useful in a few ways:
You can use constructor injection, treat all your fields as final, and treat the object as immutable.
If you stick with constructor injection entirely, your object will never be in a partially-initialized state, and your API stays simple (call the constructor and your object is ready).
For testing, you can write any implementation of C.Factory and have it return any instance you want. This can include test doubles of C or its factory: Fakes, mocks, or spies that you create manually or by using Mockito, EasyMock, JMock, or any other mocking framework.
What you are looking for is "On Demand" Injections:
public static void main(String[] args)
{
Injector injector = Guice.createInjector(...);
CreditCardProcessor creditCardProcessor = new PayPalCreditCardProcessor();
injector.injectMembers(creditCardProcessor);
}
or for static things
#Override public void configure() {
requestStaticInjection(ProcessorFactory.class);
...
}
All explained very well https://github.com/google/guice/wiki/Injections#on-demand-injection.
Note:
Both of these things are code smells and should only really be used
for migrating old code over to Guice. New code should not use these
approaches.

How to test/mock this static factory (used for graph construction)?

So, I have implemented my business classes, where I pass in all dependencies via the constructor, so I can mock those out and easily unit test them. This works great so far, but then, at one point, I need to create an object graph out of those objects. For this, I'm using a static factory (I can't use a DI framework, sadly). Example:
public class FooBar {
public FooBar(Foo foo, Bar bar) {
this.foo = foo;
this.bar = bar;
}
}
public class Foo {
public Foo() {}
}
public class Bar {
public Bar(Foo foo) {
this.foo = foo;
}
}
public class GraphFactory {
public static FooBar newFooBar() {
Foo foo = new Foo();
Bar bar = new Bar(foo);
return new FooBar(foo, bar);
}
}
So, I'm not able to really test the GraphFactory (can't mock the dependencies), which is kinda ok (not much work is done here). But what if construction of the graph is more complex, i.e. it involves looking up some properties, doing JNDI lookups and so on?
Should I still not write a unit test for this? Is my class design maybe broken? Isn't the purpose of unit testing to test classes in isolation?
There is nothing wrong with this design and it is fully testable. If we focus on the single responsibilty of the factory -- it is responsible for assembling the object graph -- the tests for this are straight forward:
Set up the factory with its prerequisites.
Invoke the factory method.
Assert that the object was constructed to your requirements: default values are set, etc.
In the example above, foo, bar, and foobar are the result of the test and do not need to be mocked.
If the assembly of the object graph is more complex, and you need additional services to fetch data and check application settings, guess what happens? These dependencies are passed into the factory through its constructor. You should mock these dependencies to isolate the factory from its dependencies' dependencies. Consumers of your factory would receive a fully wired factory through their constructor; or the factory is assembled at application start-up and made available as a singleton, etc.
This is how DI works. It sounds peculiar because now you have to worry how the factory is created (and who created that object,etc, turtles all the way down) and this is a perfectly natural reaction.
That's why we have DI frameworks to assemble complex object graphs. In a well designed DI application, nothing should know how the graph was assembled. Akin to this design, nothing should know about the DI framework.
The only exception to that rule, is... (drum-roll)... a factory object!
Most DI frameworks will inject the DI container into an object if the object being resolved takes a DI in it's constructor. This greatly simplifies the factory's plumbing, and satisfies our design principles: no one knows how to construct our object except our factory and we've encapsulated knowledge of the DI container to key areas of the application that are responsible for object assembly.
Whew. Now, if you're still following along, how does this change our test? It shouldn't, at least not too much: step #1 changes slightly, where you fill the DI container with mock objects, and then construct the factory with the DI container.
As a matter of taste, some like to use auto-mocking DI containers during testing that will automatically generate mock dependencies when an item is requested. This can remove most of the set up pain.
If the newFooBar method had to be more complex, you could refactor out everything except for the creation of the Foo and the Bar into a package-private initialisation method. Then write tests for the initialisation method.
public class GraphFactory {
public static FooBar newFooBar() {
Foo foo = new Foo();
Bar bar = new Bar(foo);
FooBar toReturn = new FooBar(foo, bar);
initialise( toReturn );
return toReturn;
}
static void initialise( FooBar toInitialise ){
// some stuff here that you can test
}
}
You can't mock or stub static method calls but you can write a unit test for the factory without mocks.
But, why do you use static factory methods?. May be better to store the factory in a static variable if you want to access it in a static way.
You should give a look into Dependecy Injection, which will allow you get rid of the factory when used properly. I recommend you this video as an introduction, it helped me a lot:
http://code.google.com/p/google-guice/
It's an introduction to Guice, a library from google, but it will help you understand DI. Then you'll see how to replace all those 'new' with annotations, letting the library do all the work for you. Some people would recommend Sring instead, but i find Guice more friendly for beginners. I just hope this doesn't fire a Guice vs Spring discussion again :D

CDI with unmanaged objects

Suppose that I have two classes, first a class without any properties, fields or annotations:
public class B {}
And a class which gets B injected, like this:
public class A {
#Inject
private B b;
public B getB() {
return b;
}
}
Now class A is pretty useless until we use it, so there are two options:
#Inject it
Construct it manually, using the trusty "new A()"
If A gets injected, CDI manages it and is kind enough to inject B which has the implicit scope of #Dependent. Cool, just what I want.
However, if I manually construct A (let's say in a factory or a builder), CDI completely ignores my object and won't inject an object of type B.
Example I'm talking about when it doesn't work, here object a will always remain null:
public class Builder {
#Inject
private A a;
public static Builder ofTypeSomething() {
// do some magic here
return new Builder();
}
private Builder() {
// and some more here
}
}
Why doesn't this work?
Class A is a valid managed bean and has a valid scope, just like class B. Even if I add #Producer to the static method, it won't change anything (which is fine, cause the idea of the static method is to call it, not to inject Builder anywhere).
Dependency injection, while useful, is not magical. The way DI works is that when you ask the container for an instance of an object the container first constructs it (via new()) and then sets the dependencies (how this happens depends on your framework).
If you construct the entity yourself then the container has no idea you've constructed the entity and can't set the dependencies of the entity.
If you want to use a factory then most frameworks have some way of configuring the entity so that the container knows to make a static factory method call and not call the constructor of the entity. However, you still have to obtain your entity from the container.
Edit: This site seems to demonstrate how to use a factory in CDI.

Categories

Resources