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.
Related
As the title suggests , I want to know how does field injection internally works in spring , I read many articles on this and got to know few things like below but didn't understood the exact reason behind it :
-> It should not be used because when you do unit testing then you are dependent upon the spring
container to instantiate the class in case of field injection.
-> You cannot use "final" keyword in case of field injection , means you cannot make the field immutable.
-> It internally uses reflection
I want to know how exactly does #Autowired works internally , how does it uses reflection , I am trying to understand the exact reason behind all the above mentioned points, what happens behind the scenes when we write the below code :
#Component
public class B {
#Autowired
private A a1;
}
I have read similar questions on stack overflow about this topic , but I couldn't find the exact explanation that I am looking.
Spring has a concept of Bean Post Processors.
When spring builds a bean it applies registered bean post processors that help to "initialize" the bean.
So, there is org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor that handles autowiring.
Basically it works with an newly created object. Spring introspects the fields of the beans (by using reflection). The fields that have #Autowired is a subject for processing with this bean post processor. It finds the candidate for injection in the application context and actually injects the value.
Now given this information, its understandable why final fields cannot be autowired. Leave alone spring, In pure Java, final fields must be instantiated directly right during the declaration (final int i = 123) or in the constructor of the class. But the autowiring happens after constructor, so its impossible to autowire the final fields.
As for the unit testing, the private properties must be somehow configured from the test. But since they're encapsulated (yes, spring kind of breaks encapsulation in this case for its usage), its impossible to write a good test for the class that contains fields injection. That's is a reason to switch to constructor injection.
public class FieldInjection {
#Autowired
private A a;
}
VS.
public class ConstructorInjection {
private final A a;
// this can be generated by lombok, you don't have to put #Autowired on constructor in the case of single constructor, spring will use it to create a bean
public ConstructorInjection(A a) {
this.a = a;
}
}
Now the test for FieldInjection class is impossible:
public class FieldInjectionTest {
#Test
void test() {
FieldInjection underTest = new FieldInjection();
how do you know that you should instantiate A a. ????
}
}
However in the case of constructor injection its a trivial task:
public class ConstructorInjectionTest {
#Test
void test() {
A a = mock(A.class);
ConstructorInjection underTest = new ConstructorInjection(a);
// the dependencies must be supplied in the constructor
// otherwise its impossible to create an object under test
}
}
This question is about a correct usage of Guice #Assisted and #Provides and also, how to do it.
The current design I refer to is something like this:
The class in the top of the hierarchy is also the only class that is exposed to the client (basically, the public API), its looks something like that:
public class Manager{
public Manager(int managerId, ShiftFactory sf, WorkerFactory wf);
// methods ...
}
As you probably understand, id is provided by the user on creation time (#Assisted?)
but the others are not, they are just factories.
The class Manager creates instances of the class Shift.
The class Shift creates instances of the class Worker.
Now, in order to create the class Shift we use its constructor:
public Shift(int managerId, int shiftId, WorkerFactory wf);
shiftId provided by the Manager and the rest are the same objects from Manager's constructor.
In order to create Worker we use 2 static factory methods (but it can be changed..):
public Worker createWorkerTypeA(int shiftId, int workerId)
public Worker createWorkerTypeB(int shiftId, int workerId)
workerId provided by the Shift class. and the rest is delegated from Shift constructor.
What is the correct, Guice-y way to do it?
Where should I put #Assisted? #Provides?
I really would like a code example of that, including the abstract module, because the code exmaples i've seen so far are not understandable to me just yet.
Thanks
At a high level, what you want is for your factories to hide the predictable dependencies so you only have to specify the ones that change. Someone who has an instance of the Factory should only have to pass in data, not factories or dependencies. I picture the interface like this.
interface ManagerFactory {
Manager createManager(int managerId);
}
interface ShiftFactory {
Shift createShift(int managerId, int shiftId);
}
interface WorkerFactory { // The two methods here might be difficult to automate.
Worker createWorkerA(int managerId, int shiftId, int workerId);
Worker createWorkerB(int managerId, int shiftId, int workerId);
}
class Manager {
#Inject ShiftFactory shiftFactory; // set by Guice, possibly in constructor
private final int managerId; // set in constructor
Shift createShift(int shiftId) {
shiftFactory.createWorkerA(this.managerId, shiftId); // or B?
}
}
class Shift {
#Inject WorkerFactory workerFactory; // set by Guice, possibly in constructor
private final int managerId; // set in constructor
private final int shiftId; // set in constructor
Worker createWorker(int workerId) {
shiftFactory.createShift(this.managerId, this.shiftId, workerId);
}
}
Note here that Manager doesn't care at all about workers—it doesn't create them, so unlike in your question, you don't have to accept a WorkerFactory just to pass it along to your Shift. That's part of the appeal of dependency injection; you don't have to concern a middle-manager (middle-Manager?) with its dependencies' dependencies.
Note also that none of the Factory interfaces or implementations are even slightly visible to your public API outside of constructors. Those are implementation details, and you can follow along the object hierarchy without ever calling one from outside.
Now, what would a ManagerFactory implementation look like? Maybe like this:
class ManualManagerFactory {
// ShiftFactory is stateless, so you don't have to inject a Provider,
// but if it were stateful like a Database or Cache this would matter more.
#Inject Provider<ShiftFactory> shiftFactoryProvider;
#Override public Manager createManager(int managerId) {
return new Manager(managerId, shiftFactoryProvider.get());
}
}
...but that's largely boilerplate, and possibly much more so when there are a lot of injected or non-injected parameters. Guice can do it for you, instead, as long as you still provide your ManagerFactory interface and you annotate a constructor:
class Manager {
private final ShiftFactory shiftFactory; // set in constructor
private final int managerId; // set in constructor
#Inject Manager(ShiftFactory shiftFactory, #Assisted int managerId) {
this.shiftFactory = shiftFactory;
this.managerId = managerId;
}
// ...
}
// and in your AbstractModule's configure method:
new FactoryModuleBuilder().build(ManagerFactory.class);
That's it. Guice creates its own reflection-based ManagerFactory implementation by reading the return type of the Manager method, matching that to the #Inject and #Assisted annotations and the interface method parameters, and figuring it out from there. You don't even need to call the implement method on FactoryModuleBuilder unless Manager were an interface; then you'd have to tell Guice which concrete type to create.
For kicks and grins, let's see the same thing with Google's code-generating AutoFactory package:
#AutoFactory(
className = "AutoManagerFactory", implementing = {ManagerFactory.class})
class Manager {
private final ShiftFactory shiftFactory; // set in constructor
private final int managerId; // set in constructor
#Inject Manager(#Provided ShiftFactory shiftFactory, int managerId) {
this.shiftFactory = shiftFactory;
this.managerId = managerId;
}
// ...
}
Almost identical, right? This will generate a Java class (with source code you can read!) that inspects the Manager class and its constructors, reads the #Provided annotations (n.b. #Provided is the opposite of FactoryModuleBuilder's #Assisted), and delegates to the constructor with its combination of parameters and injected fields. Two other advantages to Auto, which works with Guice as well as Dagger and other JSR-330 Dependency Injection frameworks:
This is normal Java code free of the reflection in Guice and its FactoryModuleBuilder; reflection performance is poor on Android, so this can be a nice performance gain there.
With code generation, you don't even need to create a ManagerFactory interface--without any parameters to #AutoFactory you would wind up with a final class ManagerFactory { ... } that has exactly the behavior Guice would wire up through FactoryModuleBuilder. Of course, you can customize the name and interfaces yourself, which might also help your developers as generated code sometimes doesn't appear well to tools and IDEs.
UPDATE to answer comments:
Regarding createWorker: Yes, sorry, copypaste error.
Regarding automation: It's because neither Assisted Inject nor AutoFactory has a great way to delegate to static methods, or to work with constructors that have identical assisted (user-provided) arguments. This is a case where you might have to write a Factory of your own.
Regarding Manager not needing a WorkerFactory: The only reason Manager would require WorkerFactory is if it's creating either a ShiftFactory or a Shift itself by calling the constructor. Note that my example does neither of those: You're letting the dependency injection framework (Guice) provide the dependencies, which means that the WorkerFactory is hiding in the ShiftFactory that Guice is already providing.
Im interested what is the proper manner to construct object with dependencies which themselves have #Assisted params. An example will better illustrate:
Ordinarilly with dependencies that do not have #Assisted params you can simply have a complex heirarchy of objects which all have their dependencies and these get injected no problem, I can just get an instance of an object and all its dependencies will be generated and injected without me having to do anything.
But if I wanted to change it so some of the dependencies in the object hierarchy have #Assisted params then I have to create those instances myself using a factory ie:
public SomeConcreteService(#Assisted String string) {
this.string = string;
}
MyFactory myFactory = injector.getInstance(MyFactory .class);
SomeService myService = factory.getMyService("some string");
This would cause problems for the clean instantiation of the objects because I would have to manually create those instances. and pass them into the required object, which essentially renders the DI for that object redundant I think???? ie I would then need to use the new keyword and pass in all dependencies manually...
new MyComplexObject(myService, myOtherService)
How do I make it so that I don't have to manually build the object graph if one or more of the dependencies uses #Assisted parameters?
The question you need to ask yourself is, "why am I making this #Assisted, and who is going to create these objects?"
If you use the key to get an instance you need, then what you have is fine:
public class YourInjectableClass {
#Inject private MyFactory factory;
public void doStuff(String key) {
// You have a key, and your factory, so you can create the instance yourself.
SomeService service = factory.getMyService(key);
// [...]
}
}
But if you use the key to get an instance create an instance to create an instance to get what you need, then that seems problematic. That might be a better problem for child injectors:
public class YourInjectableClass {
#Inject private Injector injector;
public void doStuff(String key) {
// You need an OuterObject. So rather than calling
// new OuterObject(new InnerObject(factory.getMyService(key))), do:
OuterObject outerObject =
injector.createChildInjector(new OuterObjectModule(key))
.getInstance(OuterObject.class);
// [...]
}
}
Because your value is needed throughout the dependency tree, you can treat it as an injected dependency. This can be a little more confusing, but saves you from letting your dependencies care about instantiation details all the way down the line.
Alternatively, you can create a manual OuterObjectFactory facade which does manually call new. This may be a better solution for legacy code, but can help to follow the Single Responsibility Principle by ensuring that one class is responsible for abstracting away instantiation details.
N.B. I'm assuming that SomeConcreteService takes other dependencies that the object graph can provide. If not, then there's no reason to use injection at all: Give SomeConcreteService a public constructor and call new SomeConcreteService("your value here") where needed. Though Guice takes some pains to abstract away the use of new, it is also unnecessary to create data objects or dependency-light objects like HashMap or Date.
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.
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.