IllegalStateException:STREAM when calling response.getWriter - servlets

This is a method that's used for handle ajax request. So the output is written to the response
public ModelAndView myAction(HttpServletRequest request, HttpServletResponse response, BindException errors) throws Exception
{
//call other methods and send the response as arg
//call getWriter on the response
}
According to this doc, I would definitely have an IllegalStateException if I call getWriter having already called getOutputStream(), so I suspect the methods I passed the response to did this although I don't really see them doing so...
The only thing for sure is that at some point, one of the methods may do response.sendError().
Does this some how call getOutputStream()?

HttpServletResponse#sendError() commits the response and send an error status code. The javadoc states
If the response has already been committed, this method throws an
IllegalStateException. After using this method, the response should be
considered to be committed and should not be written to.
In other words, after you call that method, the HTTP response has basically been sent. It makes no sense to call any of the getOutputStream() or getWriter() methods. Your Servlet container further makes it foolproof by throwing an Exception if you attempt to.

I had similar issues but I had not called sendError(), just setContentType() before that. As per this source, it can trigger the same behaviour:
I am guessing its because you have already opened the stream by
calling the resp.setContentType("text/plain"); method, and are then
trying to get a Writer object. You can either use Stream based
classes, or Writer based classes - not both.
Either remove the setContentType(), or send the response using
response.getOutputStream() method. That should solve the problem.
And indeed, it resolved the similar error for me.

Related

response.getWriter(); what is the task of this method?

I know this question has been asked before several times. But the answers are not satisfactory. I know getWriter method returns an object of PrintWriter class.Everyone has answered what it returns but I want to know what is used for?
When ever you request something from Client to Server it must maintain a format. Now in J2EE we bind the request information into an object and send it to server. That's why we need a HttpServletRequest reference in Service class. Now the server has the raw data which should be modify/calcuated/ whatever the code is that is to send back again to client and the result is kept in an object of response type.Thats why needed HttpServletResponse reference. Now in HttpServletResponse there is a method named getWriter() which binds the result into object and returns an object of PrintWriter class. Hope this helped you.

FIlterChain exception Handling

I am trying to understand Spring security which involves method security and URL based security . URL based security is completely based on Servlet Filters. There are some scenarios when Spring security deals with exception thrown by filters chain to do its work.
I know how filters are executed by Servlet Container but I am particularly interested in how filterChain handle exceptions thrown by doFilter method in filter chain.
I am particularly interested in how filterChain handle exceptions thrown by doFilter method in filter chain.
It does nothing with them. In other words, it just lets them go and bubble up. They'll eventually end up in servletcontainer's builtin exception handler which already knows how to deal with them based on <error-page> configuration in web.xml.
You can however control it yourself by placing FilterChain#doFilter() call in a try-catch block like so:
try {
chain.doFilter(request, response) {
} catch (ServletException e) {
Throwable cause = e.getRootCause();
// ... (handle it)
}
If anything else down the chain (filter, servlet, jsp, etc) throws an uncaught exception, it'll end up there.
See also:
How does server prioritize which type of web.xml error page to use?
What is the good approach to forward the exception from servlets to a jsp page?
I don't think you are able to return anything meaningful in an errorMessage in the HttpServletResponse stream when trying/catching the doFilter method like that, unless you specifically intercept the HttpServletResponse stream and call something like sendError. And that has to be done even before the call to doFilter.
I am particularly interested in how filterChain handle exceptions
thrown by doFilter method in filter chain.
But I am interested in knowing how to send a meaningful response back into the stream when the exception happens within the filterChain. Because even if there is no Exception, how would you go about handling the success response if you have already called a method like sendError before the doFilter (?)

flush() in rd.include vs rd.forward()

I have the following code snippet in my web app:
if (request.getParameter("user").equals("luke")||session == null && !(uri.endsWith("html") || uri.endsWith("LoginServlet"))) {
System.out.println("<<<----------denied------------->>>>");
pw.println("zzzzzzzzzz");
this.context.log("Unauthorized access request");
pw.flush();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//res.sendRedirect("login.html");
req.getRequestDispatcher("login.html").include(request,response);
}
When I am using flush before Forward(), it's throwing IllegalStateException (since the response is sent the moment we call flush and later we are trying to resend the response using forward) but the code works fine even after I provided flush before the rd.include(). Why doesn't it throw the exception here?
TIA
This behavior is explained in the Servlet Specification for the forward method in chapter 9.4 and for the include method in chapter 9.3.
The javadoc also explains this in a little detail.
The javadoc entry of HttpServletResponse#getWriter() states
Calling flush() on the PrintWriter commits the response.
Committing the response means writing the status line and headers and flushing whatever part of the response body is in the buffer.
The javadoc of forward states
Forwards a request from a servlet to another resource (servlet, JSP
file, or HTML file) on the server. This method allows one servlet to
do preliminary processing of a request and another resource to
generate the response.
So the forward to resource must take care of generating and committing the response. It can't do that if the response has already been committed.
The javadoc of include states
The included servlet cannot change the response status code or set
headers; any attempt to make a change is ignored.
This method just takes the content of another resource and writes it to the response. It can't do anything to headers or the status code. As such, committing before or after makes no difference.
The forward and the include are different methods, the include method allows you to add content to the response, you have a include tag in jsp, the include method is the similar but in the server.
The forward method transfer the request processing to another process (servlet, jsp) and that process must change the response, that is why you get that exception, you can't change the response before forward it.
You could check the documentation for those methods here.

Spring MVC Returns Response Before Completion of Controller Method

I have the following method which is returning an incorrect response to the browser before the method is even complete. This is in Spring 3.2.
#RequestMapping(value="/process1/createEditContract/validate", method=RequestMethod.POST)
public #ResponseBody StatusResponse validateProcess1(#ModelAttribute("contractEditForm") #Valid Process1CreateEditContractDTO dto, BindingResult bindingResult) {
StatusResponse response = new StatusResponse();
response.setSuccess(true);
if (bindingResult.hasErrors()) {
log.debug("Errors found. Processing status response");
response.setSuccess(false);
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for (FieldError fe: fieldErrors) {
response.getMessages().add(messageSource.getMessage(fe, null));
}
}
return response;
}
StatusResponse is a simple object that a javascript function in the JSP reads to generate a Javascript alert stating whether the action was successful or errors occurred. The method makes it all the way through, but as soon as it tries to write the response, I get this:
java.net.SocketException: Software caused connection abort: socket write error
I've been stuck for a day now, any help would be appreciated.
UPDATE
I rolled back from Spring 3.2 to Spring 3.1, and the wording of the error message changed enough to give me more information.
Basically, I'm getting now seeing this:
IllegalStateException: Response already committed
What I don't see is what is causing the response to commit so quickly. Maybe a conflict with the OpenSessionInViewFilter?
This error can occur when the local network system aborts a connection, such as when WinSock closes an established connection after data retransmission fails (receiver never acknowledges data sent on a datastream socket).". See this MSDN article. See also Some information about 'Software caused connection abort.
To prove which component fails I would monitor the TCP/IP communication using wireshark and look who is actaully closing the port, also timeouts could be relevant.
The javascript runs in browser, and your controller runs on server. You cannot pass a complex object from the controller to the javascript without converting it to a textual format such as xml or json.
So you should :
choose a format (say json)
add a produces="application/json" in your RequestMapping annotation
do generate json in your controller method

jetty webSocket : java.lang.IllegalStateException: Committed

I am using Jetty Websockets in my Web Application .
When i am trying to redirect to a logoff jsp , i am getting this error
oejs.ServletHandler:/test
java.lang.IllegalStateException: Committed
at org.eclipse.jetty.server.Response.resetBuffer(Response.java:1069)
at javax.servlet.ServletResponseWrapper.resetBuffer(ServletResponseWrapper.java:232)
at org.eclipse.jetty.http.gzip.GzipResponseWrapper.resetBuffer(GzipResponseWrapper.java:273)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:199)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:98)
This is the way i am redirecting
RequestDispatcher rd = request.getRequestDispatcher("logoff.jsp");
rd.forward(request, response);
This error is not reproduceble , but could you please tell me when it may occur??
java.lang.IllegalStateException: Committed
I thought I'd provide a more general explanation of what the exception means. First off, Jetty should be ashamed by the exception message. It provides little to no help to the developer unless they already know what it actually means. The exception should be something like:
java.lang.IllegalStateException: Response headers have already been sent. Are you trying to return a result after sending content?
Typically this exception happens when you go and call:
resp.getOutputStream(); // or getWriter()
and then later try to do a redirect or something:
resp.sendRedirect("/someOtherUrl");
// or
return new ModelAndView("redirect:/someOtherUrl");
Once you get the OutputStream or Writer so you can write body bytes to the client, Jetty has to commit the response and send the HTTP 200 and associated headers, so it can start returning the body bytes. Once that happens, you then can't do a redirect nor make any other changes to the status code or headers.
The proper thing to do, once you return body bytes, is to return null from the handler instead of a ModelAndView(...) or just change the handler to return void.
You also get this exception when you call the super method in your own method implementation.
Example:
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
super.doPost(req, resp); // <-- THIS IS THE PROBLEM
resp.sendRedirect("/someOtherUrl");
}
This occurs because your response has already processed a redirect request, you are trying to modify a committed response.
There are two general ways to solve this:
find out where the first redirect is and try to modify the logic to prevent the "two redirect" scenario from happening.
put a "return" after each of your redirect (personally I recommend this solution).
The reason on my side is using jetty with wrong url:
right: http://localhost:8080
wrong: http://localhost:8080/test
Consider you are running javax.servlet.Filter on Jetty server, and you face the same exception. The issue here can be described exactly as Gray's description (Thanks Gray). Typically this exception happens when you go and call:
resp.getOutputStream(); // or getWriter()
then
chain.doFilter(request, response);
If you called resp.getOutputStream();, make sure you are not using chain.doFilter(request, response); on the same request.
In my case I had some repository in my #Service and I declared it as RepositoryFoo repositoryFoo;, in the beginning of my class
I forgot to add #Autowired or even make it private, so it compiled fine and then when running I had this java.lang.IllegalStateException: Committed ... I wasted some time before figuring out the reason !

Resources