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.
Related
I'm using Dagger2 in a google appengine project and I have several servlets that make use of, what should be, a singleton instance of a given object (MyObject).
#Singleton
#Component(modules = {MyModule.class})
public interface MyComponent {
IMyObject object();
}
I then need DaggerMyComponent.create() to be a singleton too so that I can get the same IMyObject across all servlets. To do so, I added a
DaggerMyComponent INSTANCE = DaggerMyComponent.create()
to my MyComponent interface. However, that still allows create() to be called again by mistake and it doesn't necessarily look like a pretty solution to me.
Any ideas?
Thanks!
Unfortunately the docs seem to be saying that Dagger doesn't provide such a limitation so far as for version 2.0.1
In order to get the proper behavior associated with a scope
annotation, it is the caller's responsibility to instantiate new
component instances when appropriate. A Singleton component, for
instance, should only be instantiated once per application, while a
RequestScoped component should be instantiated once per request.
http://google.github.io/dagger/api/latest/dagger/Component.html
I have doubts on when to inject the provider of an interface and when to inject an interface directly.
What is the appropriate situation where a provider should be used? Please give examples.
If the scope of an interface is #Dependant, then the injector will create a new object anyway, if so then do we still need to use a provider?
If #New is used, a new object is created. Do we need a provider then?
One of the main reasons to use providers (you don't inject providers though) is to do some configuration of a class. Another good reason is if the class isn't available as a CDI bean.
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.
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.
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