Given that you are reading a book on lightweight containers, the first question that probably comes to mind at this point is whether EJBs are even still relevant, with or without Spring.
You may not always have a choice in the matter. Many legacy projects already use EJBs. There is a good chance that any attempt to introduce Spring in such an environment means that Spring-related code will have to work with EJBs or run in an EJB container, whether on an ongoing or a transition basis, for a number of reasons. There is usually not enough time to stop delivering new features and do a complete rewrite to new technology. Additionally, even if there is time, it's generally been proven in practice that making changes in shorter iterations is more effective than doing the same thing in longer iterations, in terms of reducing the risk of failure to meet goals or requirements. Finally, there may be political reasons. Regardless of architecture, we have all been in situations where a technology was mandated for reasons beyond our control, and a change is impossible or requires time to effect. In such an environment, where EJBs are actively used, Spring can still be a great benefit, as we explain later in this chapter.
When you do have a choice as to whether to use EJBs or not, that choice is somewhat more complex. This book shows enough of the Spring lightweight container approach that if you are already equally familiar with EJBs, it should be relatively easy to come to an informed opinion about the strengths and weaknesses of each approach, in terms of agility, effort, feature set, and to some extent, performance. It's not within the scope of this book to attempt to answer the lightweight container versus EJB general question in great detail. However, J2EE without EJB by Rod Johnson and Juergen Hoeller (Wrox, 2004) devotes a detailed chapter to this topic, and most of that book talks about general architectural concerns and strategies that have a direct or indirect relationship to a decision to use or not use EJBs. Additionally, Chapter 15 in that book presents the results of benchmarks comparing a lightweight Spring-based approach to an EJB-based approach.
Generally, we feel that time has proven that the EJB approach up to version 2.1 of the spec is not agile enough, is too complex, and in most cases does not provide any advantages while having a number of disadvantages compared to a lightweight container approach. One area where EJBs might still wisely be chosen on technical merits is when cluster-safe remoting is needed, perhaps for high-availability, stateful, backend services. Several commercial EJB container implementations have well-implemented, cluster-aware remoting of EJBs, which works very well. However, remoting still has large performance implications compared to local invocations, and the number of applications that actually need this is typically fairly limited. In this chapter, you'll see how to use Spring's EJB access proxies so that you may switch back and forth from a POJO, local EJB, or remote EJB implementation of a service without the client being aware of or coupled to the implementation type. This means that even if there exists the future possibility of needing to use EJB remoting, that is no longer a criterion for choosing to use remote EJBs from the beginning. Even when there is a need to use remoting, this pluggability means that it is possible to use one of the excellent lighter-weight Spring remoting options, and switch to the heavier-weight EJB remoting only if there is an actual need.
The future direction of the EJB spec is actually one of the many reasons that you might want to choose to use a Spring-only approach instead of a Spring + EJB approach at this point. At the time of this writing, the EJB 3.0 working group has released a draft spec for EJB 3.0 that essentially throws away almost everything in EJB 2.1 (keeping the old functionality only in a compatibility layer), in favor of a POJO / lightweight IoC container model that is similar to (but less powerful than) Spring. On the persistence side, the EJB 3.0 persistence spec, which will also run outside of J2EE containers, in normal J2SE apps, appears to be most similar to Hibernate, with influences also from the JDO spec and TopLink ORM product. Based on the direction the EJB specification is moving in, basing your application on a POJO model tied together by the Spring container is actually the best way of ensuring that you'll have the easiest migration path to EJB 3.0, should you want to take that route.