Search code examples
javaserver-sent-eventsundertow

Undertow 2.X ServerSentEventHandler not streaming data to client


I have the following Undertow 2.x ServerSentEventHandler code

public class SimpleServer {

  public static void main(String[] args) {
    Undertow server = Undertow.builder()
            .addHttpListener(8080, "localhost")
            .setHandler(new ServerSentEventHandler((connection, lastEventId) -> {

                for (int i = 0; i < 10; i++) {
                    System.out.println("LastEventId: " + lastEventId + ", i: " + i);
                    connection.send("Numbers :: " + i);

                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            })).build();
    server.start();
  }
}

with the following maven dependency

    <dependency>
        <groupId>io.undertow</groupId>
        <artifactId>undertow-core</artifactId>
        <version>2.3.12.Final</version>
    </dependency>
    <dependency>
        <groupId>com.networknt</groupId>
        <artifactId>server</artifactId>
        <version>0.1.1</version>
    </dependency>

When I hit the API, I see the following logs on the console

LastEventId: null, i: 0
LastEventId: null, i: 1
LastEventId: null, i: 2
LastEventId: null, i: 3
LastEventId: null, i: 4
LastEventId: null, i: 5
LastEventId: null, i: 6
LastEventId: null, i: 7
LastEventId: null, i: 8
LastEventId: null, i: 9

After all these logs are printed then I get all the Numbers at the same time (instead of each number being streamed as soon as its available) on the Browser. I have tried using Postman, curl and still the behavior is the same. I added the "no-cache" header in the response headers but no use. Does anyone know how do I make it stream the data from server to client? Does it have anything to do with buffering/caching, etc? Also, I am unaware why the lastEventId is always null.


Solution

  • Running the streaming logic on a different thread resolved the issue.

    public class SimpleServer {
    
      public static void main(String[] args) {
         ExecutorService executorService = Executors.newCachedThreadPool();
         Undertow server = Undertow.builder()
            .addHttpListener(8080, "localhost")
            .setHandler(new ServerSentEventHandler((connection, lastEventId) -> {
              executorService.submit(() -> {
                for (int i = 0; i < 10; i++) {
                    System.out.println("LastEventId: " + lastEventId + ", i: " + i);
                    connection.send("Numbers :: " + i);
    
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }})).build();
         server.start();
     }
    }