The Servlet specification provides that a container will instantiate a single instance of my java.servlet.HttpServlet
, and invoke the service methods (doGet()
/doPost()
) from multiple worker threads.
According to normal threading rules, it is not guaranteed that assignments to instance-level fields in init(ServeltConfig)
'happen before' reads from those same fields by other threads executing doGet()
, unless someone arranges for synchronization at some point.
Probably, containers do in fact do some kind of external synchronization to ensure that work done in init()
is visible to 'subsequent' threads.
However, does the Servlet spec explicitly guarantee that I'm threadsafe? I couldn't find a guarantee like that just now, although I must admit, I haven't read the spec from end-to-end since Servlet 2.4.
EDIT
For example, since some answerers are getting things mixed up, my question is: what is it about the Servlet spec that says the following class is threadsafe?
@WebServlet (initParams = {@WebInitParam(name="b", value="true")})
public Decider extends HttpServlet {
private boolean b = false;
public void init(ServletConfig config) {
this.b = Boolean.parseBoolean(config.getAttribute("b"));
}
public void doGet(HttpServletRequest req, HttpServletResponse res) {
res.sendRedirect(b ? "/true" ? "/false");
}
}
Certainly, if I were to do:
public static void main(String[] argv) {
HttpServlet s = new Decider();
Thread t1 = new Thread(new Runnable() {
public void run() {
s.init(...);
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
s.doGet(...);
}
});
t1.start();
t2.start();
}
... then I'd have a threading bug. What makes containers necessarily different?
EDIT 2
All the answers asserting that "the container takes care of that" are certainly welcome, but my question is specifically about whether the Servlet spec guarantees that behaviour. To answer the question adequately, you've got to make reference to the Servlet spec. (Any version, I'm cool).
Declaring a static variable is useful since it states the intent of the variable. The static variable can also have an effect if you have a hierarchy of servlet classes. Mostly, if I ever include a variable I make it static due to the first reason.
So, the correct statement would be there is only one instance per JVM for every servlet, unless it implements SingleThreadModel.
Usually only one instance of the Servlet object is created. But some advanced containers might create more than one instance under certain circumstances. Even so, there is a difference between static class variables and instance variables.
When a single-threaded servlet is deployed to the Sun Java System Web Server, the servlet engine creates a servlet instance pool used for incoming requests (multiple copies of the same servlet in memory).
The servlet container creates an HttpServletRequest object and passes it as an argument to the servlet's service methods (doGet, doPost, etc). The HttpServletRequest breaks a request down into parsed elements, such as request URI, query arguments and headers. Various get methods allow you to access different parts of the request.
JUnit HttpServletRequest Example First of all, we will create a new servlet. To create that, we simply right click on project name -> New -> Other -> Servlet under Web. Click on the Next button to proceed. Next, fill in the details and click on the Finish button.
Right click on the index.html, run on server. 1. protected void doGet (HttpServletRequest req, HttpServletResponse resp): This method is called by servlet service method to handle the HTTP GET request from client.
For this, servlets provide an interface called ‘HttpSession’ Interface. The following diagram explains how Http Sessions work in servlets: Gets the HttpSession object. If the request doesn’t have a session associated with it, a new session is created Gets the session associated with the request.
This is explicitly said in the init
javadoc:
The servlet container calls the init method exactly once after instantiating the servlet. The init method must complete successfully before the servlet can receive any requests.
And if you follow servlet life cycle, it says that a servlet should be init
-ed before service
requests from multiple threads.
... then I'd have a threading bug. What makes containers necessarily different?
In your example, the init()
and doGet()
methods can overlap. This is not possible in a Servlet
container. The container takes care to do all init()
calls and other initializations before it starts handling requests. There's no issue of multithreading across those method boundaries.
You'll still have issues with shared date being used in the doXXX()
methods.
Short of looking at the source code of each container, your best bet is to see the javadoc for Servlet
(and Filter
):
This interface defines methods to initialize a servlet, to service requests, and to remove a servlet from the server. These are known as life-cycle methods and are called in the following sequence:
- The servlet is constructed, then initialized with the init method.
- Any calls from clients to the service method are handled.
- The servlet is taken out of service, then destroyed with the destroy method, then garbage collected and finalized.
To truly support the Servlet
spec, the container has to follow those rules.
This Servlet Life Cycle
is described in chapter 2.3 of the Servlet 3.0 specification document.
After the servlet object is instantiated, the container must initialize the servlet before it can handle requests from clients. Initialization is provided so that a servlet can read persistent configuration data, initialize costly resources (such as JDBC™ APIbased connections), and perform other one-time activities. The container initializes the servlet instance by calling the
init
method of the Servlet interface with a unique (per servlet declaration) object implementing the ServletConfig interface.
Important parts in bold.
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