Guice and 'injection' of the Injector - java

I tryied Google Guice after reading this article : http://tech.puredanger.com/2007/07/03/pattern-hate-singleton/
But there is something I didn't understand : when you use the #Singleton anotation of Guice, the injection inject the same instance, but only for one Injector.
If I create an other Injector somewhere else, the #Singletion doesn't works (as stated in the documentation).
So I will have to pass the injector instance everywhere in my code, or make it available in a singleton.
And this is exactly I would like to avoid.
How to we manage injectorS to make it possible to return the same instance everytime ?
Thanks.

Code using Guice shouldn't normally need to access the injector itself: objects will receive either their dependencies or a Provider<T> for their dependencies, if they need to construct more than one.
Usually, objects only need the injector if they have dependencies but aren't themselves created by the injector (so they can't have their dependencies injected). If you're using Guice everywhere, you probably only need to do that on application start-up. If you're only using Guice for part of your project, the injector becomes a single singleton that proxies for all the other singletons you're now accessing through it.
Do note that classes annotated #Singleton are still singleton objects, albeit without some of the baggage associated with non-injected singletons. You should still try to avoid depending on them too much.

Related

How to use Guice's Injector?

I'm in process of learning Guice and I don't clearly understand how to use Injector instance. It's better to create Injector instance once on application bootstrap, and make it public singleton?
And is it true that we always must use Injector#getInstance(SomeClass.class) to get classes where we putted Guice's #Inject annotations?
You should not pass the injector around as a global singleton. Have you looked at: https://github.com/google/guice/wiki/GettingStarted? Note that RealBillingService does not use the injector to get instances of CreditCardProcessor and TransactionLog. Instead Guice handles all this for you when creating the instance.
If you're in a situation where you need Guice to create many objects of the same type consider using a Provider and injecting that provider.

Proper structure for dependency injection (using Guice)

I would like some suggestions and feedback on the best way to structure dependency injection for a system with the structure described below. I'm using Guice and thus would prefer solutions centered around it's annotation-based declarations, not XML-heavy Spring-style configuration.
Consider a set of similar objects, Ball, Box, and Tube, each dependent on a Logger, supplied via the constructor. (This might not be important, but all four classes happen to be singletons --- of the application, not Gang-of-Four, variety.)
A ToyChest class is responsible for creating and managing the three shape objects. ToyChest itself is not dependent on Logger, aside from creating the shape objects which are.
The ToyChest class is instantiated as an application singleton in a Main class.
I'm confused about the best way to construct the shapes in ToyChest. I either (1) need access to a Guice Injector instance already attached to a Module binding Logger to an implementation or (2) need to create a new Injector attached to the right Module.
(1) is accomplished by adding an #Inject Injector injectorfield to ToyChest, but this feels weird because ToyChest doesn't actually have any direct dependencies --- only those of the children it instantiates.
For (2), I'm not sure how to pass in the appropriate Module.
Am I on the right track? Is there a better way to structure this?
The answers to this question mention passing in a Provider instead of using the Injector directly, but I'm not sure how that is supposed to work.
EDIT:
Perhaps a more simple question is: when using Guice, where is the proper place to construct the shapes objects? ToyChest will do some configuration with them, but I suppose they could be constructed elsewhere. ToyChest (as the container managing them), and not Main, just seems to me like the appropriate place to construct them.
A proper way is to have guice construct your dependencies. That is create and configure.
In your situation you should have an injector constructed in the Main. From the injector you get ToyChest. When you obtain ToyChest through the injector its managed by guice and you can depend on it to supply all dependencies properly configured.
In your case you can inject Provider<Ball>, Provider<Box>, etc. in ToyChest and when needed just retrieve instance from the provider. ToyChest is not responsible for constructing the instance, just to use it. You can also check MapBinder if you have a plugin architecture.
So far everything is managed by guice, so the shapes can have their logger injected without the using class knowing about it.
If you have some runtime parameters that you want to pass to the newly created shape instances, you can use AssistedInject.
Just a hint: you are not required to use constructor injection, you can have injection on field or setter, which simplifies the constructor.

Guice Injection into Business Layer of Java Web App

I have sucessfully used Guice to Inject Providers into the servlet portion of an existing java web application, however, I can't access the injectors through the business layer (non-servlet java classes) of the application.
I have read up on Injecting the Injector, but to me that seems more like a hack and in several places, including the Guice documentation, it says not to do that too much.
I guess my question is, Where do I bootstrap a java web app so that the non-servlet/filter classes have access to the injector created in the class I use to extend GuiceServletContextListener? Is there any way to make those classes injectable without injecting the injector?
Thank you and let me know if you need any clarification.
Edit:
I am attempting to do this with a simple logger, so far, in my
servlets, I call:
#Inject
private static org.slf4j.Logger log;
The injection is set up in MyLoggerModule as follows (which is in the
createInjector call with ServletModule) :
#Override
public void configure() {
bindListener(Matchers.any(), new SLF4JTypeListener()); // I
built my own SLF4JTypeListener...
}
This all works perfectly in the servlets, but the field injection does
not work when called by a class that is not a servlet or filter.
Guice doesn't intercept calls for new objects, so if your business layer isn't already using Guice to create the objects that need injection, it'll need modification to do so.
The injection only works when handled by Guice during injection. So starting from the base injector you've made, whatever is marked with #Inject which is needed for the instance you've requested will be provided by Guice as best it can, and in turn, during instanciation of those, further #Inject annotations will be filled in by providers and bindings until nothing new needs to be instanciated. From that point on however you are not going to get fields injected into servlets created outside Guice's injection, perhaps by calling new somewhere, which is likely what your Object Factory is doing.
You'll need to change your Object Factory to use providers instead of new. If you could edit these, it wouldn't be too hard to do since Guice can give you default providers for bindings.
So one way your business layer could be Guice aware is to have whatever is creating servlets first create an Injector and then request the servlets be created by the injector. If this means you'll have more than one injector, then yes, that will be a problem but only for the objects you want to be singletons. So you could make a factory pattern class for a singleton injector, or you could find where these classes (here typed bar) which are creating servlets themselves are created (in foo), and then start with the injector there (in foo) using one Guice injector to create those (bar type) classes and also modifying them (bar type) to request a provider for the servlets which they'll use instead of making calls for a new servlet.
Now that I think about this, it could be simple if it kind of only happens once or twice for 10-20 servlet types, or it could be complicated if there's some framework that defines totally flexible behavior for what gets newed up when and why.
Another option would be avoiding #Inject on fields at all times, as recommended. So now your servlets are taking in an org.slf4j.Logger as a construction parameter. The constructor is marked #Inject, and it assigns the parameter's value to the field. Then any place you're not using injection should break with an incorrect number of parameters at a new call. Fix these by figuring out how to either get the servlet provided here instead, or how to get a provider for the servlet into the class.
Not sure what you mean... if you inject objects in to your servlets/filters, those objects have their dependencies injected by Guice as well, and so on all the way down.
How are you creating the classes that you're trying to inject this logger in to? They must be created by Guice to be injected, which means no new.

Guice: Do I have to annotate every class of an object graph with #Inject?

I'd like to introduce Guice for the use of an existing mid-sized project.
For my demands I need a custom scope (session is too big, while request to small for my project).
Imagine that I request guice to provide me an instance of Class A which has direct and indirect dependencies to many other classes (composition).
My custom provider is able to provide the instance of classes which are used as constructor arguments of all involved classes.
Question:
Do I really have to put an #Inject (and my custom scope) annotation on the constructors of all involved classes or is there a way that guice only requires these annotations on the top-level class which I request and that all further dependencies are resolved by "asking" my custom scope for a provider of the dependent types?
If this is true this would increase the effort of introducing Guice because I have to adjust more than 1000 classes. Any help and experiences during the introduction of guice is appreciated.
First of all, it's possible to use Guice without putting an #Inject annotation anywhere. Guice supports Provider bindings, #Provides methods and constructor bindings, all of which allow you to bind types however you choose. However, for its normal operation it requires #Inject annotations to serve as metadata telling it what dependencies a class requires and where it can inject them.
There reason for this is that otherwise, it cannot deterministically tell what it should inject and where. For example, classes may have multiple constructors and Guice needs some way of choosing one to inject that doesn't rely on any guessing. You could say "well, my classes only have one constructor so it shouldn't need #Inject on that", but what happens when someone adds a new constructor to a class? Then Guice no longer has its basis for deciding and the application breaks. Additionally, this all assumes that you're only doing constructor injection. While constructor injection is certainly the best choice in general, Guice allows injection of methods (and fields) as well, and the problem of needing to specify the injection points of a class explicitly is stronger there since most classes will have many methods that are not used for injection and at most a few that are.
In addition to #Inject's importance in telling Guice, it also serves as documentation of how a class is intended to be used--that the class is part of an application's dependency injection wired infrastructure. It also helps to be consistent in applying #Inject annotations across your classes, even if it wouldn't currently be absolutely necessary on some that just use a single constructor. I'd also note that you can use JSR-330's #javax.inject.Inject annotation in Guice 3.0 if a standard Java annotation is preferable to a Guice-specific one to you.
I'm not too clear on what you mean by asking the scope for a provider. Scopes generally do not create objects themselves; they control when to ask the unscoped provider of a dependency for a new instance and how to control the scope of that instance. Providers are part of how they operate, of course, but I'm not sure if that's what you mean. If you have some custom way of providing instances of objects, Provider bindings and #Provides methods are the way to go for that and don't require #Inject annotations on the classes themselves.
NO YOU DONT
GUICE does not ask you to inject every single object. GUICE will try and create only injected objects. So you can #Inject objects that you want to be injected.
On the scope bit - Scope essentially controls how your objects gets created by GUICE. When you write your own custom scope you can have a datastructure that controls the way objects are created. When you scope a class with your custom annotation, GUICE will call your scope method before creation with a Provider for that class. You can then decide if you want to create a new object or use an existing object from a datastructure (such as hashmap or something). If you want to use an existing one you get that and return the object, else you do a provider.get() and return.
Notice this
public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
return new Provider<T>() {
public T get() {
Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);
#SuppressWarnings("unchecked")
T current = (T) scopedObjects.get(key);
if (current == null && !scopedObjects.containsKey(key)) {
current = unscoped.get();
scopedObjects.put(key, current);
}
// what you return here is going to be injected ....
// in this scope object you can have a datastructure that holds all references
// and choose to return that instead depending on your logic and external
// dependencies such as session variable etc...
return current;
}
};
}
Here's a tutorial ...
http://code.google.com/p/google-guice/wiki/CustomScopes
At the most basic level, the #Inject annotation identifies the stuff guice will need to set for you. You can have guice inject into a field directly, into a method, or into a constructor. You must use the #Inject annotation every time you want guice to inject an object.
Here is a guice tutorial.

How do I write a Guice Provider that doesn't explicitly create objects?

Say I have a ClassWithManyDependencies. I want to write a Guice Provider for this class, in order to create a fresh instance of the class several times in my program (another class will depend on this Provider and use it at several points to create new instances).
One way to achieve this is by having the Provider depend on all the dependencies of ClassWithManyDependencies. This is quite ugly.
Is there a better way to achieve this?
Note - I certainly don't want the Provider to depend on the injector. Another option I considered is having ClassWithManyDependencies and ClassWithManyDependenciesProvider extend the same base class, but it's butt ugly.
As mentioned on the mailing list, anywhere you can inject ClassWithManyDependencies you can simply inject Provider<ClassWithManyDependencies> instead, no need to write anything special yourself. Guice does this for you.
You shouldn't have to write a provider except to integrate with other frameworks.
Just DON'T bind your ClassWithManyDependencies in scope SINGLETON and in the class that wants to build many instances, instead of having a ClassWithManyDependencies instance injected you have a Provider injected. (Guice can do that for free for every binded class)
On this provider you can just call get(), if not in scope SINGLETON it makes a fresh new instance each time.
Now if you are in the tricky case that ClassWithManyDependencies relies both on some GUICE IOC and on some constructor parameters, then you shall go for Assisted Injections

Categories

Resources