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
Related
I have inherited a Java web service project that is using Dagger 2. Based on my so far limited understanding of Dagger I am confused as to why every single class that is injected has the singleton annotation on it in the dagger module class's. If I was creating this application without dagger they would not all be singletons, is this something specific to dagger or have the previous developers simply misused Dagger?
[...] every single class that is injected has the singleton annotation [...] is this something specific to dagger [...]?
Nope. #Singleton is the only scope included with Dagger by default, but you can also create custom scopes, use #Reusable which may create multiple objects but will reuse them if possible, or no scope at all.
or have the previous developers simply misused Dagger?
If possible you should just ask them. If every object is a Singleton this looks like they did not invest a lot of thought in the setup and just copy-pasted declarations, at least this would be my assumption.
From the section about Reusable in the user guide:
Sometimes you want to limit the number of times an #Inject-constructed
class is instantiated or a #Provides method is called, but you don’t
need to guarantee that the exact same instance is used during the
lifetime of any particular component or subcomponent. This can be
useful in environments such as Android, where allocations can be
expensive.
Two main differences:
#Singleton annotated class is guaranted to give always the same instance. It is needed if we keep global state in it. #Reusable do not give any guarantee.
If any class requests the instance of #Singleton annotated class, double checking is performed (which is slow). In case of #Reusable, it isn't.
I'd use #Reusable scope for classes that are expensive to build (for example I'm using for Retrofit instance - but to be honest I've never made performance tests if it is worth to use this annotation at all).
On the other hand, I'm using #Singleton annotated class for the cache.
Also, if you have class which keeps encapsulated global state like this:
class StateWrapper {
final State state;
#Inject
StateWrapper(State state) {
this.state = state;
}
}
I mean the state is de facto kept in the State class, do not annotate StateWrapper as #Singleton, always annotate the smallest part: in this case the State class.
(This hint is taken from the video)
I'm wondering how I can bind a singleton to a parameter in a provider.
ie:
#Singleton
public class RunButtonController{
#Inject
public RunButtonController(EventBus eventbus){ ... }
public JComponent getView(){
return view;
}
...
}
public class UncaughtExceptionController{
#Inject
public UncaughtExceptionController(
EventBus eventBus, ...,
#Named(DefaultExceptionViewKey) JComponent defaultView)
{ ... }
...
}
public class GUIController{
//another consumer of RunButtonController, arguably the "main" consumer.
#inject
public GUIController(RunButtonController runButtonController,
UncaughtExceptionController uncaughtExceptionController, ...)
{ ... }
...
}
public class Bootstrapper{
public static void main(String[] args){
Injector injector = Guice.createInjector(new OptipModule());
GUIController controller = injector.getInstance(GUIController.class);
}
private static class OptipModule extends AbstractModule{
#Override
protected void configure() {
bind(EventBus.class).toInstance(new EventBus("OPTIPGlobalEventBus"));
bind(JFrame.class).to(GUIView.class);
}
#Provides #Named(DefaultExceptionViewKey)
public JComponent getFrom(RunButtonController runButtonController){
return runButtonController.getView();
}
}
}
Putting a breakpoint on my RunButtonController constructor, I can see it consistently getting instanced twice. I want it to only be instanced once, and I want
defaultExceptionViewProvider == runButtonController
to be true.
I've used Castle Windsor fairly extensively, but that's the only IOC container I've used, so I'm new to guice. I'm seeing remnants of visitor behavior all over the place, and guice's documentation makes it pretty clear that the defined behavior of a class (ie, instance once, use this instance, use this factory, ...) doesn't persist beyond the module it was configured for. I'd like to say that I saw it written that when you use an #Provides, guice creates a child module for you, so presumably what I need to do is tell this child #Provides-generated module that 'hey, this class is a singleton and I'm in the process of resolving it, so here it is! don't use your own!'
I think that I'm going about this framework the wrong way. I've been smashing down annotations and hitting debug, but perhaps what I really need to do is spend a few hours reading a good tutorial, unfortunately I cannot find one. The JavaDoc has examples, and the webpage publishes them, but they give you very little context and so, having read the article on #Assisted three times, I still don't understand it (perhalps that's what I should be using?) Bonus points for somebody who points in the direction of a particularly detailed blogger and a guice entry on his page.
Along those lines, and digressing enormously, I'm wondering what the ramifications are of me trying to pushing this 'hey your default notification area is this other guys view' into my IOC container. Is that maybe domain logic? I don't really want the UnhandledExceptionController to know that its view was provided by a RunButtonController, and similarly I don't want the RunButtonController to know its view is being used for anything other than being stamped out onto the view tree.
thanks for reading!
As posted, it looks like your code should work. That said, there are a few caveats that could cause singletons to coexist. Double-check the stack trace for each of the constructor calls.
It may be obvious, but you can create any number of instances outside of Guice's control, and Guice has no way of knowing those instances exist. Double check that nothing in your code calls the RunButtonController constructor manually.
Singleton behavior is enforced within any given injector. If you have two or more injectors in your application, they could each create their own instance of RunButtonController. A singleton declared in a parent injector would be visible to any child injectors, though.
Singletons work by key. If you were to remove the #Singleton annotation and add this:
bind(RunButtonController.class)
.annotatedWith(Names.named("Foo"))
.asEagerSingleton()
Then injecting RunButtonController would get you a new instance every time, but injecting #Named("Foo") RunButtonController would get you a separate singleton instance that would return the same every time. That probably doesn't apply to you, because the #Singleton is on the class itself, but it has bitten others before.
You don't seem to rely on inheritance, but remember that singleton annotations don't inherit from superclass to subclass.
Side note: #Provides methods don't work via child injectors, but private modules do (alluded to as "parent injectors" in the documentation). Internally, it's true that a separate internal module is responsible for calling those provider methods, but that doesn't really matter—singletons are shared between modules.
Regarding your digression about sharing views: You're doing fairly well already by injecting #Named(DefaultExceptionViewKey) JComponent instead of RunButtonController, but if you wanted to be even more implementation-agnostic, you could create an ExceptionHandlerComponent interface and code against that.
What is the best method to access Service Layer from Controller in Spring MVC? I'm using annotations for SpringMVC.
Earlier I used to get the bean everytime from the bean factory by calling ClassPathXMLApplicationContext(spring-bean-name.xml) in every method of controller.
From the solution to question Accessing Service Layer from custom Controller in Spring MVC I understand that service bean has to be autowired.
However suppose a controller accesses multiple services do we have to inject multiple beans? But that won't be a good practice cause we will have to use a particular service only in 1-2 methods within a controller and its not good to make it a class variable rather than a function variable.
You are correct, you need to autowire the services you intend to use. Don't worry about class variable versus local (function) variable, this is how the DI pattern is implemented.
In the strictest OO-design sense, you have a point that you should not declare variables on a class-level unless they are involved in describing the state of an object. DI (Dependency Injection) is, however, a very established pattern on no developer is going to frown upon service beans as autowired class members, regardless of how many methods actually use the service.
On a side-note, doing new ClassPathXMLApplicationContext("spring-bean-name.xml") in every method is absolutely, 100% the wrong way to do it. That involves creating a new bean-factory and bean-context every time you execute that method which is a big overhead and completely unnecessary. The bean-factory should be created once (if you're in a servlet-engine environment, by using the DispatcherServlet or the ContextLoaderListener).
You can have a static class which instantiates bean factory and then use custom static getBean method of this static class
static class SpringConfig()
{
private static ApplicationContext ctx = null;
static
{
ctx=new ClassPathXmlApplicationContext("context.xml");
}
public static Object getBean(String beanName)
{
return ctx.getBean(beanName);
}
}
This is why you have to try to keep all the methods that use the same dependencies together, this is low coupling. The bad practice is not injecting your dependencies as global variables. The bad practice is to not group your methods to make your class less coupled.
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.
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.