SSE enables real-time server-to-client streaming. Perfect for notifications, live dashboards, and activity feeds. Automatic reconnection included.
@Controller
public class NotificationController extends BaseController {
@SSE(value = "/notifications/stream", name = "notifications.stream")
public Object stream(Request req, Response res) throws Exception {
res.raw().setCharacterEncoding("UTF-8");
PrintWriter writer = res.raw().getWriter();
try {
for (int i = 0; i < 10; i++) {
String notification = String.format(
"{\"type\":\"info\",\"message\":\"Event %d\"}", i
);
writer.write("data: " + notification + "\n\n");
writer.flush();
Thread.sleep(5000);
}
} catch (Exception e) {
// Client disconnected
} finally {
writer.close();
}
return null;
}
}
Each event must end with two newlines (\n\n).
// Simple text
writer.write("data: Hello World\n\n");
// JSON (recommended)
writer.write("data: {\"user\":\"Alice\",\"message\":\"Hi!\"}\n\n");
// Named event
writer.write("event: notification\n");
writer.write("data: {\"text\":\"New message\"}\n\n");
const eventSource = new EventSource('/notifications/stream');
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Notification:', data);
};
eventSource.onerror = () => {
// Automatically reconnects
};
// Close when done
eventSource.close();
Always set UTF-8 encoding at the start of your handler to avoid charset issues:
res.raw().setCharacterEncoding("UTF-8");