Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpServletRequest.getParameter losing parameter

Tags:

java

servlets

I am confused that the HttpServletRequest.getParameter will return null sometimes while I really include the parameter in my request.

Test program below:

HelloServlet.java:

public class HelloServlet extends HttpServlet {
    private static Executor logExecutor = Executors.newFixedThreadPool(5);

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        logExecutor.execute(new Task(req));
    }
}

class Task implements Runnable {
    private HttpServletRequest req;

    public Task(HttpServletRequest req) {
        this.req = req;
    }

    @Override
    public void run() {
        System.out.println(String.format("a=%s b=%s c=%s",
                req.getParameter("a"), req.getParameter("b"),
                req.getParameter("c")));
    }
}

Map this servlet to /hello in the web.xml

Start the servlet in tomcat or jetty, launch the request with the shell scripts:

#/bin/sh

for i in {1..100}
do
        curl -i -X GET "http://localhost:8080/hello?a=a&b=b&c=c"
done

the server log shows that some parameter in some request maybe null and this case occured with no regular pattern. Such as:

a=a b=b c=c
a=a b=b c=c
a=null b=null c=null
a=null b=null c=null
a=null b=null c=null
a=null b=b c=c
a=null b=null c=c
a=a b=b c=c
a=a b=b c=c
a=a b=b c=c
a=a b=b c=c
a=null b=null c=null
a=a b=b c=c
a=null b=b c=c

I found the reason is that I cannot hold the HttpServletRequest instance for my Executor. So I want to know the reason why! Why the action I hold a HttpServletRequest instance in one requst may affect the other requests.

like image 536
terry Avatar asked Mar 27 '26 13:03

terry


1 Answers

As far as I know, I think you can not access request parameters once it has finished.

You are passing the HttpServletRequest to a Thread. Sometimes it'll be executed before the request has finished and sometimes later. Therefore, sometimes you get the parameters and sometimes they are null.

Avoid handling HttpServletRequest outside doGet or doPost. You should copy the information from the original request into a separate data structure for later processing.

For example:

public class HelloServlet extends HttpServlet {
    private static Executor logExecutor = Executors.newFixedThreadPool(5);

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String data = String.format("a=%s b=%s c=%s",
                req.getParameter("a"), req.getParameter("b"),
                req.getParameter("c"));
        logExecutor.execute(new Task(data));
    }
}

class Task implements Runnable {
    private String data;

    public Task(String data) {
        this.data = data;
    }

    @Override
    public void run() {
        System.out.println(data);
    }
}

EDIT:

Extract from Java Servlet Specification:

3.11 Lifetime of the Request Object

Each request object is valid only within the scope of a servlet’s service method, or within the scope of a filter’s doFilter method, unless the asynchronous processing is enabled for the component and the startAsync method is invoked on the request object. In the case where asynchronous processing occurs, the request object remains valid until complete is invoked on the AsyncContext. Containers commonly recycle request objects in order to avoid the performance overhead of request object creation. The developer must be aware that maintaining references to request objects for which startAsync has not been called outside the scope described above is not recommended as it may have indeterminate results.

like image 62
Tobías Avatar answered Mar 29 '26 03:03

Tobías



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!