We've had some issues with AsyncServlets, and so we looked into SSE and WebSockets.
All the tomcat examples of SSE look like:
@WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//content type must be set to text/event-stream
response.setContentType("text/event-stream");
//cache must be set to no-cache
response.setHeader("Cache-Control", "no-cache");
//encoding is set to UTF-8
response.setCharacterEncoding("UTF-8");
PrintWriter writer = response.getWriter();
for(int i=0; i<10; i++) {
System.out.println(i);
writer.write("data: "+ i +"\n\n");
writer.flush();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
writer.close();
}
}
However, I want to keep the connection for long running periods, hopefully without having to keep the thread handling the request alive. Here's an example of receiving information from a PubSubHub and wanting to push it to browsers.
@WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//content type must be set to text/event-stream
response.setContentType("text/event-stream");
//cache must be set to no-cache
response.setHeader("Cache-Control", "no-cache");
//encoding is set to UTF-8
response.setCharacterEncoding("UTF-8");
final PrintWriter writer = response.getWriter();
PublishSubsribeHub.getInstance().subscribe("TestData", new Callback(String msg){
public void run(){
writer.write("data:"+msg);
writer.flush(); // this throws NullPointerException since undeline HttpServletResponse is closed
});
}
Like mentioned in the comment above, at the point data is ready and received through PublishSubsribeHub, the connection is already closed.
The way to "fix" this is to use response.startAsync() which keeps the connection open.
However, our problems were exactly with this mechanism "asyncContext" / "asyncServlet". So wondering (before I switch to Tomcat's WebSocket impl) if there is any other way to support async push messages using Tomcat8.5 or Tomcat9, maybe using HTTP/2 spec.
Thank you
If it is feasible in the context of your project, consider using jersey library in order to enable SSE functionality.
Jersey is a popular, easy-to-use and well documented solution. Additionally, the documentation contains clear examples of how to use the libraries. You can find such an example below.
Broadcaster example
This specific example uses a broadcaster which:
Running the example
In order to run the example, follow these steps:
-
The above solution was tested with Tomcat 7, 8, 8.5. The jersey version used: 2.x