Friday, June 20, 2008

Spring vs EJB3

Recently I have been asked by many people about why I am not using Spring in most of my new projects any more, so I decided to write an article here and put my own opinion for future references.

Before going any further I think EJB3 has taken lots of good ideas from Spring and Other IOC containers as well as other technologies (like annotations)

Spring may still have its own places and benefits especially for applications running on one machine. The following debate is for ordinary information systems usually considered database applications.

For many other use cases I prefer OSGI over Spring which I will discuss in another article.

Old Reasons for using Spring

The main reasons for using Spring prior to Java EE 5 for most developers was:

  1. No need for EJB container
  2. The IOC container
  3. Light weight POJO
  4. AOP
  5. Integrity with other Programs via Spring modules

No need for The EJB container

The first reason was avoiding the heavy weight EJB container.

Now there are lots of embeddable EJB container including JBoss and Glassfish, for example the JBoss EJB3 embedded container is around 9MB while the spring container size with its dependencies has grown to over 81MB!

Don't forget that now you can embed the EJB container in Tomcat and

In EJB 3.1 all web containers will support most of the EJB features.

The IOC container

Spring had a good IOC container. Now there are better options available, for example Google Guice.

EJB3 has also a fair IOC container; you can easily inject other EJB3 components, and other resources via annotations (and also using XML deployment descriptors)

The benefit of Spring IOC container was it would let you get ride of JNDI headaches. Now EJB3 offers the same, although you can still benefit JNDI when it is needed in distributed applications.

Light weight POJO

EJB3 components are also light weight POJO. The overhead of EJB3 Session Beans over bare POJO is only 3%

AOP

Spring supports AOP, Spring AOP is build on top of AspectJ AOP framework.

EJB3 supports interceptors offer a similar limited functionality, but it is not a complete AOP.

By definition Java is not an aspect oriented language (while AspectJ is an aspect oriented language build on top of Java) Some people prefer not to use AOP at all. And some others prefer to use other AOP frameworks which may perform better for them like aspectwerkz, naming, JBoss AOP and others.

Using EJB3 developers can use any other AOP framework they like and are not limited to the AspectJ.

Integrity with other Programs via Spring modules

There are some modules available for integration of other technologies with Spring, actually availability of these modules means you have to develop your own for other technologies, to keep your code clean and in pure spring architecture. While nearly any framework developed out there is pluggable to main Java EE container.
Although you may have some problems because of conflicts in dependency and configuration in many cases. But most of times same problems also occur when you are using same set of components in Spring.

Spring promoted singleton components is not good in most cases!

this is the main reason I put spring a way in most of my applications.
Spring support two main different life cycle model (Bean Scope) for components: Singleton (default) and Prototype.
The promoted model is singleton and that is the component model I don't like. There are plenty of articles available about why singletons are bad and some people even consider them an anti pattern.
So what is wrong with this model?
to continue let me remind you that Spring Singleton Objects are Stateless one instance of them are created and shared between all users.

Lifecycle

Life cycle of Spring Singleton is like this:

  • By default beans are created on first use or at application startup if they configured to be so. They are initialized and become available for use.
  • They are used by different process and threads.
  • They are destroyed by programmer code if optionally destruction code is implanted.
Here we have came back to Dark Age of C++ which Garbage Collector was still not available. I think this is a very big architectural flaw in Spring component model.

Stateless Middle Tier

Not all applications can be written stateless, most of the times users have to hold the application state in client (web tier or users browser) or in database.
Storing application state in users' browser is an obviously wrong because it will not only increase network usage but it will also destroy your application security.
Holding state in web tier is also not a good option because you need to transfer the state objects between tiers instead of keeping them near the process which will use them again.
Storing state in DB is a disaster, as you already know CPU is thousand of times faster than hard drives.

lets take a look at an example:
imagine a user browsing a list of objects with dependent objects (master-detail) if you hold state in DB for each page view you have to perform a new query to database.
if you store state in web tier a large list should be moved between tiers which may be on different nodes. if you store state in users client (browser) you have to send entire list to user each time! all cases lead to a performance disaster in case of Spring Singleton while they could have been stored in a SFSB in EJB3 model.

now if you are using Hibernate or other JPA ORM's if you keep your EntityManager alive you can lazy load objects when users click on an Item in the list, while in Spring case since the bean is Stateless the state will be lost and developer has to look up the detail objects again which lead to more code. and more complex application.

Not scalable on clusters

I think we all agree that some times projects hit the one CPU limits and need to be distributed on clusters for scalability and for availability.
Here comes the real power of EJB component model.
EJB components can run transparently on different nodes. That’s main part of their definition and the main reason behind their overhead over other component models.
While on other hand Spring singletons are created once and stay alive as long as application is running.
Spring framework offers no way for distributing Spring objects on a cluster, so depending on your environment they will either created in one node or all nodes! And spring framework performs no load balancing on Spring beans!
That is the magic that spring performs better on single CPU, they have omitted the scalability solution.
Does this mean Spring can not be scaled at all?
No you can run Spring on other platform that provide distributed computing like using a distributed JVM or a cloud or grid. But for a program to benefit most out of parallel computing it has to be written parallel from scratch, and Spring singleton beans are not.

in most cases you have to redesign your spring application to benefit the new underlying distributed architecture.