20070320 Tuesday March 20, 2007

Guice vs. Spring JavaConfig: A comparison of DI styles

With all of the excitement surrounding Guice lately, I thought it might be worthwhile to compare Guice with Spring JavaConfig. Both represent different approaches to annotation-based dependency-injection. I've chosen to reimplement my knight/quest example from chapter 1 of Spring in Action to illustrate the basics of each option.

Before I get started, a few disclaimers:

As the author of Spring in Action, it should be no surprise to you that I will have a difficult time being unbiased. Therefore, I will make no pretense of impartiality. However, I will do my best to be as fair as I can be to both Guice and Spring JavaConfig. As someone who has several years of Spring experience to match his few days of Guice experience, I will admit that my knowledge of Guice isn't up to par with my knowledge of Spring. Therefore, it is quite possible that there are things about Guice that I simply do not know about and have not taken advantage of in my comparison. I assure you that failure to use the best possible Guice technique is not meant to devalue Guice, but merely due to the fact that I'm not as experienced as Guice as I am with Spring. For what it's worth, while I have several years of Spring experience, I'm still relatively new to Spring JavaConfig. This is only a comparison of Guice with Spring JavaConfig, the core Spring container, and (to a lesser degree) Spring AOP; it is not a comparison of Guice to the entire Spring Framework. The Spring Framework is much more than just its core dependency injection container, providing functionality that Guice does not provide or claim to provide. My comparisons will with Guice 1.0, Spring JavaConfig 1.0-m1, and Spring 2.0.2.

With that out of the way, let's get started. Since Spring is the hometeam in this matchup, I'll let Guice take the field first.

A Knight's tour of Guice

In Guice, much of the configuration is done in the context of a module class. This class effectively binds classes to interfaces within the Guice injector, so that Guice knows how to resolve certain dependencies. Here's what the KnightModule class that I wrote looks like:

package com.springinaction.chapter01.knight; import static com.google.inject.matcher.Matchers.annotatedWith; import static com.google.inject.matcher.Matchers.any; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Scopes; public class KnightModule extends AbstractModule { public void configure() { bindConstant().annotatedWith(Name.class) .to("Bedivere"); bind(Knight.class).to(KnightOfTheRoundTable.class) .in(Scopes.SINGLETON); bind(Quest.class).to(HolyGrailQuest.class) .in(Scopes.SINGLETON); bindInterceptor( any(), annotatedWith(MinstrelIntercepted.class), new MinstrelInterceptor() ); } public static void main(String[] args) throws Exception { Injector injector = Guice.createInjector(new KnightModule() ); Knight knight = injector.getInstance(Knight.class); knight.embarkOnQuest(); } }

(Note that for space considerations I'm only going to show the code that is pertinent to the comparison of Guice with Spring JavaConfig. The full source code for the Guice examples will be available here, while you'll be able to find the Spring JavaConfig examples here. Also notice that I've placed the main() method in KnightModule for convenience only--you may or may not want to do this in a real-world application.)

The first thing you'll see is the configure() method. This method, which is mandated by the AbstractModule class, is used for, among other things, binding interfaces to an implementation classes. This is important, because in Guice, you do not explicitly wire objects together--instead you declare that a property, constructor argument, or even a method argument needs to be injected and Guice will automatically (or semi-automatically, to be more accurate) find an implementation to match the property or argument.

For example, notice that the Knight interface is bound to the KnightOfTheRoundTable class. What this is basically telling Guice is that anytime it needs to inject a property or argument that is of type Knight, it should use the concrete KnightOfTheRoundTable implementation. Similarly, the Quest interface is bound to the HolyGrailQuest class. Thus when KnightOfTheRoundTable needs its quest property wired with a Quest implementation, Guice will oblige with a HolyGrailQuest.

Along with being wired with a Quest implementation, the KnightOfTheRoundTable class is also constructed with a String value that is the knight's name. Unfortunately, I could find no more straightforward way of wiring a String value into KnightOfTheRoundTable's constructor without binding the value through an annotation. Thus, the call to bindConstant() tells Guice to inject the value "Bedivere" into any String that is annotated with @Name (which is a custom annotation that I created as an "anchor" to bind the String injection to).

In the case of both the Quest and Knight bindings, the in() method is called to set the scoping of the bean to be singleton. Optionally, you can leave this out and instead place a @Singleton annotation on the KnightOfTheRoundTable and HolyGrailQuest classes. However, for reasons I'll describe later in this article, I don't particularly recommend the @Singleton annotation.

I'll come back to the call to bindInterceptor() in a moment. But first, it's important to know that KnightModule only tells Guice about the objects and values that it is to inject. It doesn't say where to inject them. For that, I had to place annotations in the KnightOfTheRoundTable class. Here's the modified KnightOfTheRoundTable.java:

package com.springinaction.chapter01.knight; import com.google.inject.Inject; public class KnightOfTheRoundTable implements Knight { private String name; private Quest quest; @Inject public KnightOfTheRoundTable(@Name String name) { this.name = name; } public Object embarkOnQuest() throws QuestFailedException { return quest.embark(); } @Inject public void setQuest(Quest quest) { this.quest = quest; } public String getName() { return name; } }

Notice the use of the @Inject annotation on both the constructor and the setQuest() method. This annotation tells Guice that it needs to inject some values into the arguments of the constructor and method that it annotates. Without this annotation in place, Guice will pass over those methods and not perform any injection at all.

First look at the setQuest() method. It is annotated with @Inject and has a Quest argument. As you'll recall, Quest is bound to HolyGrailQuest. Therefore, when Guice is configuring the KnightOfTheRoundTable object, it will call setQuest(), passing in a reference to a HolyGrailQuest object.

It should also be noted that although this example doesn't show it, Guice can also inject into any method, not just setters and constructors. So, even if the setQuest() method were renamed to giveMeAQuestPlease(), Guice would still call it, passing in a HolyGrailQuest object.

Also, instead of explicitly binding Quest to HolyGrailQuest in KnightModule.java, I could've used the @ImplementedBy annotation in Quest.java to bind HolyGrailQuest to Quest. For example, here's the Quest interface, annotated with @ImplementedBy:

package com.springinaction.chapter01.knight; import com.google.inject.ImplementedBy; @ImplementedBy(HolyGrailQuest.class) public interface Quest { public Object embark() throws QuestFailedException; }

The @ImplementedBy annotation is effectively equivalent to the bind() call I used in KnightModule. The difference is that it sets up Quest to be bound to a default implementation class, should one not be bound to Quest in KnightModule.

Now look at the constructor. It is also annotated with @Inject. And it has a String argument that is annotated with @Name. The @Inject argument tells Guice that the constructor must be injected, while the @Name annotation (a custom annotation that I created to help this example along) helps Guice know what to inject it with. Back in the KnightModule class, we bound the String value "Bedivere" to the @Name annotation. Therefore, when KnightOfTheRoundTable is constructed, it will be constructed with the argument being set to "Bedivere".

Guice and AOP

At this point you've seen the basics of Guice injection. Now let's see how Guice does AOP.

First, I implemented the MinstrelInterceptor as an AOP Alliance MethodInterceptor:

package com.springinaction.chapter01.knight; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class MinstrelInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation mi) throws Throwable { Knight knight = (Knight) mi.getThis(); System.out.println( "La la la, Sir " + knight.getName() + " is so brave!"); Object rtn = mi.proceed(); System.out.println("" + "Tee-he-he, he did " + mi.getMethod().getName()); return rtn; } }

Then, back in KnightModule.java, I had to bind the interceptor:

bindInterceptor( any(), annotatedWith(MinstrelIntercepted.class), new MinstrelInterceptor() );

This effectively binds the MinstrelInterceptor to all methods that are annotated with @MinstrelIntercepted (another custom annotation) on all types ("any()"). I couldn't find any more straightforward way to create a "pointcut" other than to create a custom annotation and to bind the interceptor to it.

With the interceptor bound to @MinstrelInterceptor (on both types and methods), I had to change the KnightOfTheRoundTable to use the @MinstrelIntercepted annotation on the embarkOnQuest() method:

@MinstrelIntercepted public Object embarkOnQuest() throws QuestFailedException { return quest.embark(); }

With the embarkOnQuest() method annotated and MinstrelInterceptor bound to the @MinstrelIntercepted annotation, any call to a KnightOfTheRoundTable's embarkOnQuest() method will result in the minstrel singing about the knight's exploits.

And that is, in a nutshell, how I implemented the knight/quest example using Guice. Again, the full source code for this example is available for download here.

Now let's see how I did the same thing using Spring JavaConfig.

A Knight's tour of Spring JavaConfig

Like Guice, Spring JavaConfig enables you to configure an application's objects in Java code using annotations. But their approaches to dependency injection are vastly different.

To get started, I needed to create a configuration class. In Spring JavaConfig, any class that is annotated with @Configuration can serve as a JavaConfig configuration. Here's the knight example's KnightConfig.java:

package com.springinaction.chapter01.knight; import org.springframework.beans.factory.annotation.Bean; import org.springframework.beans.factory.annotation.Configuration; import org.springframework.beans.factory.annotation.SpringAdvice; import org.springframework.context.ApplicationContext; import org.springframework.context.java.AnnotationApplicationContext; @Configuration public class KnightConfig { @Bean public Knight knight() { KnightOfTheRoundTable knight = new KnightOfTheRoundTable("Bedivere"); knight.setQuest(quest()); return knight; } @Bean public Quest quest() { return new HolyGrailQuest(); } @Bean @SpringAdvice("execution(* *.embarkOnQuest(..))") public MinstrelInterceptor minstelAdvice() { return new MinstrelInterceptor(); } public static void main(String[] args) throws Exception { ApplicationContext ctx = new AnnotationApplicationContext(KnightConfig.class); Knight knight = (Knight) ctx.getBean("knight"); knight.embarkOnQuest(); } }

(Again, I've placed the main() method in KnightConfig as a convenience. You may or may not want to do this in a real-world application.)

At first glance, you may think that KnightConfig is analogous to the Guice example's KnightModule. It's true, that both serve as the central configuration artifact for both resources. But take a look a little closer and you'll see that they're quite different. More specifically, KnightConfig is more explicit in its configuration than the Guice example's KnightModule.

For example, notice the first method in KnightConfig is simply called knight() and it returns a Knight. This method is annotated with @Bean and is, in fact, the complete set of instructions for how Spring JavaConfig should create and inject a bean named "knight" in the Spring container. In short, it will create a new instance of KnightOfTheRoundTable, passing in "Bedivere" as its constructor argument. Then it will call the setQuest() method to wire a Quest into the quest property. The actual quest used is a reference to the quest() method.

Similarly, the quest() method is also annotated with @Bean and simply returns an instance of HolyGrailQuest.

The method names give the bean its ID, while the value returned is the type. Everything that happens in the method defines how the bean is configured. Therefore, taken together, the knight() and quest() methods are roughly equivalent to the following Spring XML configuration:

<bean id="knight" class="com.springinaction.chapter01.knight.KnightOfTheRoundTable"> <constructor-arg value="Bedivere" /> <property name="quest" ref="quest" /> </bean> <bean id="quest" class="com.springinaction.chapter01.knight.HolyGrailQuest" />

I should also mention that because all of the configuration takes place directly in Java code, it's quite easy to inject references into regular methods...not just constructors and setters. Similarly, it's no problem to add conditional and looping logic in your configuration, which is something that pure Spring XML cannot do.

It's also important to realize that Spring JavaConfig is not mutually exclusive to Spring XML configuration. You can easily use both in the same application by configuring the @Configuration-annotated classes as beans in Spring XML and then wiring an org.springframework.beans.factory.java.ConfigurationPostProcessor in your Spring XML. In trying to create an XML-free example, however, I've not exploited the mix-n-match of JavaConfig with XML here.

And, in case you're wondering, Spring's special wiring features, such as autowiring, lazy-loading, init-methods, etc, are all still available as attributes to the @Bean and @Configuration annotations. It's beyond the scope of this article to go into any great detail, but the knight() method could be redefined as follows to be autowired by type:

@Bean(autowire=Autowire.BY_TYPE) public Knight knight() { KnightOfTheRoundTable knight = new KnightOfTheRoundTable("Bedivere"); // no need to wire in a Quest...it'll be auto-wired return knight; }

As with the Guice example, I'll come back to see how the minstrel advice is wired in. First, however, let's see what else needs to be done with KnightOfTheRoundTable and HolyGrailQuest for Spring JavaConfig to wire them together.

Oh wait...actually, there's nothing special that needs to be done with either of those classes. They're perfectly suitable for wiring with Spring JavaConfig, just as they would be using Spring XML. Unlike Guice, Spring JavaConfig keeps its annotations confined to the configuration classes. So I guess I can go ahead and talk about how to use AOP with Spring JavaConfig.

Spring JavaConfig and AOP

The minstrelAdvice() method is similar to the knight() and quest() methods in that it wires a MinstrelAdvice object into the Spring container. But what makes it special is its @SpringAdvice annotation. This annotation tells Spring JavaConfig that the bean configured in the method is actually AOP advice that implements one of Spring's advice interfaces (such as MethodBeforeAdvice or even AOP Alliance's MethodInterceptor). In fact, because the Guice example's MinstrelInterceptor implements the AOP Alliance MethodInterceptor class, it's perfectly suitable for reuse in the Spring JavaConfig example!

The @SpringAdvice annotation takes a pointcut expression as its value attribute. Here I'm using an AspectJ-style pointcut expression to indicate that I want the advice applied to the execution of the embarkOnQuest() method on any class.

And that ends our examination of Spring JavaConfig as applied to Spring in Action's knight/quest example. The full source code for the Spring JavaConfig example can be found here.

Conclusions

Both Guice and Spring JavaConfig offer interesting alternatives to the sometimes verbose XML used to configure many frameworks (including Spring). Each, however, takes a different approach to configuration. Let's examine how they stack up against each other:

String identifiers - One complaint against Spring's XML configuration is the use of String identifiers and the lack of refactorability therein. It's true, that Spring's XML configuration is heavy with references to classes, properties, and other beans that are merely String values and thus difficult to refactor without a proper tool (such as the SpringIDE for Eclipse). Fortunately, both Guice and Spring JavaConfig register a win in this category, as neither relies on String identifiers in their configuration and both are easily refactorable through modern IDEs. Speed/Performance - Guice bills itself as faster than other containers when performing dependency injection. While I didn't run any formal benchmarks to compare Spring JavaConfig and Guice, some informal tests proved Guice's claims to be true. This is not terribly surprising, however, as Spring defines a rich set of lifecycle events around the creation of beans in the container, while I could not find any comparable lifecycle built into Guice. Without the overhead of the lifecycle events, Guice does, in fact, wire up the beans much faster than Spring. JAR file footprint - The Guice example above only requires two JAR files: guice-1.0.jar and aopalliance.jar. Together, these two JAR files weigh in at just over half a megabyte. Meanwhile, the Spring example requires several JAR files, including spring-javaconfig.jar, spring-beans.jar, spring-aop.jar, spring-core.jar, spring-context.jar, commons-logging.jar, aopalliance.jar, asm-2.2.2jar, cglib-nodep-2.1_3.jar, and aspectjweaver.jar, together weighing in at several megabytes in size. So, Guice is more lightweight than Spring in terms of JAR file footprint. Non-intrusive - Both Spring JavaConfig and Guice rely on proprietary annotations to help them do their injections. Where they differ, however, is that Guice requires placement of @Inject annotations withing the injected application classes, while Spring JavaConfig confines its use of annotations to the configuration-specific classes. Consequently, Guice-injected classes cannot be reused and compiled in a separate application without the Guice JAR file in place. Meanwhile, Spring JavaConfig leaves the application classes unaltered, enabling their unhindered reuse. Thus, in this category, Spring JavaConfig is the clear winner. (Granted, Spring does define a handful of annotations to be placed in application classes--@Required and @Transactional come to mind. But their use is not mandated to configure Spring.) Third-party beans - Related to the last category, I could find no direct way to inject values into a third party class using Guice. Guice-style injection requires the use of the @Inject annotation, which is useless in classes for which I do not have the source code (or classes that I do not wish to annotate with @Inject). Guice's documentation indicates that third-party components will require the creation of a custom provider, but in my opinion, this is a hack that adds complexity to something that would be very simple if the @Inject annotation were not required. Spring JavaConfig, however, keeps the configuration separate from the application classes, thus wiring a third-party class in Spring JavaConfig is no different than wiring a custom class. Spring wins again. Constant/literal injection - Injecting a String literal (or any other type of literal value) in Spring JavaConfig is rather straightforward. In contrast, literal injection in Guice is cumbersome, requiring the creation and use of a custom annotation to identify where the literal should be injected. Spring JavaConfig wins this category. AOP - The Guice documentation acknowledges that Guice's flavor of AOP is less powerful than Spring AOP (both of which are much less powerful than AspectJ). But, the Guice documentation claims that this loss of AOP power is in trade for simplicity. Honestly, I found Guice's approach to AOP (binding interceptors) non-intuitive as compared to Spring JavaConfig. The Spring JavaConfig approach required only a simple annotation with an AspectJ-style pointcut expression, whereas Guice required a confusing binding call involving "matchers" to pick out the target of the interceptor. Maybe I'm too well-versed in Spring AOP to appreciate the simplicity of Guice's interceptor-binding...but for now I must give Spring the win in this category.

Final score: Guice - 3, Spring JavaConfig - 5.

I'm glad that I spent the time to learn a little about Guice, but I'm not all that "juiced" about using Guice. In addition to all of the reasons given above, I'd much rather build my application against a well-established container like Spring that has a wealth of integration points with other frameworks and APIs (Guice only has integration with Struts 2 and Spring, as far as I can tell). Also, to be clear, Guice really doesn't compete with Spring as much as it competes with Spring's application context--Spring's capabilities go beyond dependency injection and AOP.

Also, one more comment on the speed issue: I've given Guice a point in that category, simply because my quick-n-dirty tests confirmed that Guice was faster. But, I've seen a few more detailed performance tests run by others that show that while Guice is faster in creating prototype beans, Spring is faster in creating singletons. Given that singletons are more typically used than prototypes, Spring should probably get the point in this category. But since I have not taken the time to provide the evidence, I'll go ahead and give this one to Guice.

(I'm sure that you're wondering where the numbers are that show Spring is faster in producing singletons. Unfortunately, the work done to produce these numbers is not mine and I am not sure if the author is ready to release his figures yet. If he's reading this, then he knows I'm talking about him here and I ask him to provide the numbers on his blog. When/if he does that, I'll put the link to his blog here.)

Again, let me repeat that I've had only a few days worth of experience with Guice as compared to a few years of experience with Spring. If there's a change that can be made to the Guice examples to make them better and to provide a more fair comparison, I'm eager to hear about it.

Special thanks to Crazy Bob for his gracious offer to review my Guice example. He pointed out a few things about my example that could've been done a bit better. He also suggested moving the ".in(Scopes.SINGLETON)" part of the binding into the HolyGrailQuest and KnightOfTheRoundTable classes as a class-scoped @Singleton annotation. I chose not to do this, because it would be one more intrusion of Guice into my application objects. Finally, Bob wanted me to mention that Guice really shines when you use a dependency more than once (in the knight/quest example, the Quest dependency was only used once).

Thanks also go to Rod Johnson, Colin Sampaleanu, and Costin Leau for going over the Spring JavaConfig bits and providing their feedback. Rod suggested that I mention that the @AspectJ advice style is way nicer than the AOP Alliance stuff (which is basically a legacy programming model in Spring 2.0). I fully agree that the @AspectJ stuff is pretty slick and I recommend it over the AOP Alliance stuff. I only used the AOP Alliance stuff here to provide a slightly more even playing field. (Although, in hindsight, an @AspectJ example would've been a slam-dunk in Spring's favor.)

Finally, and before I get pointless comments to this effect: I realize that a "Knight's Tour" is a series of 64 moves by a knight piece on a chess board, where the knight visits every square once and only once. Had I given an actual "knight's tour" of Guice and Spring, my examples would've been more comprehensive (covering at least 64 points). I know the phrase isn't a perfect fit here, but it sounds cool, so I'm keeping it. :-)

And, in case you didn't catch those download links earlier, you can find the Guice example code here and the Spring JavaConfig example code here.

(2007-03-20 00:00:00.0) Permalink Comments [45]
Comments:


I've never been the first to comment on my own blog entries...but here I go...

Chris Tam points out another oddity about Guice, requiring multiple custom annotations to handle the case where you have multiple implementations of a single interface to be injected: http://www.xeniumhk.com/blog/?postid=66. Very astute observation Chris.

Posted by 216.87.145.186 on March 20, 2007 at 04:35 PM EDT #

I still say that xml config is the winner. I do not like the Java annotation based DI style. I really dig the xml config file style DI. The benefit of it doing the wiring and acting as a great piece of documentation for the system can't be beat.

Erik

Posted by Erik Weibust on March 20, 2007 at 05:11 PM EDT #

Erik: Don't panic! You and I are still on the same page WRT Spring XML. I prefer the XML style, too...it's great for running through an XSLT template to produce documentation and GraphViz DOT files! But since everybody out there is bagging on Spring XML lately, I wanted to explore an XML-free alternative.

Posted by Craig Walls on March 20, 2007 at 05:36 PM EDT #

I was one of the Spring-XML bashers (the word is too strong, but i dont know a better one), but i am not using Guice but Spring, of course with XML. I was of course not complaining about refactoring problems or something because i am using IDEA which is a no-brainer for Spring XML WRT refactoring, it was more a general complaint that if you really have a lot of bean, it feels cumbersome to edit all this stuff.

But thanks to your work craig, i got a fast start into configuring both frameworks in java and i must say this dont impress me too much either :) The implementedBy approach on the other hand is quite neat. But as i said, this dont impress me that much that i will instantly go away from XML configuration. Perhaps i just have to admit that big applications will have a large part of wiring informations, no matter how they are defined.

Posted by Marc Logemann on March 20, 2007 at 06:27 PM EDT #

Very nice overview, Craig.

I do think you're drawing too many conclusions from too small of a sample. This is analogous to performance tuning: you should worry about the overall scalability, not micro-optimizations. In the Real World, you use dependencies much more often (M) than you define them (N). If Spring were an O(N*M) solution, Guice would be an O(N) solution. Guice and Spring appear to be 1:1 in your example because M = 1.

In more concrete terms, let's say that instead of using Knight just once as you did, you use Knight in 50 different web actions. With Spring's JavaConfig, do you have to define 50 @Bean methods, one for each action? With Guice, you just put @Inject anywhere you need a Knight.

You mentioned auto-wiring, but we both know that isn't a viable option in cases like this.

Erik Burke experienced this first hand in his port from Spring to Guice (http://stuffthathappens.com/blog/2007/03/09/guicy-good/): "At the end of the day, I compared my [Guice] modules ? written in Java ? to my Spring XML files. The modules are significantly smaller and easier to read. Then I realized about 3/4 of the code in my modules was unnecessary, so I stripped it out. They were reduced to just a few lines of code each."

Also, the type checking within a Spring JavaConfig class is nice, but what about the integration between such classes when you have many of them? Guice may be a "lighter" framework, but it's actually geared toward bigger applications where you have many independent modules with various interdependencies. As your Guice application gets bigger, you can easily reorganize modules and move bindings around. Is the same true for moving bean definitions between Spring JavaConfigs?

The Spring AOP support is "cool" if you're a framework developer, but not really practical. I think if you talk to anyone who uses Spring AOP, they'll cite one use case: applying @Transactional to a method to make it transactional.

Guice encourages matching interceptors to annotations as it's the most maintainable pattern (compared to matching methods by name as you did). Most developers shouldn't have to worry about binding interceptors to methods. Binding an interceptor is a one time effort for which you can largely cut and paste the code. All developers have to know is to apply annotations to methods to get the services they want.

Finally, I put your "singleton performance" claim to the test. Guice returned singletons 5X as fast as Spring. If you want to try it yourself, I just tweaked the PerformanceComparison class in Guice's test directory to use a singleton.

The best advice I can give to anyone evaluating a new tool is, examples this small are never sufficient. We constantly prototype small but real features when evaluating tools, and it's funny to see which intial assumptions hold water and which fall apart.

Posted by Bob Lee on March 20, 2007 at 06:52 PM EDT #

I also have a slightly interesting anecdote: in the very early days, Guice looked very much like Spring's JavaConfig, which isn't surprising considering Rod showed me Spring's JavaConfig almost a year ago (and I showed him Guice about 6 months ago). Just like with JavaConfig, you wrote explicit Java code to wire your objects. I originally introduced @Inject as an optional way to double-check that the external code called all your setters as expected. Once we had @Inject, I asked, why do we need to write explicit wiring code at all? Shortly thereafter, we had the Guice you all know today.

Posted by Bob Lee on March 20, 2007 at 07:10 PM EDT #

Bob Lee>> In the Real World, you use dependencies much more often (M) than you define them (N). If Spring were an O(N*M) solution, Guice would be an O(N) solution. Guice and Spring appear to be 1:1 in your example because M = 1.

Bob Lee>> In more concrete terms, let's say that instead of using Knight just once as you did, you use Knight in 50 different web actions. With Spring's JavaConfig, do you have to define 50 @Bean methods, one for each action? With Guice, you just put @Inject anywhere you need a Knight.

In The Real World, the reason we have interfaces is so that when we need to we can plug in different versions of those interfaces, often in the same application. And so when we write one piece of code that works against an interface, it doesn't have to concern itself about how another completely unrelated piece of code (perhaps not yet even written) may use that same interface.

As Chris Tam points out, the whole Guice model completely (totally) breaks down when you start needing to inject different versions of an interface.

So yes, this is pretty simple:

@Inject
public void setService(Service myService);

and I can have one simple bind statement in Guice to handle this.

But now in another module I need a Service too. So I do this

@Inject
public void setService(Service myService);

But wait, this guy needs another version of Service! And I have to know this fact in each actual piece of code that needs to be injected. Every piece of code I write anywhere that needs to be inject with a service, needs to know whether it should ask for a generic service:

@Inject
public void setService(Service myService);

or make the decision, "I probably need a special version of service", so I'm going to do this:

@Inject
public void setService(@MyMarkerAnnotation Service myService);

But wait. Now do I need to inject the same special Service as that other code I shouldn't know about but actually do have to now know about (to make this decision), or do I play it safe and make another special marker annotation?

@Inject
public void setService(@MyOtherMarkerAnnotation Service myService);

And soon I wind up not with one bind statement to handle the injection of Service, but "x" bind statements, one for each marker.

Add to this the fact that Guice can not inject into existing code...

Add to this that this is quite invasive...

... and we have a broken dependency injection model.

Colin

Posted by Colin Sampaleanu on March 20, 2007 at 07:37 PM EDT #

Colin, following your logic, even though you only need multiple implementations of a type roughly 10% of the time (that's being generous), you need to write explicit wiring code 100% of the time.

Binding annotations work quite nicely in practice. They describe what the client needs. For example, you can use @ReadOnly and @Secure to describe a DataSource.

You say, "add to this the fact that Guice can not inject into existing code," but I've already explained that you can write custom providers in Guice and wire objects manually. A custom provider is a little more verbose than an @Bean method in a Spring JavaConfig, but luckily you don't do this often, so Guice comes out ahead overall.

Guice does have a sweet spot with application development where you have the ability to go back and apply/change annotations. If you have a lot of third party classes which don't fall into this category, you can either write custom providers or you can use Spring to wire them up--Guice plays very nicely with it.

Posted by Bob Lee on March 20, 2007 at 08:48 PM EDT #

Many interesting comments from Bob and Colin. I'll wait awhile for these thoughts to sink in before I respond. But, I wanted to go ahead and respond to a few things Bob said.

First, the singleton performance claims were not mine, as I stated in the article. I was just repeating what I've been told and I invite the original author of those claims to present his findings. But, as they were not my own tests, I was sure to give the appropriate disclaimers.

Second, your comments on short example vs. large example are well taken. Unfortunately, due to space constraints and time, I only had the time to attack Guice and JavaConfig on a smaller scale. But I accept your challenge and, when time frees up (lots going on here, so it may be a month or more), I will find an example of reasonable size, repeat the experiment, and post my findings here. In the meantime, I invite anyone else (perhaps Erik Burke) to blog their own comparison giving *details* on how Guice compares to Spring. I, for one, would be interested in reading anything from anyone on either side of the argument.

Posted by Craig Walls on March 20, 2007 at 09:46 PM EDT #

I want to comments on an AOP-related point Bob mentioned:
Bob> The Spring AOP support is "cool" if you're a framework developer, but not really practical. I think if you talk to anyone who uses Spring AOP, they'll cite one use case: applying @Transactional to a method to make it transactional.

That is indeed how most get started with Spring AOP. However, after initial learning period, many recognize the real power and flexibility of AspectJ pointcut expression. It opens up a whole set of possibilities. Here are a few examples from real projects:

1. Monitor access to sensitive data: In Spring, using the AspectJ integration (still based on proxies, and not the AspectJ weaver), it is trivial to write a pointcut expression such as execution((@Sensitive *) *(..)) to select any method that declares to return a type marked with the @Sensitive annotation. Then I can write a simple aspect such as the following:

<div class="code">
@Aspect
class SensitiveAccessMonitoring {
@Pointcut(?execution((@Sensitive *) *(..))?)
public void sensitiveAccess() {}

@AfterReturning(value=?sensitiveAccess()? returning=?sensitiveObj?)
public void monitor(Object sensitiveObj) {
?
}
}
</div>

Then all I have to do is to annotate sensitive classes with @Sensitive annotation, such as:

<div class="code">
@Sensitive
public class MedicalRecord {
?
}
</div>

Don?t like annotations? Prefer interfaces instead (such as, MedicalRecord implements SensitiveDocument)? No problem. Just modify the pointcut as follows:

<div class="code">
execution(SensitiveDocument+ *(..))
</div>
Know that all classes in the domain.confidential package must be treated as sensitive? No problem there either:

<div class="code">
execution(domain.confidential.* *(..))
</div>

In each case, the flexible pointcut expression language allow me to focus on problem and works with my style.

2. Sanitize data obtained through external untrusted sources before usage: The same story here. I decide how untrusted data is marked (annotation, interface, package structure, naming convention); framework doesn?t dictate anything here.

Let?s say, I decided to use an interface ? Untrusted. Now I can use an aspect such as the following:

<div class="code">
@Aspect
public class SanitizeUntrustedData {
@Pointcut(?execution(* service..*(..)) && args(untrusted)?)
public void untrustedDataUsage(Untrusted untrusted) { }

@Before(?untrustedDataUsage(untrusted)?)
public void sanitize(Untrusted untrusted) {
use untrusted object?
}
}
</div>

Notice, btw, how the advice is type-safe i.e. uses specific Untrusted type instead of potentially problematic Object.

I can cite many more examples such as these. In each case, the key difference is that methods themselves do not provide any selection criteria (as would be the case for @Transactional). Instead, the context involved determines selection.

How would you express the same things in Guice?

Posted by Ramnivas Laddad on March 20, 2007 at 10:44 PM EDT #

Bob,

You talk about a 10% ("being generous") of the time that you need multiple implementations of an interface, but essentially downplay or sidestep the fact that you do not know this ahead of time, and people in practice do not wish to go back and modify existing working code with special marker annotations, or may not even have a choice in the matter. I find it absolutely crazy that I may have a codebase with 500 (or whatever) classes in it, and at some point I want to introduce some polymorphism somewhere (the reason I was using interfaces in the first place), and now I have to go dig up all the code using generic @Inject tag and stick in marker annotations of some sort.

But this is not all of it. Your mention of DataSource is actually a perfect example to show a number of issues with the Guice approach.

I've actually seen quite a number of apps where multiple DataSources were needed.

Now the average DAO in such an app doesn't give a flying you know what about which DataSource it's using. It works with whatever DataSource it's injected with and doesn't care and shouldn't care if other DAOs use other DataSources. So another DAO may use the same DataSource or a completely different one. And in some cases, multiple instances of the _same_ DAO class are actually created and wired to different DataSources.

So to handle the first issue (two different DAO classes need two different DataSources), I either have to work with generic @Inject and accept that I have to go back later and qualify them with special annotations, or else put in those annotations from the beginning. Not great either way...

Now what about multiple instances of the same DAO class with different DataSources injected into each. And really, this is not about a narrow example like DAOs and DataSources. The reality is that in OO programming, when using the Strategy pattern, it's pretty common to have multiple instances of one class with different implementations of a strategy injected into it. Probably one of the best justifications for using interfaces, after all. How do you handle this? Well with Guice, you would theoretically have to build some sort of custom provider for that interface (i.e. the DataSource). And on top of that you have to give it enough contextual information so it can make the decision on which DataSource it builds. But this is actually pretty hard, because your custom provider is _still_ bound to the target location via only an interface binding. Look at this:

MyDao:

public class MyDao {
@Inject
public MyDao(DataSource ds) { ... }
...
}

Now I have two instances of this that I need to inject. What am I supposed to do here? What about if I make a custom Provider which grabs something from Jndi (a DataSource in this case), and we'll make it able to get the right DataSource. So here is a first cut (straight from the Guice users guide):

class JndiProvider<T> implements Provider<T> {

@Inject Context context;
final String name;
final Class<T> type;

JndiProvider(Class<T> type, String name) {
this.name = name;
this.type = type;
}

public T get() {
try {
return type.cast(context.lookup(name));
}
catch (NamingException e) {
throw new RuntimeException(e);
}
}

/**
* Creates a JNDI provider for the given
* type and name.
*/
static <T> Provider<T> fromJndi(
Class<T> type, String name) {
return new JndiProvider<T>(type, name);
}
}

Now I need to go through the steps of hooking this up:

// Bind Context to the default InitialContext.
bind(Context.class).to(InitialContext.class);
// Bind to DataSource from JNDI.
bind(DataSource.class)
.toProvider(fromJndi(DataSource.class, "java:comp/env/whatever/myDataSource"));

But wait, what have I done here? All I've done is the equivalent of a Spring FactoryBean, but (after all this work) this is statically bound to provide the same DataSource from the same location into all objects that ask for DataSources.

So tell me how I'm supposed to use this mechanism to get different DataSources into two instances of the same class that needs a DataSource? We need some context to make a decision here, and no way to provide it. The binding is static after all, with only two things being used to make the decision, the target interface that needs to be produced (DataSource), and an optional marker annotation at the injection point. The latter is of no use here since it's the same class I'm injecting into after all.

Now I may be missing something here, but even if I'm not, I presume Guice would try to add some mechanism to introduce dynamic context, so a Provider can find out "something" about the context under which it's supposed to provide DataSource, and make a dynamic decision. But really, what is there to work with? All Guice knows is the target interface being requested (invariant), an optional annotation on that (no use since it'd be invariant since it's the same class being injected into), and the class being injected into (invariant). There is nothing similar to a Spring "bean", a bag of metadata about one particular (scoped) configuration of a class, allowing you to very trivially configure one instance of a class (needing a DataSource) different from another instance of the same class (needing a DataSource). To talk about "this" and "that" version of class X.

We could try to inject a custom Provider and make the decision at run-time:

public class MyDao {
@Inject
public MyDao(Provider<DataSource> dsFactory) { this.dsFactory = dsFactory; }
...
public someDaoMethod() {
DataSource ds = dsFactory.get();
}
}

But this doesn't change much. We have no context on which to make a decision, except perhaps a ThreadLocal, in no way a generally viable solution.

So how does the Spring case look?

In XML first

<jee:jndi-lookup id="dataSource1" jndi-name="java:comp/env/whatever/myDataSource1"/>
<jee:jndi-lookup id="dataSource2" jndi-name="java:comp/env/whatever/myDataSource2"/>

<bean id="dao1" class="...">
<constructor-arg ref="dataSource1"/>
</bean>

<bean id="dao2" class="...">
<constructor-arg ref="dataSource2"/>
</bean>

Now the Java Variant:

@Bean
public dataSource1() {
return new JndiTemplate().lookup("java:comp/env/whatever/myDataSource1" }
}

@Bean
public dataSource2() {
return new JndiTemplate().lookup("java:comp/env/whatever/myDataSource2" }
}

@Bean
public dao1() {
return new MyJpaDao(dataSource1());
}

@Bean
public dao2() {
return new MyJpaDao(dataSource2());
}

That's not so hard... Of course the DataSource beans could be inlined in both the XML and Java variants. They are broken out here since there would probably be multiple users of them.

Now Bob, what about your statement that it's possible to write custom providers in Guice and wire objects manually, in reply to my statement that Guice can not inject into existing code?

I stand by this, to the extent that Guice becomes pretty cumbersom when trying to work with existing code. I can write a custom Provider to produce and inject an object, but things now become much more verbose and I am bypassing the normal Guice ways of doing things. So if my third party class needs 2 constructor arguments and 3 setter method arguments, I need to make a custom Provider, inject the provider itself with those 5 arguments, in the provider create the class instance, and manually inject the values. I also no longer have field injection available to me. And I have to register the Provider. At this point you are much more verbose than Spring Java Config (you need a special class for each object you want to build/inject, not a method, plus have to register the binder), and we still have all the other issues with no context to make dynamic decisions on a per instance basis.

Colin

Posted by Colin Sampaleanu on March 20, 2007 at 11:49 PM EDT #

Hi guys,

Bob is definitely right with his point that different interface implementations are not too common. I checked our code base and we dont reach 10% there. So as i said before, in our case something like @implementedBy would definitely help us.

Marc Logemann

Posted by Marc Logemann on March 21, 2007 at 04:47 AM EDT #

Colin, I'm sorry, but you lost me. 500 classes is a tiny application in my opinion, and we have no problem going back and editing existing code. It would be naive to suggest that you don't have to do that. That's why Guice put so much focus on maintainability.

You're talking about "datasource1" and "datasource2", but I presented a real example: @ReadOnly. Who knows best whether a given class can use a read-only DataSource? The class itself, and that's where the annotation belongs, not off in some XML file.

Posted by Bob Lee on March 21, 2007 at 06:04 AM EDT #

Bob,

Your sidestepping the main point of my previous comment, which was about the apparent inability for Guice to inject one instance of class A (needing an interface X) with one implementation of interface X, while it injects another instance of the same class A with another implementation of interface X. If you look at my specific example, I can not see how you could with Guice inject one instance of JpaDao with one DataSource, and another instance with another. This is not some pie in the sky requirement, datasources was just an example (that you picked). This is a strategy, and you see it over and over again in OO code, and is one of the main reasons you use an interface in the first place.

As for the other simpler case, of injecting class A with an implementation of X, while injecting class B with a different implementation of X, what does 500 have to do with it, it's just a number I picked. My basic point is that it's sometimes impossible and also from a coupling point of view not acceptable to have to know ahead of time that you need to do this (even putting aside invasiveness), to add the marker annotation upfront, and that I don't find the alternative acceptable either, that I later have to go into the codebase in finished working code (which I may not even own) in various places to look for X usage to add these in...

Colin

Posted by Colin Sampaleanu on March 21, 2007 at 08:41 AM EDT #

This problem is what jumped out at me straight away. It is the exact same limitation as is in EJB3 DI. In an application I worked on which uses Spring we make heavy (perhaps too heavy) use of the Strategy pattern. Guice is worthless in this case.

And I would estimate that around 50% of the interfaces have more than 1 implementation. That is why we bothered using interfaces. If you are using interfaces when you have no intention of using multiple implementations then you are engaging in pointless speculative generality. (Java's dynamic proxy limitations are a problem of course, but a workaround to that problem doesn't mean using interfaces for everything is a good idea)

Posted by Asd on March 21, 2007 at 09:04 AM EDT #

Ok, how about an example.

class MessageSender
{
Transport transport;
MessageFormatter formatter;

public void sendMessage(Message m
{
....
}

....
}

Say I want to configure one component to send messages by email using a HTML format, and another one to send messages over HTTP using an XML format.

In Spring XML:

<bean id="c1" class="...">
<property name="transport" ref="smtpTranport"/>
<property name="formatter" ref="htmlFormatter"/>
</bean>

<bean id="c2" class="...">
<property name="transport" ref="httpPostTranport"/>
<property name="formatter" ref="xmlFormatter"/>
</bean>

How do I configure that using Guice?

Posted by Asd on March 21, 2007 at 09:10 AM EDT #

Colin,

You can inject different implementations of the same interface into the same client class quite easily. You just have to do it with two different Injectors obtained by feeding Guice two different Modules, one bind the interface to the first implementation, the other bind the interface to the second implementation.

I'm not sure if this the something that the Guice folks would recommend, or how often the situation arises in practice.

Posted by Weiqi Gao on March 21, 2007 at 11:38 AM EDT #

@Asd, what is the code that originally determines whether to pick smtp/html or http/xml? Where is that logic?

Posted by Stephen Colebourne on March 21, 2007 at 11:51 AM EDT #

Weiqi,

That may be easy, but seems completely unrealistic as to how you'd ever want to use Guice within an application. Normally you would create one injector, and feed it one or more modules. So if there is more than one module, you want to share the modules with the same injector, which means this would not work.

How are you realistically supposed to use two (or more) injectors in the same app? The whole point is to tie together the network of classes you know how to bind. The multiple injector approach would put a wall between the bindings.

Colin

Posted by Colin Sampaleanu on March 21, 2007 at 11:52 AM EDT #

@Asd: 50% of all interfaces have several implementations in your project? That seems really unrealistic to apply to an average project. Lets take DAOs. All of our DAO Interfaces have exact one implementing class, and we have a lot of DAOs. I dont think that this scenario is very uncommon.

Posted by Marc Logemann on March 21, 2007 at 12:05 PM EDT #

I'm not saying its an optimal solution. I'm just trying to show that it is not impossible to solve the scenario with Guice, as claimed in the earlier post.

Posted by Weiqi Gao on March 21, 2007 at 12:13 PM EDT #

Weiqi,

An injector is effectively a container. The only reason this approach "works" is because you've created two containers. But you don't want to build your app with two (or more) containers, as there is no way to share binding between them.

So I do indeed think the word impossible is much more accurate than talking about optimal vs. suboptimal. This is not a usable mechanism when working with one injector, and it'd be very hard to structure your configuration to work with multiple injectors, given the isolation between the injectors, the need to thus partition bindings and or duplicate bindings, and then on the client side know which injector you need to work with...

Posted by 216.138.221.115 on March 21, 2007 at 12:52 PM EDT #

Marc Logemann,
50% probably is not typical, but 10% seems low to me. In any case in almost any given project you will have at least a few interfaces with multiple implementations, and making the easy case even easier is not enough to justify the complication to the harder case.

Stephen Colebourne,
Eh.. I just came up with that of the top of my head. You could have two different web services, one of which needs to send message to be read by an admin, the other one just needs to send them to some logging service. In any case c1 and c2 would be injected to the services. The specifics aren't really important.

I've been thinking about Guice some more and I don't see all that great a distinction between what Guice does and autowiring (which is widely considered to be a bad idea).

Is
binder.bind(Service.class)
.to(ServiceImpl.class)
.in(Scopes.SINGLETON);

really that different to

<bean id="service"
class="ServiceImpl">
</bean>

<bean id="client"
class="ClientImpl"
autowire="byType">
</bean>

What you are effectively saying is in this context (or module) I am only going to have one implementation class for this interface. Admittedly there is a risk if ServiceImpl implements more than one interface but I think that is probably rare. I would imagine Spring could easily be extended to allow the following syntax:

<bean id="service"
class="ServiceImpl" auto-wire-candidate-class="Service">
</bean>

<bean id="client"
class="ClientImpl"
autowire="byType">
</bean>

Posted by Asd on March 21, 2007 at 01:24 PM EDT #

Craig, any tips for indenting code in your comments? I tried <pre> and to no avail.

Asd, we do always have N > 1 implementations of an interface: the real implementation and N - 1 mock implementations which we use for unit testing, but we don't use Guice in unit tests.

Colin and Asd, I'm going to address Asd's example using annotations throughout. If you don't think annotations will work for you, then please give me more details of how you decide which MessageSender to use, and I'll see if I can address your concerns.

bind(MessageSender.class).annotatedWith(Email.class)
.toProvider(new Provider<MessageSender>() {
@Inject @Smtp Transport transport;
@Inject @Html MessageFormatter formatter;
public MessageSender get() {
return new MessageSender(transport, formatter);
}
});

bind(MessageSender.class).annotatedWith(Http.class)
.toProvider(new Provider<MessageSender>() {
@Inject @Http Transport transport;
@Inject @Xml MessageFormatter formatter;
public MessageSender get() {
return new MessageSender(transport, formatter);
}
});

You could also extend MessageSender instead of writing a custom provider. For example:

class EmailMessageSender extends MessageSender {
@Inject
EmailMessageSender(@Smtp Transport transport,
@Html MessageFormatter formatter) {
super(transport, formatter);
}
}

bind(MessageSender.class).annotatedWith(Email.class)
.to(EmailMessageSender.class);

Posted by Bob Lee on March 21, 2007 at 01:31 PM EDT #

Bob,

How is this supposed to work in real use? It seems this is basically just giving up on using Guice to inject the MessageSender, and building Provider which shadows and builds _each type_ (configuration really, it's the same class) of MessageSender. Then you still have to bind the right Provider into the target location, presumably based on some special marker annotations.

This seems pretty convoluted and against the normal flow of how I'd want to work.

I would normally build a MessageSender working against Transport and MessageFormatter interfaces

public class MessageSender {
...
Transport transport;
MessageFormatter formatter;
...
}

and not have it worry about how many types of transports and formatters there are. In the Guice case, I would immediately start using the inject tag:

public class MessageSender {
...
@Inject Transport transport;
@inject MessageFormatter formatter;
...
}

Now this might be good enough, but as soon as some other class somewhere needs another kind of Transport, or another kind of MessageFormatter, I have to plug in some custom annotations so Guice can inject the right type:

public class MessageSender {
...
@Inject @SomeOtherMarker Transport transport;
@inject @YetAnotherMarker MessageFormatter formatter;
...
}

Now I have to make sure I use the same or a different special marker annotation as that other class or those other classes, as appropriate.

Now I get to the point where I start needing to inject two different instances of MessageSender with different implementations of Transport or MessageFormatter, I basically give up on Guice injecting into my MessageSender directly. I either rip out the annotations, or leave them there but know they will not be used, and then build two or more MessageSender Providers, one to build each configuration of the MessageSender.

This process sucks, at the end of the day. I just want to build a MessageSender, and have it work against polymorphic Transports and MessageFormatter:

public class MessageSender {
...
Transport transport;
MessageFormatter formatter;
...
}

And that should be it. The code should (and could, in a non-Guive world) work from then on. I don't want to have to think about what other classes might be using Transprot and MessageFormatter and are they they same ones (use bare @Inject or also add a marker decoration?). I don't want to think about the fact that maybe there will be one instances or multiple instances of MessageSender (inject into MessageSender or give up on that and go to custom Providers). And I don't want to have to make these changes to my class along the way, due to the limitations of the Guice model...

Colin

Posted by Colin Sampaleanu on March 21, 2007 at 02:36 PM EDT #

Bob>> You could also extend MessageSender instead of writing a custom provider. For example:

Bob, I have to say this idea is crazy. I have a MessageSender which works perfectly fine against polymorphic interfaces, Transport and MessageFormatter, has no code specific to each, and now I'm supposed to subclass the MessageSender and make an email specific MessageSender just for the convenience of Guice. Not having to be aware of what kind of Transport and MessageFormatter is plugged in is why we're using interfaces for these things in the first place... Do I make 10 variants that encompass all the variations of Transport and MessageFormatter?

Colin

Posted by Colin Sampaleanu on March 21, 2007 at 02:43 PM EDT #

This "3/4 of the code / xml was stripped out" keeps on getting mentioned without any proof given. I probably edit some of my spring code from 2 years ago and remove a fair chunk of it as I'm more experienced with it.

So Bob please stop quoting that reduction amount until some concrete proof is given.

Posted by BlogReader on March 21, 2007 at 02:44 PM EDT #

@Colin, @Bob
I spend a few hours last night trying to get Guice to handle the situation Colin described above to no avail.

Lets say you have a class App that needs a read-only DAO and a "secure" DAO. The DAO implementation is _the same_, but it takes a differing DataSource in the constructor. In this case, there is no way to add a annotation to the DAO constructor that will let Guice know which DataSource to inject.

It is possible (even trivial) to use a custom binding annotation to inject a specific instance of a class based upon annotation:

bind(DataSource.class).annotatedWith(Secure.class).toInstance(DataSource.lookup("secure"));

But, the three-level configuration Colin described doesn't really work for me using Guice. However, a two-level solution where you can directly annotate the "setter" works great, and this is the example code that Bob posted.

I did however find a solution that does work for the three-level case, but probably isn't what Colin had in mind. If you add two new classes that extend your Dao, it becomes much easier to manage. Example:

public class App {
TestDao secure;
TestDao readonly;
@Inject
public void setSecureDao(@Secure TestDao dao) {
this.secure = dao;
}
@Inject
public void setReadOnlyDao(@ReadOnly TestDao dao) {
this.readonly = dao;
}
}

public class ReadOnlyDao extends TestDao {
@Inject
public ReadOnlyDao(@ReadOnly DataSource ds) {
super(ds);
}
}

SecureDao is similar to the above

and in your module:

bind(TestDao.class).annotatedWith(Secure.class).to(SecureDao.class);
bind(TestDao.class).annotatedWith(ReadOnly.class).to(ReadOnlyDao.class);
bind(DataSource.class).annotatedWith(Secure.class).toInstance(DataSource.lookup("secure"));
bind(DataSource.class).annotatedWith(ReadOnly.class).toInstance(DataSource.lookup("readonly"));

So, as I see it, the only way to really handle a three-level problem is to actually create the sub-classes. So, in the above, you have SecureDao extends TestDao and ReadOnlyDao extends TestDao. This works and effectively tags the correct implementation. It's not quite optimal, but to me, the makes sense, as I'd say that the code should know what version of the Dao it should have... but it's not as flexible as the Spring solution.

It is probably also possible to use Scoping and a custom Provider class to actually handle this, but the doc's on Scopes in Guice is pretty sparse.

Posted by Marcus Breese on March 21, 2007 at 03:02 PM EDT #

@Colin and Bob why can't you just accept that you are solving the same problem in different ways. It is not an attack on your value or self worth as a person. Both of you are extremely smart gentlemen, on the order I will never amount to. However, your arguments are no different than comparing the size of your penis or whose Dad would beat up the other. Kudos to both of you on your frameworks, and here is to ending religious turf wars in our industry.

Posted by Kevin Burke on March 21, 2007 at 04:28 PM EDT #

I'm perfectly happy for anyone to use Spring if they don't buy into Guice's narrow philosophy. I hit the bars with Rod Johnson and Keith Donald a few nights ago, and we all got along great as always.

I'm not sure why Colin seems to have it out for Guice, but I personally have a hard time ignoring FUD. I suppose he might have been a little surprised by Guice's release as he wasn't one of the Spring developers we showed Guice to over the 6 months leading up to 1.0 (sincerely sorry, Colin).

BlogReader: You asked for proof, but does my O(N) vs O(M*N) argument above not count? Let's use an example: say I use a dependency Foo in 50 web actions. Using Spring's JavaConfig, I need to write an explicit @Bean method for each action, correct? Using Guice, I don't have to write any of that explicit wiring code. I just apply @Inject at the injection points. (This obviously assumes auto-wiring is not an option.)

Posted by Bob Lee on March 26, 2007 at 09:54 PM EDT #

[ CrzayBob; You asked for proof, but does my O(N) vs O(M*N) argument above not count? ]

Not really as you're just making up what M and N are. I need some real proof, not handwaving.

[ Let's use an example: say I use a dependency Foo in 50 web actions. Using Spring's JavaConfig, I need to write an explicit @Bean method for each action, correct? ]

I'm not sure if that is much of a big deal:
@BeanWhatever
IFoo foo
and then have your IDE do a setter for it. 2 lines of work.

Posted by BlogReader on March 30, 2007 at 10:57 AM EDT #

BlogReader, if you need further proof, try Guice. If you don't want to try Guice, don't; I have little incentive to encourage you to switch. I'm not a very altruistic person. I'm not trying to build up my consulting business (I don't even have one). I open sourced Guice so I could use it in Struts 2 and so other like-minded programmers don't have to repeat the effort.

Posted by Bob Lee on March 31, 2007 at 04:26 PM EDT #

Bob,

There's nothing personal here, and I don't know why you'd think there is or make it out that way. Any of the 3 or 4 times we've met you seemed like a decent guy, and I certainly respect your online persona. How do I "have it out" for Guice, and how am I "spreading FUD"? I am not miffed that you didn't show me Guice before, and in fact I looked at Guice at least as far back as last November when somebody mentioned it on the Struts list.

I'm a pretty straight shooting, simple kind of guy. If people are comparing Guice and Spring, and somebody is saying Guice is the cat's meaow, and I can clearly see the model has some issues, I'm going to at least try to state my point of view. If somebody were comparing red avocados to blue avocados I wouldn't give a damn, but IoC/DI is a subject pretty near and dear to my heart. Everything I've said about Guice anywhere (which as far as I know so far is only in this blog entry and another) was backed by technical arguments. People can then draw their own conclusions.

So as for going out drinking together, I wouldn't have thought anything I've said above would have been grounds for exclusion of any such activity, but it seems to me that you're the one taking this personally...

Regards,
Colin

Posted by Colin Sampaleanu on March 31, 2007 at 07:20 PM EDT #

Colin, I never take tech stuff personally, and I have a great deal of respect for you and Spring, too. Most importantly, I'll buy you a beer anytime. :)

Posted by Bob Lee on March 31, 2007 at 08:07 PM EDT #

You might want to compare guice's approach to the annotated modules of Apache HiveMind 2:
http://cwiki.apache.org/HIVEMIND2/newin2annotatedmodules.html

Posted by Achim on April 01, 2007 at 07:09 AM EDT #

Achim, to start, Hivemind uses string identifiers. :(

You might want to compare it to Guice. ;)

Posted by Bob Lee on April 01, 2007 at 12:40 PM EDT #

Bob, you are free to ignore the service ids if you can ensure that the service type is unique. But if not (see discussion above about multiple implementations) then it's nice to have such a differentiator.

Posted by Achim on April 02, 2007 at 03:46 PM EDT #

BTW, I don't think the statement about spring java config not relying on String identifiers in the configuration is correct.
Thats what the reference guide tells you how to wire a service which is defined in a different context:

public ExampleBean anotherBean() {
ExampleBean bean = new ExampleBean("anotherBean);
bean.setDep(getBean("myBean")); // use utility method to get a hold of 'myBean'
return bean;
}

Posted by Achim on April 02, 2007 at 03:55 PM EDT #

Achim, Guice uses annotations instead of string identifiers. Hivemind looks like Spring's JavaConfig to me.

Posted by Bob Lee on April 02, 2007 at 05:15 PM EDT #

I like this idea by Asd to alleviate the configuration task... This is extremely useful in the 50 bean example cited by Bob.

>> Asd

I would imagine Spring could easily be extended to allow the following syntax:

<bean id="service"
class="ServiceImpl" auto-wire-candidate-class="Service">
</bean>

Posted by Alex on April 04, 2007 at 02:21 AM EDT #

Guice and Interfaces.

I like Guice but had some challenge using/defining classes implementing a given Interface.

So far I found that

binder.bind(ITransform.class).annotatedWith(named("InsertSequence")).to(InsertSequence.class).in(Scopes.SINGLETON);

worked as defined in Module to then retrieve a class as follows:

ITransform it = injector.getInstance(BackupServers.class);
...
it = injector.getInstance(InsertSequence.class);

No annotations on the Interface Implementation classes are used and the name in 'named' does not matter but allows retrieving via injector.getInstance(className.class)

annotatedWith(named("anyUniqueName"))

The statement below did not work; it should as per the documentation and would avoid using the dummy 'named' tag.

binder.bind(ITransform.class).annotatedWith(InsertSequence.class).to(InsertSequence.class).in(Scopes.SINGLETON);

This might not be the correct/intended use but so far by experimentation I found this behaviour that works for me; it uses Module to document/configure, and allows me to retrieve a given class without annotating it.

Here is my Module definition:

-------------------------------------

public void configure(Binder binder) {
//binder.bind(ITransform.class).to(BackupServers.class).in(Scopes.SINGLETON);
binder.bind(ITransform.class).annotatedWith(named("BackupServers")).to(BackupServers.class).in(Scopes.SINGLETON);
binder.bind(ITransform.class).annotatedWith(named("InsertSequence")).to(InsertSequence.class).in(Scopes.SINGLETON);
//binder.bind(ITransform.class).annotatedWith(InsertSequence.class).to(InsertSequence.class).in(Scopes.SINGLETON);
binder.bindConstant().annotatedWith(named("BackupServers.rePattern")).to("^(\\S+)\\s+(\\d+)$");
binder.bindConstant().annotatedWith(named("InsertSequence.reCmd")).to("10L");
}

-------------------------------------

Posted by j.f. zarama on April 09, 2007 at 12:32 AM EDT #

Hi,

We use Spring XML config on our project which has very strict style guidelines enforced on the code. We usually code to interfaces so that our classes can be declared final and still be be mocked out in tests (among other reasons).

What we ended up with was a huge set of XML wiring files containing references to all the default implementations of the interfaces ie DefaultSomething, DefaultSomethingElse.

Then one of our guys realised that we could create our own BeanFactory to lookup default implementations in the classpath based on our naming convention of DefaultXxxx. Our wiring files then shrunk to a fraction of their size as we were only explicitly wiring in multiple implementations of an interface, aspects, ambiguous arguments or config. The same thing could probably be done for Spring JavaConfig. If the naming convention was made configurable, then this approach could cut down the size of the wiring in many if not most Spring-based projects.

Regards,

Ben

Posted by Ben Warren on April 25, 2007 at 11:53 PM EDT #

Craig,

Can you please explain, in KnightConfig, why did you used the @Bean annotation on quest() ?
To me, it doesn't seem necessary, nor other annotations but for the object graph root (but then again, what do I know about Spring?)

Thank you,
Vlad

Posted by b100dian on June 18, 2007 at 10:17 AM EDT #

Colin's example problem of injecting two different Datasource's into the same class is a problem I have faced in real projects several times.

Its not uncommon to have your data spread in several databases, and want to point the same app code at each of them.

I havent seen a convincing solution to the problem Colin described posted here. I really think Guice should find some more elegant solution to this problem.

Guice's philosophy of focusing on "Defaults" does seem efficient for 90+% of cases, but nonetheless, if you're unable to handle the remainder without modifying your app, that's a terrible weakness.

Posted by Ben Hutchison on August 30, 2007 at 04:09 AM EDT #

I try to find a solution to use Ioc container used as java script client, GWT used to compile the js code. Because of GWT doesn't support java reflection,Spring can't be directly used in client side. Someone pointed Guice+Gin is a good solution. But for we using Spring in our real world project and it was proved great by our hands-on experience. I expect spring community could plan to support client side solution for GWT. If we can find the same awesome solution in client side(Java+Js+Html) as server side(practically,not really accurate). That would be exciting.

Posted by Sammi on October 04, 2008 at 07:04 AM EDT #

Post a Comment:

Name:
E-Mail:
URL:

Your Comment:

HTML Syntax: NOT allowed