public abstract class Sse extends Object implements AutoCloseable
Server-Sent Events (SSE) is a mechanism that allows server to push the data from the server to the client once the client-server connection is established by the client. Once the connection is established by the client, it is the server who provides the data and decides to send it to the client whenever new chunk of data is available.
{
sse("/path", sse -> {
// 1. connected
sse.send("data"); // 2. send/push data
});
}
Simple, effective and easy to use. The callback will be executed once when a new client is connected. Inside the callback we can send data, listen for connection close events, etc.
There is a factory method event(Object)
that let you set event attributes:
{
sse("/path", sse -> {
sse.event("data")
.id("id")
.name("myevent")
.retry(5000L)
.send();
});
}
Beside raw/string data you can also send structured data, like json
, xml
, etc..
The next example will send two message one in json
format and one in text/plain
format:
{
use(new MyJsonRenderer());
sse("/path", sse -> {
MyObject object = ...
sse.send(object, "json");
sse.send(object, "plain");
});
}
Or if your need only one format, just:
{
use(new MyJsonRenderer());
sse("/path", sse -> {
MyObject object = ...
sse.send(object);
}).produces("json"); // by default always send json
}
We provide request access via two arguments callback:
{
sse("/events/:id", (req, sse) -> {
String id = req.param("id").value();
MyObject object = findObject(id);
sse.send(object);
});
}
The onClose(Throwing.Runnable)
callback allow you to clean and release resources on connection close. A connection is closed by calling close()
or when the client/browser close the connection.
{
sse("/events/:id", sse -> {
sse.onClose(() -> {
// clean up resources
});
});
}
The close event will be generated if you try to send an event on a closed connection.
The keep alive time feature can be used to prevent connections from timing out:
{
sse("/events/:id", sse -> {
sse.keepAlive(15, TimeUnit.SECONDS);
});
}
The previous example will sent a ':'
message (empty comment) every 15 seconds to keep the connection alive. If the client drop the connection, then the onClose(Throwing.Runnable)
event will be fired it.
This feature is useful when you want to detect onClose(Throwing.Runnable)
events without waiting for the next time you send a new event. But for example, if your application already generate events every 15s, then the use of keep alive is useless and you can avoid it.
The require(Class)
methods let you access to application services:
{
sse("/events/:id", sse -> {
MyService service = sse.require(MyService.class);
});
}
The next example will generate a new event every 60s. It recovers from a server shutdown by using the lastEventId()
and clean resources on connection close.
{
// creates an executor service
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
sse("/events", sse -> {
// if we go down, recover from last event ID we sent. Otherwise, start from zero.
int lastId = sse.lastEventId(Integer.class).orElse(0);
AtomicInteger next = new AtomicInteger(lastId);
// send events every 60s
ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> {
Integer id = next.incrementAndGet();
Object data = findDataById(id);
// send data and id
sse.event(data).id(id).send();
}, 0, 60, TimeUnit.SECONDS);
// on connection lost, cancel 60s task
sse.onClose(() -> {
future.cancel(true);
});
});
}
Modifier and Type | Class and Description |
---|---|
static class |
Sse.Event
Event representation of Server sent event.
|
static interface |
Sse.Handler
Server-sent event handler.
|
static interface |
Sse.Handler1
Single argument event handler.
|
Constructor and Description |
---|
Sse() |
Modifier and Type | Method and Description |
---|---|
void |
close()
Close the connection and fire an onClose(Throwing.Runnable) event.
|
Sse.Event |
event(Object data)
Factory method for creating Sse.Event instances.
|
String |
id()
A unique ID (like a session ID).
|
Sse |
keepAlive(int time, TimeUnit unit)
The keep alive time can be used to prevent connections from timing out:
|
Sse |
keepAlive(long millis)
The keep alive time can be used to prevent connections from timing out:
|
Optional<String> |
lastEventId()
Server sent event will send a Last-Event-ID header if the server goes down.
|
<T> Optional<T> |
lastEventId(Class<T> type)
Server sent event will send a Last-Event-ID header if the server goes down.
|
Sse |
onClose(org.jooby.funzy.Throwing.Runnable task)
Listen for connection close (usually client drop the connection).
|
<T> T |
require(Class<T> type)
Ask Guice for the given type.
|
<T> T |
require(com.google.inject.Key<T> key)
Ask Guice for the given type.
|
<T> T |
require(String name, Class<T> type)
Ask Guice for the given type.
|
<T> T |
require(com.google.inject.TypeLiteral<T> type)
Ask Guice for the given type.
|
CompletableFuture<Optional<Object>> |
send(Object data)
Send an event.
|
CompletableFuture<Optional<Object>> |
send(Object data, MediaType type)
Send an event and set media type.
|
CompletableFuture<Optional<Object>> |
send(Object data, String type)
Send an event and set media type.
|
@Nonnull public String id()
@Nonnull public Optional<String> lastEventId()
@Nonnull public <T> Optional<T> lastEventId(Class<T> type)
T
- Event id type.
type
- Last event id type.
@Nonnull public Sse onClose(org.jooby.funzy.Throwing.Runnable task)
task
- Task to run.
@Nonnull public CompletableFuture<Optional<Object>> send(Object data, String type)
sse.send(new MyObject(), "json");
sse.send(new MyObject(), "json").whenComplete((id, x) -> {
if (x == null) {
handleSuccess();
} else {
handleError(x);
}
});
The id
of the success callback correspond to the Sse.Event.id()
.
data
- Event data.
type
- Media type, like: json, xml.
Sse.Event.id()
.
@Nonnull public CompletableFuture<Optional<Object>> send(Object data, MediaType type)
sse.send(new MyObject(), "json");
sse.send(new MyObject(), "json").whenComplete((id, x) -> {
if (x == null) {
handleSuccess();
} else {
handleError(x);
}
});
The id
of the success callback correspond to the Sse.Event.id()
.
data
- Event data.
type
- Media type, like: json, xml.
Sse.Event.id()
.
@Nonnull public CompletableFuture<Optional<Object>> send(Object data)
sse.send(new MyObject());
sse.send(new MyObject(), "json").whenComplete((id, x) -> {
if (x == null) {
handleSuccess();
} else {
handleError(x);
}
});
The id
of the success callback correspond to the Sse.Event.id()
.
data
- Event data.
Sse.Event.id()
.
@Nonnull public Sse.Event event(Object data)
Sse.Event
instances. Please note event won't be sent unless you call Sse.Event.send()
:
sse.event(new MyObject()).send();
The factory allow you to set event attributes:
// send data
MyObject data = ...;
sse.event(data).send();
// send data with event name
sse.event(data).name("myevent").send();
// send data with event name and id
sse.event(data).name("myevent").id(id).send();
// send data with event name, id and retry interval
sse.event(data).name("myevent").id(id).retry(1500).send();
data
- Event data.
@Nonnull public <T> T require(Class<T> type)
T
- Service type.
type
- A service type.
@Nonnull public <T> T require(String name, Class<T> type)
T
- Service type.
name
- A service name.
type
- A service type.
@Nonnull public <T> T require(com.google.inject.TypeLiteral<T> type)
T
- Service type.
type
- A service type.
@Nonnull public <T> T require(com.google.inject.Key<T> key)
T
- Service type.
key
- A service key.
@Nonnull public Sse keepAlive(int time, TimeUnit unit)
{
sse("/events/:id", sse -> {
sse.keepAlive(15, TimeUnit.SECONDS);
});
}
The previous example will sent a ':'
message (empty comment) every 15 seconds to keep the connection alive. If the client drop the connection, then the onClose(Throwing.Runnable)
event will be fired it.
This feature is useful when you want to detect onClose(Throwing.Runnable)
events without waiting until you send a new event. But for example, if your application already generate events every 15s, then the use of keep alive is useless and you should avoid it.
time
- Keep alive time.
unit
- Time unit.
@Nonnull public Sse keepAlive(long millis)
{
sse("/events/:id", sse -> {
sse.keepAlive(15, TimeUnit.SECONDS);
});
}
The previous example will sent a ':'
message (empty comment) every 15 seconds to keep the connection alive. If the client drop the connection, then the onClose(Throwing.Runnable)
event will be fired it.
This feature is useful when you want to detect onClose(Throwing.Runnable)
events without waiting until you send a new event. But for example, if your application already generate events every 15s, then the use of keep alive is useless and you should avoid it.
millis
- Keep alive time in millis.
public final void close() throws Exception
onClose(Throwing.Runnable)
event.
close
in interface AutoCloseable
Exception
Copyright © 2019. All rights reserved.