Skip to content

Conversation

@afarber
Copy link
Contributor

@afarber afarber commented Jan 16, 2026

Closes #11765

This PR adds EventSourceHandler to jetty-core/jetty-server for SSE support without Servlet API dependencies.

  • Abstract handler with newEventSource(Request) factory method
  • EventSource interface with onOpen(Emitter) and onClose() callbacks
  • Emitter with event(), data(), comment(), close() methods
  • Configurable heartbeat period for connection keep-alive
  • Documentation in programming guide

@afarber
Copy link
Contributor Author

afarber commented Jan 16, 2026

Successfully tested on my Macbook M1 macOS 26.2 by running the curl -N -H "Accept: text/event-stream" http://localhost:8080/ command against the EventSourceDemo.java listed below:

image
package org.eclipse.jetty.server.handler;

import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;

public class EventSourceDemo
{
    public static void main(String[] args) throws Exception
    {
        Server server = new Server();
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(8080);
        server.addConnector(connector);

        EventSourceHandler handler = new EventSourceHandler()
        {
            {
                setHeartBeatPeriod(Duration.ofSeconds(15));
            }

            @Override
            protected EventSource newEventSource(Request request)
            {
                return new EventSource()
                {
                    private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
                    private final AtomicInteger counter = new AtomicInteger();

                    @Override
                    public void onOpen(Emitter emitter) throws IOException
                    {
                        emitter.comment("Connected to Jetty SSE demo");
                        emitter.data("Welcome! You will receive events every 2 seconds.");

                        executor.scheduleAtFixedRate(() ->
                        {
                            try
                            {
                                int n = counter.incrementAndGet();
                                emitter.event("tick", "Event #" + n + " at " + Instant.now());
                            }
                            catch (IOException e)
                            {
                                executor.shutdown();
                            }
                        }, 2, 2, TimeUnit.SECONDS);
                    }

                    @Override
                    public void onClose()
                    {
                        executor.shutdown();
                        System.out.println("Client disconnected");
                    }
                };
            }
        };

        server.setHandler(handler);
        server.start();
        System.out.println("SSE Demo server started on http://localhost:8080/");
        System.out.println("Test with: curl -N -H 'Accept: text/event-stream' http://localhost:8080/");
        server.join();
    }
}

@afarber afarber force-pushed the 11765-implement-event-source-handler branch from 67f42eb to a24ff42 Compare January 17, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce EventSourceHandler

1 participant