From time to time I meet someone who doesn't like EJBs :-). He often argues: "EJBs are heavyweight". This is in general enough to convince developers, not to use it. However I often ask in such situation: "Please define the term heavyweight and lightweight". I love the answers. In most cases the term "heavyweight" is associated with container, deployment and frameworks. Recently I got even an answer, that EJBs are annotated - that the reason for their heavy weight. I asked than, whether it would be lighter to have a deployment descriptor - but the discussion stopped at this point :-). Even the description in wikipedia is funny: "...EJB 3.0 was less heavy weight than EJB 2.0 and provided more choices to developers...". So EJB 3.0 are less heavy weight - than I would like to introduce the term "midweight" :-).
The truth is: EJB 3 are just annotated Java classes (if you love XML you can even use just Deployment Descriptors instead of annotation) - but the container (=runtime - still not need to associate the term "container" with heavyweightness), uses the meta data to add additional behavior during the deployment time. The additional behavior is nothing else, than aspects - or crosscutting functionality. Some of the aspects are essentially important in concurrent systems. Especially the association of an instance with the thread, and transactions are really important. The problem here: both are unsexy and do not have effects on the "green bar" in unit tests - so this issue is often ignored (until production :-)).
Because of the aspects, we get indirection between the caller and the instance. The aspects (nothing else than decorators), are executed first, before the actual instance (business logic) will be executed. So the container applies, transactions, checks the security starts a session in case needed / declared. This causes of course some overhead (3% in Glassfish) - but you would have to provide similar functionality anyway. In case of pure POJOs in a WebContainer, you will have to provie a ServletFilter, decorate the request with security, transactions etc, instantiate all needed / required resources in the filter, put them in a ThreadLocal, catch all exceptions and rollback transactions ....and educate the developers only to use the resources from ThreadLocal.
Applying aspects to POJOs could be actually a reason to call EJBs "heavyweight". But then, all other frameworks will have to be renamed as well :-). One real issue with J2EE were overblown (often commercial) appservers. The deployment was slow and errorprone. However this issue is already solved (the download of Netbeans 6.1 with Profiler, Visual Designer, Tomcat 6 and Glassfish v2 takes 139 MB) and is getting even better. A deployment of a small EJB 3 takes about 2 seconds on my machine (without virus scanner :-)), bigger applications can be deployed in less than 1 minute. The only thing, which takes long ist the preparation of NamedQueries in JPA - but this is an EJB 3 independent issue. Glassfish v3 is highly modular and embeddable. JBoss - was always modular - and is embeddable as well.
So, what's the deal with "lightweightness"? If you ask me, EJB 3 are "ultralightweight", and POJOs actually silently disappeared. The "POJOs" are often nothing else, than JavaBeans maintained by another container, using similar techniques. Pure POJOs, without decoration, configuration and aspects are gone (or are only usable in applications without concurrent write-access to database). Even ultra-lean (and really great) Guice, will have to decorate POJOs with transactions, concurrency, inject resources etc. Perhaps we should rename EJB 3 to another term - the same story as with applets - the problem with the history :-)
NEW 2016: Java EE 7 Workshops: Bootstrap, Effective, Architectures, April, 4th-6th, Munich's Airport
On demand workshops: Java EE 7 Bootstrap, Effective Java EE 7 and NEW: Java EE 7 Testing are available for streaming