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.
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.
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.
Yes it's thread-safe.
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.
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:
@ConcurrencyManagement(BEAN)
@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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With