=== Server-Sent Events

https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events[Server-Sent Events] (SSE) is a mechanism that allows the server to push data to the client once a connection is established. Unlike WebSockets, SSE is strictly unidirectional: the server can send data to the client, but not the other way around.

.Server-Sent Events
[source,java,role="primary"]
----
{
  sse("/sse", sse -> {            // <1>
    sse.send("Welcome");          // <2>
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  sse("/sse") {                   // <1>
    sse.send("Welcome")           // <2>
  }
}
----

<1> Connection established.
<2> Send a message to the client.

==== Message Options

Additional message properties (like custom events, IDs, and retry timeouts) are available via the javadoc:ServerSentMessage[] class:

.Server-Sent Message
[source,java,role="primary"]
----
{
  sse("/sse", sse -> {
    sse.send(
        new ServerSentMessage("...")
            .setEvent("myevent")
            .setId("myId")
            .setRetry(1000)
    );
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  sse("/sse") {
    sse.send(ServerSentMessage("...").apply {
        event = "myevent"
        id = "myId"
        retry = 1000
    })
  }
}
----

For details on how these options are interpreted by the browser, see the MDN documentation on the https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format[Event stream format].

==== Connection Lost

The `sse.onClose(Runnable)` callback allows you to clean up and release resources when the connection ends. A connection is considered closed when you explicitly call `sse.close()` or when the remote client disconnects.

.Connection Lost
[source,java,role="primary"]
----
{
  sse("/sse", sse -> {
    sse.onClose(() -> {
      // Clean up resources
    });
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  sse("/sse") {
    sse.onClose {
      // Clean up resources
    }
  }
}
----

==== Keep Alive

You can use the keep-alive feature to prevent idle connections from timing out or being dropped by intermediate proxies:

.Keep Alive
[source,java,role="primary"]
----
{
  sse("/sse", sse -> {
    sse.keepAlive(15, TimeUnit.SECONDS);
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  sse("/sse") {
    sse.keepAlive(15, TimeUnit.SECONDS)
  }
}
----

This example sends a `:` message (an empty SSE comment) every 15 seconds to keep the connection active. If the client drops the connection, the `sse.onClose` event will be fired.

This feature is especially useful for quickly detecting closed connections without having to wait until your application tries to send a real event. (However, if your application already pushes data frequently—e.g., every few seconds—enabling `keepAlive` is generally unnecessary).
