Why are EJBs thread safe and servlets not ? Why are EJBs thread safe and servlets not ? multithreading multithreading

Why are EJBs thread safe and servlets not ?


Probably because they were not designed with the same goals in mind.

The servlet API is a simple API, very close to the HTTP protocol, on top of which you can build applications or frameworks. The HTTP protocol being completely stateless, I guess it made sense to also build an API that is stateless. Several frameworks built on top of the servlet API (Stripes, for example), use one instance of Action per request, which is not used concurrently.

EJBs are a much more complex and high-level framework, designed to implement transactional business-logic as simply as possible. It's more heavyweight, and has stateful components. These obviously need to be thread-safe. I guess it was thus natural to make stateless beans thread-safe as well.

It should be noted that Spring beans, for example, are singletons by default, and must thus follow the same rules as servlets. So multiple designs are possible to provide more or less the same functionality.

Threads have nothing to do with a performance optimization. If you need to handle 3 requests concurrently, you need 3 threads, whether the request goes to a servlet or to an EJB.


The shortest answer to your question is of course it is a good idea to make it possible for EJBs to work like Servlets and in EJB 3.1 we added a component that can do exactly that: @Singleton

An @Singleton bean can be multi-threaded like a servlet, by either:

  • Using @ConcurrencyManagement(BEAN)
  • Using @ConcurrencyManagement(CONTAINER) along with @Lock(READ) on methods where concurrency is desired and @Lock(WRITE) on methods that are not thread safe.

One other thing that Servlets have had for years that EJBs never had was <load-on-startup> which allows a Servlet to load eagerly and do work at application start.

To match the Servlet <load-on-start> we added the @Startup annotation which can be added to any @Singleton EJB and will cause it to start when the application starts. These beans will have their @PostConstruct method called when the application starts and their @PreDestroy called when the application shuts down.

Rather than use a number (<load-on-startup>1</load-on-startup>) to dictate the order in which beans annotated with @Startup start, you can annotate beans with @DependsOn and specify a list of beans that need to start before the annotated bean.

And a far less known and understood aspect we did in EJB 3.1 to align Servlets and EJBs was of course to allow EJBs to be packaged inside of .war files -- that's not the less known part -- and when we did that we quietly changed the definition of java:comp/env to match the Servlet approach.

Prior to EJB 3.1 there was no possible way to have two EJBs share a java:comp/env namespace (java:comp/env is bean-scoped in the EJB spec). Servlets, by contrast, never had any way for individual Servlets to have their own private java:comp/env namespace (java:comp/env is module-scoped in the Servlet spec). So in EJB 3.1 an EJB that is packed in a war will have the same module-scoped java:comp/env namespace as all other Servlets and EJBs in the webapp, which is a pretty big contrast to the bean-scoped java:comp/env namespace that EJBs get when packed in an EAR outside of a war. We debated on that one for weeks.

Nice little bit of beer-time trivial to quiz your friends with.


Your best answer is straight out of the Javadoc for the javax.servlet.SingleThreadedModel interface:

Deprecated. As of Java Servlet API 2.4, with no direct replacement.

public interface SingleThreadModel

Ensures that servlets handle only one request at a time. This interface has no methods.

If a servlet implements this interface, you are guaranteed that no two threads will execute concurrently in the servlet's service method. The servlet container can make this guarantee by synchronizing access to a single instance of the servlet, or by maintaining a pool of servlet instances and dispatching each new request to a free servlet.

Note that SingleThreadModel does not solve all thread safety issues. For example, session attributes and static variables can still be accessed by multiple requests on multiple threads at the same time, even when SingleThreadModel servlets are used. It is recommended that a developer take other means to resolve those issues instead of implementing this interface, such as avoiding the usage of an instance variable or synchronizing the block of the code accessing those resources. This interface is deprecated in Servlet API version 2.4.