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