Server Side Events (SSE) in Java

I saw an excellent question on StackOverflow about implementing server side events using Servlet 3.0

Here is a full working example (Servlet 3.0 / Java EE 6) based on my answer

Some notes:

  1. it handles “browser tab / window closed” via out.checkError() that also calls flush()
  2. I wrote it quickly, so I’m sure it can be improved, just a POC, don’t use in production before testing

Servlet: (omitted imports for brevity)

@WebServlet(urlPatterns = {"/mySSE"}, asyncSupported = true)
public class MyServletSSE extends HttpServlet {

  private final Queue<AsyncContext> longReqs = 
      new ConcurrentLinkedQueue<>();
  private ScheduledExecutorService service;

  public void init(ServletConfig config) throws ServletException {
    final Runnable notifier = new Runnable() {
      public void run() {
        final Iterator<AsyncContext> iterator = longReqs.iterator();
        //not using for : in to allow removing items while iterating
        while (iterator.hasNext()) {
          AsyncContext ac =;
          Random random = new Random();
          final ServletResponse res = ac.getResponse();
          PrintWriter out;
          try {
            out = res.getWriter();
            String next = "data: " + 
              String.valueOf(random.nextInt(100) + 1) +
              "num of clients = " + longReqs.size() + "\n\n";
            //checkError calls flush, 
            //and flush() does not throw IOException
            if (out.checkError()) { 
          } catch (IOException ignored) {
    service = Executors.newScheduledThreadPool(10);
    service.scheduleAtFixedRate(notifier, 1, 1, TimeUnit.SECONDS);

  public void doGet(HttpServletRequest req, 
       HttpServletResponse res) {

    final AsyncContext ac = req.startAsync();
    ac.setTimeout(60 * 1000);
    ac.addListener(new AsyncListener() {
      @Override public void onComplete(AsyncEvent event) throws 
        IOException {longReqs.remove(ac);}
      @Override public void onTimeout(AsyncEvent event) throws 
        IOException {longReqs.remove(ac);}
      @Override public void onError(AsyncEvent event) throws 
        IOException {longReqs.remove(ac);}
      @Override public void onStartAsync(AsyncEvent event) throws 
         IOException {}


<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
        <meta http-equiv="Content-Type" 
           content="text/html; charset=UTF-8">
        <title>JSP Page</title>
            function test() {
                var source = new EventSource('mySSE');
                source.onopen = function(event) {
                    console.log("eventsource opened!");

                source.onmessage = function(event) {
                    var data =;
                    document.getElementById('sse').innerHTML += 
               + "<br />";
            window.addEventListener("load", test);
        <h1>Hello SSE!</h1>
        <div id="sse"></div>

Now read this

Why Java Is Still Relevant

Or why it’s not a bad idea learning it even if you hate it (migrated from Java is probably one of the most “love to hate” languages out there. According to this HN poll it is the 2nd most hated... Continue →