13

Is it possible to create a server sent event using java servlets so that a client could receive updates using:

 <script>
   var source = new EventSource('/events');
   source.onmessage = function(e) {
     document.body.innerHTML += e.data + '<br>';
   };
 </script>

All examples I have found on the web are using PHP but I would assume that it should work using Java's HTTP Servlet.

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
Chris
  • 9,209
  • 16
  • 58
  • 74
  • You are looking for the HTML5 feature "Server-Sent Events" - right? http://today.java.net/article/2010/03/31/html5-server-push-technologies-part-1 – Robert Jun 24 '11 at 11:14
  • yes.. and the event should be created using a java servlet – Chris Jun 24 '11 at 11:18
  • Servlets can only answer an incoming HTTP request. They are not designed to hold a connection open. You can do it but I assume that your server will run very fast out of worker threads if you do so. – Robert Jun 24 '11 at 11:45
  • 1
    Servlets can hold the connection open--just don't return from the doGet/doPost methods (and obviously, don't manually close any streams). But like Robert said, you usually have a limited pool of connections allowed to you by your web server. Once you run out of those, you can't process any new connections until you start closing the old ones. – Jack Edmonds Jun 24 '11 at 12:37
  • 1
    This may help. http://blog.maxant.co.uk/pebble/2011/06/21/1308690720000.html – Varun Jun 24 '11 at 12:54
  • The answer in [this question (link)](http://stackoverflow.com/questions/8958098/how-to-implement-server-sent-events-in-jee6) is far more useful than any here, it offers an example of what you probably actually want to do: asynchronous responses. – lpd Dec 04 '16 at 12:53

3 Answers3

7

this does the trick.

HTML

<!DOCTYPE html>


<html>
<body onload ="registerSSE()" >
    <script>

        function registerSSE()
        {
            alert('test 1');
            var source = new EventSource('http://frewper:8080/hello/sse');  
            alert('Test2');
            source.onmessage=function(event)
            {
                document.getElementById("result").innerHTML+=event.data + "<br />";
            };

            /*source.addEventListener('server-time',function (e){
                alert('ea');
            },true);*/
        }
    </script>
    <output id ="result"></output>

</body>
</html>

Servlet :

import java.io.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;




public class sse extends HttpServlet
{
public void doPost(HttpServletRequest request, HttpServletResponse response)
{
    try
    {
        System.out.println("SSE Demo");
        response.setContentType("text/event-stream");

        PrintWriter pw = response.getWriter();
        int i=0;
        while(true)
        {

            i++;
            pw.write("event: server-time\n\n");  //take note of the 2 \n 's, also on the next line.
            pw.write("data: "+ i + "\n\n");
            System.out.println("Data Sent!!!"+i);
            if(i>10)
            break;
        }
        pw.close();

    }catch(Exception e){
        e.printStackTrace();
    }
}

public void doGet(HttpServletRequest request,HttpServletResponse response)  
{
    doPost(request,response);
}

}
frewper
  • 1,385
  • 6
  • 18
  • 44
  • 1
    I tried it on JDK 1.6.0_25 and chrome browser using Jetty but it doesn't seem to work. the servlet gets the request and the "Data Sent" message is printed on console but the web page shows no response. What JDK version and browser did you use? Im new to this whole thing. – DPD Jun 28 '12 at 11:44
  • used jdk 1.6.0_24, i used tomcat for this, and it worked perfectly fine. Also Check if your browser supports 'sse'. preferably use chrome or the latest version of firefox. – frewper Jul 10 '12 at 06:25
  • I get an error "EventSource's response has a charset ("iso-8859-1") that is not UTF-8. Aborting the connection." which I think was the default encoding. Add `response.setCharacterEncoding ( "UTF-8" );` – Bakudan Aug 21 '12 at 12:12
  • please @frewper the code in your answer is not working with me. I create the two files but I ask if I should include some librairies ?? please answer – Souad Jun 21 '13 at 22:41
  • 1
    I had to add `response.flushBuffer()` after writing to the PrintWriter. Otherwise the messages might not be sent immediately, but all at once when the doPost method completes. – mihca Nov 01 '19 at 09:39
4

Server-Sent Events is a HTML5 feature. We say "HTML5", therefore it's just client side feature. So long server can set https respnse header "text/event-stream;charset=UTF-8","Connection", "keep-alive", then it is supported by server. You can set such header with Java Servlet. Here you can find a step for step guide on SSE with servlet

1

I have created a very simple library that can be integrated within plain Java Servlets in Asynchronous mode, so no extra server threads are required for each client: https://github.com/mariomac/jeasse

It integrates the SseDispatcher (for point-to-point SSEs) and SseBroadcaster (for event broadcasting). An example of use:

public class TestServlet extends HttpServlet {

SseBroadcaster broadcaster = new SseBroadcaster();

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    Scanner scanner = new Scanner(req.getInputStream());
    StringBuilder sb = new StringBuilder();
    while(scanner.hasNextLine()) {
        sb.append(scanner.nextLine());
    }
    System.out.println("sb = " + sb);
    broadcaster.broadcast("message",sb.toString());
}

//http://cjihrig.com/blog/the-server-side-of-server-sent-events/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    broadcaster.addListener(req);
}
}
Mario
  • 1,661
  • 13
  • 22
  • Looks interesting. But why did you license it LGPL (instead of e.g. Apache 2) ? – Tom Fennelly Dec 30 '15 at 18:42
  • @TomFennelly I basically picked up "randomly" a license that can be freely used without restrictions on the derived code. Do you recommend me to use another? Is there any disadvantage in the LGPL? – Mario Dec 31 '15 at 10:39
  • In terms of being business friendly, Apache 2 is less viral in terms of restrictions is places on people that use it in products etc. – Tom Fennelly Jan 01 '16 at 11:07