Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are EJBs thread safe and servlets not ?

As per my understanding, a servlet container creates limited instances of servlets and multiple threads of each servlet instance and reuse those threads and instances.

Because there are multiple instances of a thread, they are not "Thread-safe" (though I understand that coding them with Thread-safety is not difficult).

EJBs containers on the other hand do not create threads of EJB, but reuse EJB objects only (using pool). Since there are no multiple threads of an EJB instance, there's no question of thread safety.

My question: Why have different behavior? Is it not a good idea to make EJBs work as Servlets (thread unsafe)?

I'm sure I'm missing something and want to understand that missing part.

like image 394
Sandeep Jindal Avatar asked Jun 26 '12 22:06

Sandeep Jindal


People also ask

Are EJBs thread-safe?

Working with EJBs without any further configuration is thread-safe regardless whether you are invoking one method or multiple methods concurrently. The container cares about the serialization of calls.

Why servlets are not thread-safe?

Servlet instances are inherently not thread safe because of the multi threaded nature of the Java programming language in general. The Java Virtual Machine supports executing the same code by multiple threads. This is a great performance benefit on machines which have multiple processors.

Is stateless beans are thread-safe?

Yes it's thread-safe.

Are servlets multithreaded?

A Java servlet container / web server is typically multithreaded. That means, that multiple requests to the same servlet may be executed at the same time.


3 Answers

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.

like image 77
JB Nizet Avatar answered Oct 08 '22 09:10

JB Nizet


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.

like image 44
David Blevins Avatar answered Oct 08 '22 09:10

David Blevins


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.

like image 3
Toddius Zho Avatar answered Oct 08 '22 08:10

Toddius Zho