CDI 1.0 vs. Spring 3.1 feature comparsion: bean definition & dependency injection
This blog article provides a comparison matrix between Spring IoC 3.1 and CDI implementation JBoss Weld 1.1. Comparing the two technologies is difficult 'cause it happens easily that you compare apples to oranges. I have asked myself a lot of questions before I have started the comparison effort:
- Which direction is best for comparison: from CDI features to Spring features or vice versa?
- What is a feature and which features should one choose for comparison?
- What's the appropriate level of abstraction for comparison?
- Which features are important?
- Will I use Spring or CDI terminology or will I have my own abstract feature requirements?
- For the CDI implementation: which implementation to choose, Weld, Apache OpenWebbeans or Resin CanDI?
- Can I build groups of features?
I have decided to build my own list of abstract requirements for an IoC container. Furthermore I think a good way to start the comparison is to only look at the "pure" bean definition and dependency injection features provided. The advanced stuff like CDI Interceptors or Decorators is covered ín subsequent articles. I have chosen Weld as the CDI implementation because it provides the best documentation compared to the other implementations, also Weld is the reference implementation for JSR 299. With regards to the particular features compared: I have chosen features that I found important from my own history as a developer in large projects, and yes! of course that's subjective. There will be other features that you may find more important, feel free to add comments and I will adjust the matrix if appropriate.
To outline the scope of this analysis and for those that like to dive deaper into the topic, it's a good idea to be concrete about the reference for this comparison:
Spring 3 reference dosumentation refered to:
- Chapters 3.2 to 3.4: Container Overview, Bean Overview, Dependencies
- Chapters 3.9 to 3.12: Annotation-based container configuration, Classpath scanning and managed components, Java-based container configuration
- Chapter 7.4: Expression support for defining bean definitions
Weld 1.1 reference documentation refered to:
- Chapters I.1-I.4: Introduction, More about beans, Dependency injection and programmatic lookup
- Chapter III.8: Producer methods
Why comparing CDI and Spring is not particular easy
Spring offers three different approaches to do dependency injection: XML-based, annotation-based and pure Java-based (programmatic). CDI on the other hand is strictly annotation-based. Therefore the easiest way to compare the two is: "Spring's component scanning and autowiring" vs. CDI. These concepts play in the same sand box - from a technological view point. On the other hand one may say that XML-based (or programmatic Java-based) configuration provide critical benefits. Therefore I have not distinguished the three different approaches in Spring, I just looked at the features provided.
Spring is a framework that provides lots of functionality that is integrated into the IoC container. Comparing all the stuff with CDI does not make sense, because in Java EE lots of the functionality of the Spring IoC container is covered in other API, seperate from (but also integrated into) CDI.
A summary of what I think is true
From a pure feature oriented-perspective: in the area that I compared in this article, there is only little critical difference in the two technologies. Spring offers three different IoC container configuration approaches: XML-based, Annotation-based and pure Java-based (programmatic). CDI on the other hand is purely annotation driven. CDI gives you less to think about, it is a very streamlined solution. Spring offers options to fine-tune for your specific requirements. XML-based or programmatic Java-based configuration - for instance - are the only ways for you to have real pure POJO's. Also, the Spring Expression Language adds some noteworthy features (e.g. bean identification and injecting property values). However, both technologies cover the most important dependency injection features.
In the comparison process I have tried some of the stuff with both frameworks. I have to say that I found the Weld reference documentation much more intuative to read. May be that's a consequence if you only provide one configuration approach. On the the other hand I would suggest that Spring reference documentation should structure their chapters according to the three different mainstream approaches (XML, annotations, programmatic). It's a bit confusing that examples are spread across the reference documentation (e.g. if you are looking for type-safe dependency injection using annotations). The three approaches are the obvious documentation structure, because end users first decide which approach to use
Note that I was doing feature comparison here. There is more to think about then just features. See my two blog entries on technology decision making and JEE vs. Spring comparison.




From http://niklasschlimm.blogspot.com/2011/06/cdi-10-vs-spring-31-feature-comparsion.html
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





Comments
Adrian Mitev replied on Wed, 2011/07/06 - 1:16am
Nicolas Frankel replied on Wed, 2011/07/06 - 1:40am
Hello,
You matrix is interesting; yet, there's a point you fail to mention. By default, all classes on the classpath are available for injection in CDI whereas only those referenced are in Spring.
Since this is a big source of potential problems, I think you should mention it.
Geoffrey De Smet replied on Wed, 2011/07/06 - 2:04am
Comparing Weld without Seam to Spring might be a bit unfair.
For example, Weld+Seam does have "pure pojo support" as you can use Seam-Config to use XML instead of annotations.
Charlie Mordant replied on Wed, 2011/07/06 - 3:10am
@Nicolas: this is not a big problem, in practice you just have to declare <context:component-scan basePackage="..."/> in your application-context.xml.
So, do you think that in the near future (or if it is possible now) we will be able to run a J2EE capable application (Jta managed, jms aware...) with a tomcat server and JSR299?
Niklas Schlimm replied on Wed, 2011/07/06 - 3:38am
in response to: ge0ffrey
Hi Geoffrey, my comparison articles are more "pure Java EE vs. Spring(+Java EE)" like. It's not comparing Java EE+Seam vs. Java EE+Spring. The question to me was (when I started comparison): is pure Java EE (since CDI 1.0) ready to compete with Spring IoC? Java EE + Seam has always been an alternative to Spring, not just since Java EE 6. It's difficult to find the exact fair scope for comparison I suppose :-) so I just started and did my best to be fair ...
Cheers, Niklas
Niklas Schlimm replied on Wed, 2011/07/06 - 3:41am
in response to: adr
Hi Adrien, my articles do compare pure Java EE vs. Spring. Java EE + Seam has always been an alternative to Spring, also before Java EE 6. The real question to me was: is Java EE 6 ready to compete with Spring?
Cheers, Niklas
Niklas Schlimm replied on Wed, 2011/07/06 - 3:43am
in response to: tcharl
Reza Rahman replied on Wed, 2011/07/06 - 11:12am
Thanks for mentioning this. I agree talking about CDI without portable extensions is somewhat myopic. In the least case, the article should have made mention of their availability.
The explicit reason CDI supports an extensive portable extensions SPI is to support a rich plugin ecosystem consisting of projects like Seam 3, Apache CODI, Arquillian, Forge, CDISource and so many others. This way, CDI can remain a very small, simple core that focuses on getting the 80% use-case right while allowing for exensions where really needed (but still in a very portable, standards-compliant manner).
I talked about the CDI ecosystem at TSSJS 2011 for those interested: http://www.caucho.com/articles/CDI_Landscape.pdf.
Reza Rahman replied on Wed, 2011/07/06 - 12:05pm
in response to: nschlimm
This is actually an implementation detail. All beans need not be loaded on startup and can be loaded lazily as they are needed. All Java objects in a module are also not loaded, just the ones that are legitimate CDI beans. All that is done is jar scanning which is trivial and done for all Java EE components and not just CDI in Java EE 5/Java E 6.
This point actually vividly demonstrates the fundamental philosophical differences between Spring and CDI/Java EE in general that this comparison only vaguely alludes to. In CDI, bean processing via annotaions just works out of the box. In Spring, enabling it requires explicit configuration. My comparsion showed the differences between Spring and Java EE configuration for very common cases: http://www.redhat.com/f/pdf/jbw/rrahman_320_spring_framework.pdf. Lincoln makes the same point here: http://ocpsoft.com/java/spring-to-java-ee-a-migration-guide-cdi-jsf-jpa-jta-ejb/ as does CDISouce.
Bruno Borges replied on Wed, 2011/07/06 - 5:24pm
Grzegorz Grzybek replied on Thu, 2011/07/07 - 12:53am
Jar scanning should not be described as "trivial". With Spring the user is in control - with <context:component-scan />. With JavaEE implementations you end up with all your JARs being scanned up and down.
I don't say what's good and what's bad, but running:
should give a little hint, that not everything should be scanned :)
regards
Grzegorz Grzybek
Lincoln Baxter replied on Thu, 2011/07/07 - 8:30am
@Grzegorz - Not entirely true. You can directly control which beans are and are not scanned simply by using @Veto or by not including beans.xml in your jar, then adding beans one-by-one as you please. This is not hard to do, and is actually not a difference worth mentioning because with a trivial amount of configuration (yes, I said trivial!), Spring can do the same thing as CDI, and visa versa, perhaps with a few minor exceptions on both sides.
However, more importantly, this article ignores the more relevant subject of CDI extensions, which can change or control the entire function of the dependency injection container; it also ignores the Contexts (C in CDI) which are a huge differentiation between the two. Spring does have this concept, but it does not have the concept of binding beans, interceptors, and decorators to contexts and beans in a type-safe way.
Interceptors and Decorators are yet another difference between CDI and Spring. In addition to that, CDI provides a built-in lightweight publish-subscribe event bus which is *extremely* powerful.
You cannot ignore the differences if you are going to compare the similarities.
Niklas Schlimm replied on Thu, 2011/07/07 - 12:18pm
in response to: lincolnthree
Hi Lincoln,
I did not want to make it a JEE+Seam vs. JEE+Spring comparison. Seam+JEE has always been the alternative to Spring for enterprise development. But is pure Java EE 6 an alternative?
Scopes and Contexts will be covered in my next article (actually it's finished and also coveres integration testing scoped-beans - will publish next week or so). This one was "pure" (or "basic") bean definition and DI features.
Spring 3.1 does not have a concept for typesafe scopes. However, you can JSR299-scopes-enable Spring very easy as shown here: http://matthiaswessendorf.wordpress.com/2010/05/06/using-cdi-scopes-with-spring-3/, the project can be downloaded here: http://matthiaswessendorf.wordpress.com/2010/09/15/a-cdi-scope-resolver-for-spring/ .
Typesafe bean injection is already available as shown in my blog: http://niklasschlimm.blogspot.com/2011/06/type-safe-dependency-injection-in.html.
Interceptors and Decorators is the article I am currently working on. The pattern approach - btw - is what I like the most in CDI, it makes it obvious to use them if you have these annotations. Some say you can do all this with AOP or pure DI, but they missed the benefit of programming model simplicity in a large development shop.
Cheers, Niklas
Reza Rahman replied on Thu, 2011/07/07 - 1:47pm
in response to: gzres
jar scanning *is* quite trivial. It's a matter of one loop and if statements over class definitions you find in a candidate jar. It's performance on most typical systems are in the sub-second range. Spring incurs basically the same cost, just iterating through packages in multiple jars instead of all class definitions in a jar. That's hardly worth the additional configuration burden.
Reza Rahman replied on Thu, 2011/07/07 - 1:45pm
in response to: nschlimm
You are missing the point and that's what's making your analysis deeply flawed.
The relationship between Seam 2 and Seam 3 to Java EE is fundamentally different. Seam 2 was a framework like Spring that sat on top of Java EE. Seam 3 (and other CDI portable extension projects like CODI) on the other hand is just a set of ad-hoc CDI plugins. Talking about CDI without it's available plugins is about as meaningless as talking about JSF without it's available plugins. The way I see it, talking about EJB 2 without useful extensions like XDoclet is just as meaningless.
As I have tried to explain to you repeatedly in the past, there is no such thing as "pure Java EE". The job of any good Java EE API is to define the core and foster an extensions/plugins ecoystem that developers can leverage, not act as a walled garden. I think the walled garden is more the Spring mindset in that something that doesn't come from the "mothership" is not considered "pure".
Grzegorz Grzybek replied on Fri, 2011/07/08 - 12:06am
in response to: rrahman
@Lincoln Baxter
First - sorry for hijacking threads:) Tomcat is not CDI implementation and I was talking about JARs scanning in general. For CDI OK - it's a matter of beans.xml, but scanning for e.g. servlets is not a matter of some marker files.
@Reza
I've just recently been fighting with JARs scanning on JBoss 6 and here are some proves that jar scanning is not that trivial after all :) :
I know the third point is a dirty hack and makes me a bad JBoss user because I'm telling JBoss to stay away from my classes - just deploy my war. But it's a different topic.
So sorry again for mixing CDI and classpath scanning in general in one comment :)
regards
Grzegorz Grzybek
Reza Rahman replied on Fri, 2011/07/08 - 2:21am
in response to: gzres
OK, this is getting really silly :-).If you're going to quibble in favor of Spring, at least pick something more substantive :-).
Just because you can mess up a simple task says nothing about the actual computional resources necessary to perform that given task. You can use quick-sort to get log(n) performance to perform a sort or you can write your own home-brewed sort algorithm that performs worse than bubble-sort and has bugs.
The bottom line is that any sane jar scanning algorithm, especially when only triggered by the existance of beans.xml, which is the case for CDI, is cheaper than making a single database query in most enterprise systems. It's also the case that Spring and CDI annotation scanning performance is basically equivalent for reasons already mentioned. In fact, Spring performance can be worse since it has to look for classes that match a package name across the entire class-path instead of just focusing on scanning candidate jars.
BTW, Servlet, EJB, JPA, etc only scan candidate jars too and not the entire classpath as is the case with Spring - specifically for the reason of preempting potential performance issues :-).
joshua long replied on Fri, 2011/07/08 - 2:19am
Spring's got a huge ecosystem of supporting libraries from SpringSource and from numerous other groups / projects / organizations. Many of these supported projects do not have CDI analogs, either. After all, Spring's is, and has been, the de-facto standard since 2004 and - perhaps mysteriously to somebody whose used JavaEE for more than a single generation - plugins written on top of Spring in 2004 still work on Spring today. To suggest that Spring only fosters libraries from the "mothership" is... misguided.
The JBoss .pdf linked was overtly-verbose, out of date and not representative of the common ways to configure things in Spring in 2009, and it's even less so now.
Reza Rahman replied on Fri, 2011/07/08 - 3:08am
in response to: starbuxman
Hmm - I'm not entirely sure of the point of your post. I guess it's cool that someone from SpringSource itself joins the fray. No one so far is talking about comparing anything other than basic DI features but you.
The point is that projects like Seam Solder, Seam XML Config and CODI enhance even basic DI features via CDI plugins, so they are entirely relevant while talking about CDI DI features. Maybe they are not relevant only because it deprives Spring of a spuriuos claim to "de-facto superiority" :-).
What I find very interesting about your comments on my analysis is that it was reviewed by none other than - you. You had no valid objections to it then and I doubt you do now (in fact, your only concrete suggestion was to use the "p" namespace that I've never seen anyone use in a real Spring project). You can quibble about configuration flavors all you want, but the reality is that anything Spring mandates more configuration.
I'll grant you that it is dated, which is why I fully intend to update and expand on it in article series form as soon as possible. I'll look forward to seeing what you guys have to say on those...
joshua long replied on Fri, 2011/07/08 - 3:11am
in response to: rrahman
Reza Rahman replied on Fri, 2011/07/08 - 5:27am
in response to: starbuxman
Bogdan Mustiata replied on Fri, 2011/07/08 - 5:40am
Niklas Schlimm replied on Fri, 2011/07/08 - 7:51am
Reza Rahman replied on Fri, 2011/07/08 - 7:58am
in response to: b.m
I think this kind of statement lacks serious perspective.
Let alone the community around the JCP that includes people like Antonio, Adam and Werner each open source Java EE implementation like GlassFish, JBoss, Seam and Resin have their own vibrant communities. For example, here is the list of people involved in the Java EE 7 JSR: http://java.net/projects/javaee-spec/members. Note that non-vendors far outweight vendors and there is no limit to who can join the java.net project.
A lot of time is spent making sure all Java EE APIs integrate with each other. The few gaps that are left are usually promptly filled vendor extensions or plugins. Besides adding features where needed, the major goal of portable extension projects like Seam/CODI is to provide integration with standard/non-standard APIs from various vendors as smoothly possible. Take a look at the current and proposed list of Seam/CODI modules to see why.
As to upgrades, both every JCP expert group and vendor is downright religious about backwards compatibility and upgrade paths. In fact, I think Java EE is too overly concerned with backwards compatibility (perhaps with the sole exception of the Seam project that I see as being far more progressive). For example, products like WebSphere to this day support things like CORBA, EJB 1, EJB 2 and JAX-RPC just so old code can continue to run!
Reza Rahman replied on Fri, 2011/07/08 - 8:21am
in response to: nschlimm
I would say "pure" Java EE is good enough for the vast majority of use cases (that's certainly been my experience even with Java EE 5 projects). Where it is not, you should be looking to extensions and plugins to each Java EE API. CDI plugins play a particularly important role since one of CDI's primary goals was to significantly expand Java EE extensibility. Folks like Dan Allen made that clear long ago: http://java.dzone.com/articles/cdi-extensions-you-can-build.
I look forward to the rest of your posts. I think as a long-time Spring user, you have a bit of a Spring bend, but I do think you are making a real effort to be objective and that's what you need to do in your role for the long and short term best interests of your orgnization and the developers that work there. Besides, people like me are here to keep you honest :-).
If you want to deliberately disregard CDI plugins, your article should clearly mention that as well as a rationale for what your reasoning behind leaving it out is.
Reza Rahman replied on Fri, 2011/07/08 - 9:03am
in response to: rrahman
Sirikant Noori replied on Sun, 2012/01/15 - 11:44am