Niklas has posted 30 posts at DZone. You can read more from them at their website. View Full User Profile

CDI 1.0 vs. Spring 3.1 feature comparsion: bean definition & dependency injection

07.05.2011
| 19407 views |
  • submit to reddit

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

Published at DZone with permission of its author, Niklas Schlimm.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Adrian Mitev replied on Wed, 2011/07/06 - 1:16am

There is a CDI helper projects named "Seam Solder" that provides additional annotations like @Veto and many other useful things.

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: Geoffrey De Smet

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: Adrian Mitev

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: Charlie Mordant

Agreed :-) It may also be an issue to have ALL the beans registered w/o any purpose ...

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: Niklas Schlimm

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

Hi Niklas, would you mind taking a look at the Gamboa Project? It's an archetype for Wicket-Spring-Scala-MongoDB. Something I'm working on. www.gamboa-project.org I'll be looking forward to reading your comments

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:

svn log http://svn.apache.org/repos/asf/tomcat/trunk/conf/catalina.properties

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: Lincoln Baxter

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: Grzegorz Grzybek

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: Niklas Schlimm

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: Reza Rahman

 @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 :) :

  • org.jboss.web.deployers.MergedJBossWebMetaDataHackDeployer class and its comment
  • threads on http://community.jboss.org/en/jbossmc/ forum - many of them are about preventing JBoss from loading server classes (which is not about scanning but classloading) or about scanning in particular
  • I've also been forced to use jboss-scanning.xml with empty <scanning xmlns="urn:jboss:scanning:1.0"/> just to let my WAR deploy without errors.

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: Grzegorz Grzybek

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 also features an in-container, type-safe publish-subscribe mechanism. Interceptors and decorators are a difference, but not a differentiator. You can as easily achieve the same effects in Spring with its AOP library. This post does not consider CDI extensions because it would be irrelevant. The things discussed are pure-play DI (not AOP, not the publish/subscribe mechanism, not the web-tier support, etc). In the same way, the post also ignores the large ecosystem of libraries that build on the core dependency injection container in Spring. In fact, this post ignores most of the Spring framework itself! Most of the features described lives in one jar in the Spring framework, the rest in a second jar.

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: joshua long

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: Reza Rahman

Well, thanks Reza. Awfully big of you. I guess that it's "cool" that somebody from Resin or JBoss joins the fray, too. I did have "valid" objections to the .PDF then, and i have even more now. I (personally) welcome an updated, corrected version. The original thrust of the comments on this post were about expanding the discussion to include interceptors and other things that are available only in CDI addons. You mention Seam, Arquilian and a slew of other projects in the CDI ecosystem specifically to support the case that considering CDI without the CDI ecosystem is myopic. Those projects alone do much, more than simply augment CDI's pure-play DI features.

Reza Rahman replied on Fri, 2011/07/08 - 5:27am in response to: joshua long

If you have valid objections to my analysis, why wait - let's sort it out right now. Please do tell what you want "corrected" and "updated". I still have your review comment emails, so it will be interesting to see what you say this time...

Bogdan Mustiata replied on Fri, 2011/07/08 - 5:40am

My humble opinion is that since spring is made by one vendor with the support of the community, unlike cdi (jee) that is "agreed" and "standardized" by n vendors with some support of the community, spring offers the better integration between whatever stuff they offer, and obviously better upgrade paths. My 2c.

Niklas Schlimm replied on Fri, 2011/07/08 - 7:51am

@Josh @Reza it was my decision to compare pure Spring vs pure CDI. Cause that is interesting to me: is pure Java EE a fully sufficient development stack for enterprise development? And is it mature? (robust dev env, good integration, meaningful error messages, good testing support, extensibility, impl options). This article is about bean definition and built-in (no plugin enhanced) DI. My next post is about scopes incl. integration testing. Interceptors and Decorators will be the follow up. I am doing this cause the decision is atrategic to me as the architecture lead in my company, I am sharing this to get valuable technical feedback from the community, such as you guys.

Reza Rahman replied on Fri, 2011/07/08 - 7:58am in response to: Bogdan Mustiata

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: Niklas Schlimm

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: Reza Rahman

For anyone interested, Josh and I mutually agreed to take this discussion off-line to keep it as level-headed as we can make it. Whether I agree with it or not, I see his input as being very valuable in my writing an updated Spring/Java EE comparison in detailed article series form this time instead of just a talk. One thing I will do this time is make it clear that I work for Caucho since I am no longer an independent and the comparison will be more like looking at Spring from a Java EE perspective (similar to the disclaimer Lincoln had in his analysis).

Sirikant Noori replied on Sun, 2012/01/15 - 11:44am

I think it's a little bit miss leading on the CDI part or you didn't read all the document, the core of CDI is not only DI, there is Scope (ApplicationScoped, SessionScoped, ConversationScoped, RequestScoped and Dependent, user can also define customized scope), so with CDI you can inject ConversationScope object into SessionScope without worry where it should change to new instances or release.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.