This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Should one call .close() on HttpServletResponse.getOutputStream()/.getWriter()?
Am I responsible for closing the HttpServletResponse.getOutputStream() (or the getWriter() or even the inputstream)
or should I leave it to the container ?
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
OutputStream o = response.getOutputStream();
...
o.close(); //yes/no ?
}
You indeed don't need to do so.
Thumb rule: if you didn't create/open it yourself using new SomeOutputStream(), then you don't need to close it yourself. If it was for example a new FileOutputStream("c:/foo.txt"), then you obviously need to close it yourself.
Reasons that some people still do it are just to ensure that nothing more will be written to the response body. If it would ever happen, then this will cause an IllegalStateException in the appserver logs, but this wouldn't affect the client, so the client still gets the proper response. This is also an easier debug to spot the potential problems in the request-response chain which you wouldn't see at first glance. For example, something else is appending more data to the response body somewhere further down in the chain.
Another reason which you see among starters is that they just wanted to prevent that more data is written to the response body. You see this often when JSP incorrectly plays a role in the response. They just ignore the IllegalStateExceptions in the logs. Needless to say that this particular purpose is bad.
No you don't need to close it. If you do you basically end the response to the client. After closing the stream you cannot send anything else to the client until the next request. You didn't open the stream, so you don't have to close it.
Related
i'm trying to create an asynchronous servlet, so that the client makes a request, get an answer like "process started" and stops waiting.
The servlet will start some computation and write the result on a DB and then the user will be able to check if the process is terminated and to see its result.
Well, every time i try to do this a get errors. In the request i have a Connection object, and if i pass it to a Thread and then start it, when the main servlet ends the connection gets closed and the Thread throws an Exception ('connection has already been closed').
Is there a way to just give to the client a response and tell it not to wait anymore while the servlet does all its job?
Thank you in advance!
If you were mentioning a DB Connection, why not create the Connection inner your Thread?
There exists Ajax (JavaScript) in the browser to place a call, and have success/failed callbacks received later. That would be the most regular way.
If more is required, register the request for scheduling in a queue = store something in the database. Then have a timer task (for instance from Spring) in your app that does the work. This prevents overloading, DoS.
In fact if looks like the response is fully sent to the client when you close the response output stream (or writer), and you can continue the processing inside the servlet without any threading issues. Unfortunately I could never found a confirmation that if was explicitely allowed in servlet specs, but I could do it successfully in Tomcat (was using version 7)
So provided you note it in a bold comment, your servlet code could look like:
void service(ServletRequest req, ServletResponse resp) {
OutputStream out = res.getOutputStream();
... // generate the output
out.close(); // the response is sent to client
// asynchonous processing
...
}
Obviously, the doGet method has a return type of void, so, it doesn't return anything. In this sense, I'm using the word "return" to mean send the response back to the client that requested it.
I'm trying to implement a long-polling Servlet. It would be beneficial for it not to send a response until I have something that I would like to send back. So, in the doGet method I add the connected user's ID and AsyncContext to a map:
private ConcurrentMap<String, AsyncContext> contexts = new ConcurrentHashMap<>();
//...in the doGet method when I need to add the context...
contexts.put(userId, context);
Then, when I have something to send back, I can retrieve the appropriate context and write to it's responses output stream:
AsyncContext context = contexts.get(userId);
PrintWriter writer = context.getResponse().getWriter();
writer.write("something to send to the client");
But, the client never seems to receive the response. Looking at the Network tab in the developer console of the browser, I can see the GET request is sent and then returns (with a status of 200). This occurs before I actually send something back. Which is leading me to believe that after the doGet method is finished the response is returned. And perhaps because of this, after this point, nothing can be sent to the client because the connection is not opened.
Does the doGet method send the response to the client once the method is finished executing? If this is the case, how can I keep the connection open for a long-polling effect?
To answer my own questions: Does the doGet method send the response to the client once the method is finished executing?
Yes, when the doGet (or any HttpServlet method, ex: doGet, doPost, etc.) method finishes executing it sends the response back to the client.
If this is the case, how can I keep the connection open for a long-polling effect?
Using asynchronous Servlets (which I was using, however, I found my particular problem must be elsewhere, yet these answers are still relevant to the questions asked). On the ServletRequest object call the startAsync method, like so:
AsyncContext context = request.startAsync(request, response);
"This will notify the Web Container that at the end of the request call it should free the handling thread and leave the connection open so that other thread writes the response and end the connection."Reference Link.
Also, I will add the solution to my particular problem (the client wasn't receiving the response) was because in my Servlet, I wasn't calling the complete method on the AsyncContext object:
asyncContext.complete();
Yes, the response stream is flushed and closed when doGet() finishes executing.
Keeping UI threads occupied for extended periods of time violates Java Enterprise best practice.
Recommend you rather return immediately if nothing to respond, and implement a timer on the client (browser) side to poll the server for results every so often.
I hava a problem in this code line:
resp.setBufferSize(2048);
catch this exception
java.lang.IllegalStateException: Committed or content written
resp is HttpServletResponse
I have read about this but I donĀ“t found the solution
We can't really tell you how to solve this without seeing your actual code.
But it is absolutely clear that you are calling the setBufferSize method too late. Something that your application has done to the response object prior to that call has "committed" the response.
I want a user to make a post, the data in the post is handled and the request is forwarded to a jsp-page. The jsp-page is sent back to the user but then the server should do a job. This job takes a lot of time so the user shouldn't wait for it.
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
//... get posted data ...
request.getRequestDispatcher("/page.jsp").forward(request, response);
//do-someting
}
I want the "do-something" to be done after the connection is closed and the user gets the page.jsp. Of course the "do-something" is completely serverside like updating a database etc. So the server keeps working even after the user leaves the page. I tried to flush and close the outputstream in the servlet after the forward to the jsp-page but this results in an exception. Also flushing and closing in the jsp-page results in an exception. How can I do this?
If your job (do-something) is completely independent of what should be displayed in the jsp, then you can use one of the following:
A timer
A thread (in a thread pool)
A more powerful library like Quartz which will give you powerful scheduling capabilities
let's say I have this code in javascript:
function doAnAjaxCall () {
var xhr1 = new XMLHttpRequest();
xhr1.open('GET', '/mylink', true);
xhr1.onreadystatechange = function() {
if (this.readyState == 4 && this.status==200) {
alert("Hey! I got a response!");
}
};
xhr1.send(null);
}
and let the code in the servlet be:
public class RootServlet extends HttpServlet {
public void doGet (HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.getWriter().write("What's up doc?");
resp.setStatus(200);
}
}
Will xhr1 still wait for new changes in readystate? Or it is closed as soon as it gets the first response?
If it remains open, will it lead to memory leaks/slower browser after a while and accumulating a few of those?
Should I always call resp.getWriter().close() at the end of the servlet code?
And, lastly, for the jQuery fans out there:
does $.ajax() behave as XMLHttpRequest() in that respect?
Will xhr1 still wait for new changes in readystate? Or it is closed as soon as it gets the first response? If it remains open, will it lead to memory leaks/slower browser after a while and accumulating a few of those?
Behind the scenes, it remains open. It (and the memory occupation) is however the responsibility of the webbrowser engine. It maintains a certain amount of connections in a pool which has a maximum limit per domain anyway. MSIE for example has a bug which causes them to leak away when they are still running while the user unloads (closes) the window.
Should I always call resp.getWriter().close() at the end of the servlet code?
Not necessary. The servletcontainer will close it anyway. Closing it yourself only prevents the risk of some (buggy) code further in the response chain from writing to the response body. For more detail, see this answer.
And, lastly, for the jQuery fans out there: does $.ajax() behave as XMLHttpRequest() in that respect?
It uses XMLHttpRequest under the covers (only when supported by the browser; otherwise it's the MSIE ActiveX object). It constructs a new one on every call. Open the unminified source code, Ctrl+F the jQuery.ajaxTransport( function. All the ajax handling code is almost 200 loc and it covers all possible browser specific bug fixes you can think about.