Java streaming
I have a servlet mapped to a url that does a long task and outputs some data while running.
What I want to do is call this url and see the output in real time.
Let's take this as an example:
package com.tasks;
public class LongTaskWithOutput extends HttpServlet {
private static final long serialVersionUID = 2945022862538743411L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.addHeader("Content-Type", "text/plain");
PrintStream out = new PrintStream(response.getOutputStream(), true);
for(int i=0; i<10;i++) {
out.println("# " + i);
out.flush();
try {
Thread.sleep(1000);
} catch(Exception e){}
}
}
}
The web.xml
following is stated:
...
<servlet>
<servlet-name>LongTaskServlet</servlet-name>
<servlet-class>com.tasks.LongTaskWithOutput</servlet-class>
<description>Long Task Servlet</description>
</servlet>
<servlet-mapping>
<servlet-name>LongTaskServlet</servlet-name>
<url-pattern>/longTask</url-pattern>
</servlet-mapping>
...
What's happening
If I browse localhost/myApp/longTask
, the browser makes me wait 10 seconds and then prints out all the text at once.
What is going to happen
The text should be sent to the browser as soon as it is written to the output stream, and the browser should render one line every second.
As you can see, I've already put out.flush()
in to make sure the thread is flushing every second, but it still doesn't work.
I also tried with response.flushBuffer()
, but I got the same result.
Is there a way to achieve this?
Update
As @MadConan suggested , I tried to use the output stream directly:
OutputStream out = response.getOutputStream();
for(int i=0; i<10;i++) {
out.write(("# " + i + "\n").getBytes());
out.flush();
try {
Thread.sleep(1000);
} catch(Exception e){}
}
Unfortunately, the result is the same.
source to share
You are clearing the content from the response stream, but your response is not communicated to the client. Understand it this way: you give some things to be someone, take and leave the room and pass on to someone else. Until the person leaves the room and hands it in, your package will not be delivered.
For your requirement, you can keep pushing the data to some kind of global space and then have a PULL mechanism from the client to read that space every X seconds and display the content to the client. It is also possible for the PUSH mechanism to do the same, it depends on your project whether you should use PUSH or PULL.
This basically means that in one request you cannot update the client and go back to the server and do the same over and over. The request dies after the response has been sent to the client. Then there should be another PULL request from the client or PUSH from the server.
source to share