-
Dependency injection with Guice (20 messages)
- Posted by: Ryan Taylor
- Posted on: December 15 2008 07:26 EST
Guice is Google's open source dependency injection framework for Java development. It enables better testing and modularity by taking away the pain of writing your own factories. This article offers a tour of the most important Guice concepts that will leave you ready to Guice up your applications.Threaded Messages (20)
- Article tries to downplay effects of annotation by Torben Putkonen on December 15 2008 09:22 EST
- Re: Article tries to downplay effects of annotation by Jason Lee on December 15 2008 10:19 EST
- Re: Article tries to downplay effects of annotation by Solomon Duskis on December 15 2008 11:38 EST
- Re: Article tries to downplay effects of annotation by Will Hartung on December 15 2008 12:14 EST
-
Re: Article tries to downplay effects of annotation by Bob Lee on December 15 2008 12:24 EST
-
Re: Article tries to downplay effects of annotation by Torben Putkonen on December 16 2008 09:10 EST
- Re: Article tries to downplay effects of annotation by James Watson on December 16 2008 01:38 EST
-
Re: Article tries to downplay effects of annotation by Torben Putkonen on December 16 2008 09:10 EST
-
Re: Article tries to downplay effects of annotation by Bob Lee on December 15 2008 12:24 EST
- Re: Article tries to downplay effects of annotation by Sony Mathew on December 15 2008 12:17 EST
- Re: Article tries to downplay effects of annotation by Aleksandr Panzin on December 15 2008 17:55 EST
- Re: Article tries to downplay effects of annotation by Mathieu Carbou on December 15 2008 20:04 EST
- Re: Article tries to downplay effects of annotation by Marc de Kwant on December 16 2008 01:56 EST
-
Constructors are preferred (by me anyway) by rob bygrave on December 16 2008 06:17 EST
-
Hmmm... looks like I was wrong ? by rob bygrave on December 16 2008 06:55 EST
- 9.1.1 Post-Construction Modification of Final Fields by rob bygrave on December 16 2008 11:04 EST
-
Re: Hmmm... looks like I was wrong ? by Bob Lee on December 16 2008 11:54 EST
-
Re: Hmmm... looks like I was wrong ? by James Watson on December 17 2008 10:21 EST
- Re: Hmmm... looks like I was wrong ? by Bob Lee on December 17 2008 12:39 EST
-
Re: Hmmm... looks like I was wrong ? by James Watson on December 17 2008 10:21 EST
-
Hmmm... looks like I was wrong ? by rob bygrave on December 16 2008 06:55 EST
- 2 cents by Leif Ashley on December 15 2008 09:49 EST
- No edit? by Leif Ashley on December 15 2008 09:51 EST
- I agree by Bj??rn Caroll on December 15 2008 10:55 EST
-
Article tries to downplay effects of annotation[ Go to top ]
- Posted by: Torben Putkonen
- Posted on: December 15 2008 09:22 EST
- in response to Ryan Taylor
"Some engineers dislike the idea of adding an @Inject to their class. They prefer that a class be totally ignorant of the DI framework. This is a reasonable point, but I'm not convinced by it. As dependencies go, an annotation is pretty mild. The @Inject tag takes on meaning only when you ask Guice to construct your class." This is incorrect. The "@Inject" annotation takes meaning as soon as it is added to the Java code. After the annotation is added, it is no longer possible to compile the code without Guice. Add the annotation and you've injected one more dependency to your project. Having said that... why do all the articles that praise Guice exclude the import statements from the Java code examples? Embarrassed maybe? -
Re: Article tries to downplay effects of annotation[ Go to top ]
- Posted by: Jason Lee
- Posted on: December 15 2008 10:19 EST
- in response to Torben Putkonen
Having said that... why do all the articles that praise Guice exclude the import statements from the Java code examples? Embarrassed maybe?
Personally, I find the imports in code examples to be useless noise. I can always copy and paste the code, press Shift-Command-I (NetBeans on the Mac FTW! :) and move on. Having to wade through all of that in someone's blog entry adds zero value to the discussion, unless the discussion is "Look at all those imports!" :) -
Re: Article tries to downplay effects of annotation[ Go to top ]
- Posted by: Solomon Duskis
- Posted on: December 15 2008 11:38 EST
- in response to Torben Putkonen
"... The @Inject tag takes on meaning only when you ask Guice to construct your class." After the annotation is added, it is no longer possible to compile the code without Guice. Add the annotation and you've injected one more dependency to your project.
The original meaning of "meaning" is at runtime, not compile time. Sure, compile time dependency may not be 100% ideal, but IMHO, it's not that bad either. You still can use any class annotated with @Inject outside of a Guice runtime. Projects that use IoC can have plenty of unit tests (and other runtime scenarios) that don't need Guice to manage the runtime behavior of your objects. -
Re: Article tries to downplay effects of annotation[ Go to top ]
- Posted by: Will Hartung
- Posted on: December 15 2008 12:14 EST
- in response to Torben Putkonen
What's interesting is that (from my glance at the article, being otherwise ignorant of Guice) it seems that you can add your own annotations in order to provide selectivity to what "types" of objects are injected (i.e. the "Fast" example with @Fast). By the same token, you'd like to think it would be a minor tweak to change the Guice supplied @Inject annotation with a project supplied @MyInject annotation. Assuming @Inject is simply a marker annotation (without other parameters), it should be straightforward to augment Guice by making the annotation used for marking Injection a parameter to the framework. Then you could fire up Guice, tell it to use @MyInject, and then you'd have no external dependencies within (the bulk of) your code. Only that code that relied on the Guice Factory would be dependent, and even that could likely be refactored to a single class or set of classes making your framework reliance quite isolated. -
Re: Article tries to downplay effects of annotation[ Go to top ]
- Posted by: Bob Lee
- Posted on: December 15 2008 12:24 EST
- in response to Will Hartung
Hi, Will. Kevin B. recently answered this question on the Guice mailing list (http://groups.google.com/group/google-guice/browse_thread/thread/323cc1f4e6b074e5):First off, your code is going to depend on some interfaces like Module and Provider anyway, so your change with the annotations doesn't really change anything. I do think it would make sense for us to put these common interfaces and annotations into their own small JAR file, so you can feel more light and airy when you depend on only that, and there is a feature request filed for it (I don't remember if Bob and Jesse agree, though). Beyond that, I think that some people, when seeing "import com.google.inject.Inject", simply imagine a problem where none really exists. We all work so hard at keeping dependencies out of our code that when we see that we react against it at a gut level. But in reality, your classes have no runtime dependency on Guice. If they run as part of an application that doesn't wish to use Guice, the Guice jar file needn't even be present on the server at all. The idea of "dependency" or "tight coupling" is that "the one cannot function without the other." But with annotations, this isn't the case. They're just decoration that don't, and can't, actually do anything. They sit there, innocuously, in case tools will wish to read them, and otherwise have no effect whatsoever. They don't impede you from testing your code, or from using the classes with Spring or just using them normally. Hopefully this explains why we have never been convinced there's an actual problem here.
-
Re: Article tries to downplay effects of annotation[ Go to top ]
- Posted by: Torben Putkonen
- Posted on: December 16 2008 09:10 EST
- in response to Bob Lee
Hopefully this explains why we have never been convinced there's an actual problem here.
The size of the JAR is not an issue. The issue is that the JAR file exists and is needed. The problem is the Guice dependency that is added to the code. The number of extra JAR files I need is greater than 0. If I want to use Spring, I still need Guice to compile. If I ask it a bit differently, then maybe then my point is clearer: Please provide a list of all the DI frameworks that my code should support. DI frameworks are supposed to support the code. Not the other way around. Guice makes some neat tricks, but it fails because it makes the assumption that it is the universal solution. -
Re: Article tries to downplay effects of annotation[ Go to top ]
- Posted by: James Watson
- Posted on: December 16 2008 13:38 EST
- in response to Torben Putkonen
I am not a Guice user (we are still on 1.4 at work) but I think to be fair, Bob Lee is actually trying to put the power back in the hands of the developer whereas Spring tries to wipe your ass for you. On the other hand, I actually quite agree that the issue you are pointing to is quite a real one. But I see it as a flaw with annotations. I used to use xdoclet back in the day and as crude as it is compared to annotations it was nice that all you added to your code was comments and nothing broke if you dropped xdoclet.Hopefully this explains why we have never been convinced there's an actual problem here.
The size of the JAR is not an issue. The issue is that the JAR file exists and is needed.
The problem is the Guice dependency that is added to the code. The number of extra JAR files I need is greater than 0. If I want to use Spring, I still need Guice to compile. If I ask it a bit differently, then maybe then my point is clearer:
Please provide a list of all the DI frameworks that my code should support.
DI frameworks are supposed to support the code. Not the other way around. Guice makes some neat tricks, but it fails because it makes the assumption that it is the universal solution. -
Re: Article tries to downplay effects of annotation[ Go to top ]
- Posted by: Sony Mathew
- Posted on: December 15 2008 12:17 EST
- in response to Torben Putkonen
Use the Context IoC design pattern. I have been using it since Java 1.3 and works great. See article https://www.theserverside.com/tt/articles/content/IOCandEJB/article.html The article needs an update (in progress..) but mostly still applies. -
Re: Article tries to downplay effects of annotation[ Go to top ]
- Posted by: Aleksandr Panzin
- Posted on: December 15 2008 17:55 EST
- in response to Torben Putkonen
After the annotation is added, it is no longer possible to compile the code without Guice.
Same story with a lot of other things, but there is nothing stopping you from mapping the standard javax.annotations.Resource to act as that @Inject annotation. @Resource could be used instead of @Inject... -
Re: Article tries to downplay effects of annotation[ Go to top ]
- Posted by: Mathieu Carbou
- Posted on: December 15 2008 20:04 EST
- in response to Torben Putkonen
"Some engineers dislike the idea of adding an @Inject to their class. They prefer that a class be totally ignorant of the DI framework. This is a reasonable point, but I'm not convinced by it. As dependencies go, an annotation is pretty mild. The @Inject tag takes on meaning only when you ask Guice to construct your class."
I am not agree... We use Guice a lot (after using Spring a lot) and we find that Guice brings a far better design than Spring for example, and reduce code. For sure you will have @Inject in your code, but with Spring, you also may have @Autowired, InitializingBean, Spring annotations / super classes in your tests, spring super classes for Hibernate of you use the HibernateTemplate, ... Spring may be everywhere in your code. Guice is specialized and it does very well what it is supposed to do: dependency injection. Spring is just a factory for your beans. If you compare the IOC features of both i think Guice is better. 1. Guice forces better design in your code: you can take advantage of package view to limit the visibility of your implementation, that you and only you control and can modify without impact, and just provides interfaces to the public world. With Spring, every bean in the xml must be public. So client code may use directly your implementations (and you must know them to create a spring context). So you often have a public interface along with its public implementation... And you see developers ending up using directly the implementation as declared in spring xml file... 2. @Inject is not intrusive since you choose Guice as your DI framework and you control your implementations. Personally, i prefer writing this in my package org.service public interface Service {void load();} final class MyService { @Inject Dao myDao; // Dao being an interface provided by a module @Inject Provider session; // provides new sessions each time public void load() {session.get(); [...] } } than public final class MyService { // private fields public MyService(Dao dao, SessionFactory session) { // this.XXX = XXX; } public void load() {{session.get(); [...]} } The code in the load() method won't change: what changes is how you instanciate the class and provide dependencies to it. Guice does the job better i think. It does not force you to use traditional getter / setter methods and ctors, and also does not force you to expose you implementation to the public world. With Guice you can do better with fewer code !
This is incorrect. The "@Inject" annotation takes meaning as soon as it is added to the Java code. After the annotation is added, it is no longer possible to compile the code without Guice. Add the annotation and you've injected one more dependency to your project.
Having said that... why do all the articles that praise Guice exclude the import statements from the Java code examples? Embarrassed maybe? -
Re: Article tries to downplay effects of annotation[ Go to top ]
- Posted by: Marc de Kwant
- Posted on: December 16 2008 01:56 EST
- in response to Mathieu Carbou
I have never used this technology but WHY use annotations when you have to write classes like thispublic class HeroModule implements Module { public void configure(Binder binder) { binder.bind(Vehicle.class).to(FrogMobile.class); } } @Inject public FrogMan(Vehicle vehicle) { this.vehicle = vehicle; } public class Adventure { public static void main(String[] args){ Injector injector = Guice.createInjector(new HeroModule()); FrogMan hero = injector.getInstance(FrogMan.class); hero.fightCrime(); } }
Which in my view are just plain old factories. Furthermore I dislike programming something that is clearly configuration and has no business in code. When you want to switch implementation you have to recode this and deploy it. Where with something like Spring you can change your configuration and be done with it. Furthermore I think it is a good practice to be somewhat verbose in coding. It is hard enough to read your own code after a while, let alone someone else. I do not reccommend to hide code use shortcuts just because the programmer is lazy and unwilling to do some work. M2C -
Constructors are preferred (by me anyway)[ Go to top ]
- Posted by: rob bygrave
- Posted on: December 16 2008 18:17 EST
- in response to Mathieu Carbou
Well, I for one would prefer using the Constructor over @Inject on the fields (and I'm pretty sure I read somewhere Bob Lee has this preference as well). The reason being that it can enable you to make the fields final and that has the benefit in terms of the Java Memory Model and concurrency/thread safety. Refer to: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalRight So for me this means the Constructor is by far the preferred method where possible (I'm a fan of final fields where possible) and setter method or field injection the poor cousin. Additionally I'd guess and say those people favoring Constructor injection have more aversion to requiring @Inject - they question why it is needed at all - perhaps there is a good reason for it but it is not clear to me. -
Hmmm... looks like I was wrong ?[ Go to top ]
- Posted by: rob bygrave
- Posted on: December 16 2008 18:55 EST
- in response to rob bygrave
Looks like I was wrong WRT Bob's preference... http://markmail.org/message/fxs5k32dihpoy5ry#query:bob%20lee%20constructor%20injection+page:1+mid:fxs5k32dihpoy5ry+state:resultsI actually shouldn't have mentioned the semantics of final. The important thing is that all injection happens in a single thread, so there are no concurrency concerns w/ field vs. constructor injection. Bob
Hmmm. Rather interesting because in my mind I think of final fields as having the visibility of volatile at construction - but dynamically changing a final field (via reflection) after construction would not quite be the same thing and I wonder if it provides the same visibility?? I wonder why Bob thinks it would? "all injection happens in a single thread" - very interesting... but again this doesn't provide the visibility guarantee that final fields or volatile provides? I must be missing something... -
9.1.1 Post-Construction Modification of Final Fields[ Go to top ]
- Posted by: rob bygrave
- Posted on: December 16 2008 23:04 EST
- in response to rob bygrave
And here it is... http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf 9.1.1 Post-Construction Modification of Final Fields ... Freezes of a final field occur both at the end of the constructor in which the final field is set, and immediately after each modification of a final field via reflection other special mechanism. ... -
Re: Hmmm... looks like I was wrong ?[ Go to top ]
- Posted by: Bob Lee
- Posted on: December 16 2008 23:54 EST
- in response to rob bygrave
Looks like I was wrong WRT Bob's preference...
I strongly prefer constructor injection. That's actually one of the primary reasons I created Guice (other frameworks didn't handle it well). In the rare cases where I do use field injection, I typically don't make the fields final. -
Re: Hmmm... looks like I was wrong ?[ Go to top ]
- Posted by: James Watson
- Posted on: December 17 2008 10:21 EST
- in response to Bob Lee
Is it feasible to use Guice without using field based injection? What are the cases you find you need to use field-based injection?Looks like I was wrong WRT Bob's preference...
I strongly prefer constructor injection. That's actually one of the primary reasons I created Guice (other frameworks didn't handle it well).
In the rare cases where I do use field injection, I typically don't make the fields final. -
Re: Hmmm... looks like I was wrong ?[ Go to top ]
- Posted by: Bob Lee
- Posted on: December 17 2008 12:39 EST
- in response to James Watson
Is it feasible to use Guice without using field based injection? What are the cases you find you need to use field-based injection?
Field injection is useful for pre-constructed objects. I use it when I'm not going to unit test code directly. For example: bind(Foo.class).toProvider(new Provider() { @Inject Bar bar; public Foo get() { ... } }); -
2 cents[ Go to top ]
- Posted by: Leif Ashley
- Posted on: December 15 2008 09:49 EST
- in response to Ryan Taylor
You know, I'm going to eventually get the name "2 cent" on here. Anyway, having used Seam/EJB this time around for a client, I have to say I'm not all that impressed with DI. It's more to learn, you have to pay close attention to what you're doing just to make it work at all, it makes testing quirky since it's all "in container", and it just doesn't buy you much. By all means, if there's something DI gives me other than "my object", then let me know. It's like worst of bother worlds: little value and the rest of your java code moves closer to an in-container solution. So testing is a PITA as well. Anyone else feel this way? -
No edit?[ Go to top ]
- Posted by: Leif Ashley
- Posted on: December 15 2008 09:51 EST
- in response to Leif Ashley
Words of wisdom here are to proof read you post before hand. Hey, it's Monday and starbucks hasn't kicked in. lol -
I agree[ Go to top ]
- Posted by: Bj??rn Caroll
- Posted on: December 15 2008 10:55 EST
- in response to Leif Ashley
If you make your code independent of the framework then you just move the problem into your XML file. The XML file will be dependent on your Java code and if you make changes to your code then you have to remember to change your XML, which is not statically typed. This way of creating programs are bad. For some reason many seems to think that if you program in XML all problems goes away. If you use the annotation strategy it is just as flexible and more straight forward to use a factory.