Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If I assign instance fields in HttpServlet#init(ServletConfig), does the Servlet spec guarantee I can read them in doGet()?

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).

like image 443
David Bullock Avatar asked Oct 03 '13 11:10

David Bullock


People also ask

Is it good to have instance static variables in a servlet?

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.

How many instances of a servlet are there in memory are its member VARS thread safe pattern?

So, the correct statement would be there is only one instance per JVM for every servlet, unless it implements SingleThreadModel.

How many instances of servlet are created?

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.

What is instance in servlet?

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).

How do I use httpservletrequest?

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.

How do I create a HTTPServlet request In JUnit?

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.

How to handle HTTP GET request from client using Servlet?

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.

How do HTTP sessions work in servlets?

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.


2 Answers

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.

like image 60
kan Avatar answered Sep 19 '22 14:09

kan


... 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.

like image 36
Sotirios Delimanolis Avatar answered Sep 19 '22 14:09

Sotirios Delimanolis