Change this line
writer.write("data: "+ i +"
");
to
writer.write("data: "+ i +"
");
BTW, your code will have a serious performance issue because it will hold a thread until all events are sent.Please use Asynchronous processing API instead. e.g.
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AsyncContext actx = req.startAsync();
actx.setTimeout(30*1000);
//save actx and use it when we need sent data to the client.
}
Then we can use AsyncContext later
//write some data to client when a certain event happens
actx.getResponse().getWriter().write("data: " + mydata + "
");
actx.getResponse().getWriter().flush();
if all events sent we can close it
actx.complete();
UPDATE 1:
We need close the event source at browser if we do not want browser reconnect the server again when server completes the response.
eventSource.close();
Another method maybe helps, viz. we set a quite large retry time but I have not tried it, e.g.
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AsyncContext actx = req.startAsync();
actx.getResponse().getWriter().write("retry: 36000000000
"); // 10000 hours!
actx.getResponse().getWriter().flush();
//save actx and use it when we need sent data to the client.
}
UPDATE 2:
I think Websocket maybe is better for your case.
UPDATE 3: (answer the questions)
- What is actually happening on the server? In normal scenarios, tomcat creates a thread to handle every request. What is happening now?
If use NIO connector which is default in Tomcat 8.0.X, within the whole processing cycle HTTP I/O about a request won't hold a thread. If use BIO a thread will be hold until the whole processing cycle completes. All threads are from a thread pool, tomcat won't create a thread for each request.
- What is the correct way to ensure that the event stream is sent only once to the same connection/browser session?
Do eventSource.close()
at browser side is the best choice.
- What is the correct way to ensure that the event stream is closed and no resource overhead incurs on the server?
Do not forget to invoke AsyncContext.complete() at server side.
- How to differentiate between GET and POST requests. Why did it choose GET?
The EventSource API in a browser only supports GET requests but at the server side there 's no such restriction.
SSE is mainly used to receive events data from server. If a event happens the browser can receive it in time and no need to create a new request to poll it.
If you need full-duplex communication try WebSocket instread of SSE.
- Is it too early to use SSE on Tomcat? Any performance issues?
There should be no performance issues if we use NIO connector & Asynchronous processing API. I don't know whether Tomcat NIO connector is mature or not but something will never be known unless we try it.