Class EventSource
- java.lang.Object
-
- org.glassfish.jersey.media.sse.EventSource
-
- All Implemented Interfaces:
EventListener
public class EventSource extends Object implements EventListener
Client for reading and processingincoming Server-Sent Events.Instances of this class are thread safe. To build a new instance, you can use one of the available public
EventSourceconstructors that produce pre-configured event source instances. Alternatively, you can create a newEventSource.Builderinstance usingEventSource.target(endpoint)factory method. Compared toEventSourceconstructors, an event source builder provides greater flexibility when custom-configuring a new event source builder.Once an
EventSourceis created, itopens a connectionto the associatedweb targetand starts processing any incoming inbound events. Whenever a new event is received, anonEvent(InboundEvent)method is called as well as any registeredevent listenersare notified (seeregister(EventListener)andregister(EventListener, String, String...).Reconnect support
The
EventSourcesupports automated recuperation from a connection loss, including negotiation of delivery of any missed events based on the last received SSE eventidfield value, provided this field is set by the server and the negotiation facility is supported by the server. In case of a connection loss, the last received SSE eventidfield value is send in the "Last-Event-ID" HTTP request header as part of a new connection request sent to the SSE endpoint. Upon a receipt of such reconnect request, the SSE endpoint that supports this negotiation facility is expected to replay all missed events. Note however, that this is a best-effort mechanism which does not provide any guaranty that all events would be delivered without a loss. You should therefore not rely on receiving every single event and design your client application code accordingly.By default, when a connection the the SSE endpoint is lost, the event source will wait 500L ms before attempting to reconnect to the SSE endpoint. The SSE endpoint can however control the client-side retry delay by including a special
retryfield value in the any send event. JerseyEventSourceimplementation tracks any received SSE eventretryfield values set by the endpoint and adjusts the reconnect delay accordingly, using the last receivedretryfield value as the reconnect delay.In addition to handling the standard connection losses, Jersey
EventSourceautomatically deals with anyHTTP 503 Service Unavailableresponses from SSE endpoint, that contain a "Retry-After" HTTP header with a valid value. The HTTP 503 + "Retry-After" technique is often used by HTTP endpoints as a means of connection and traffic throttling. In case a HTTP 503 + "Retry-After" response is received in return to a connection request, JerseyEventSourcewill automatically schedule a new reconnect attempt and use the received "Retry-After" HTTP header value as a one-time override of the reconnect delay.Using HTTP persistent connections
The experience has shown that persistent HTTP connection management in the
HttpURLConnection, that is used as a default Jersey clientconnector, is fragile. It is unfortunately quite possible, that under heavy load the client and server connections may get out of sync, causing JerseyEventSourcehang on a connection that has already been closed by a server, but has not been properly cleaned up by theHttpURLConnectionmanagement code, and has been reused for a re-connect request instead. To avoid this issue, JerseyEventSourceimplementation by default disables persistent HTTP connections when connecting (or reconnecting) to the SSE endpoint.In case you are using Jersey event source with a Jersey client
ClientConfig.connectorProvider(org.glassfish.jersey.client.spi.ConnectorProvider)connector provider configured to use some other clientConnectorProviderimplementation able to reliably manage persistent HTTP connections (such asorg.glassfish.jersey.grizzly.connector.GrizzlyConnectorProviderororg.glassfish.jersey.apache.connector.ApacheConnectorProvider), or in case you simply need to use persistent HTTP connections, you may do so by invoking theusePersistentConnections()method on an event source builder prior to creating a new event source instance.- Author:
- Pavel Bucek, Marek Potociar
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static classEventSource.BuilderJerseyEventSourcebuilder class.
-
Field Summary
Fields Modifier and Type Field Description static longRECONNECT_DEFAULTDefault SSEEventSourcereconnect delay value in milliseconds.
-
Constructor Summary
Constructors Constructor Description EventSource(WebTarget endpoint)Create new SSE event source and open a connection it to the supplied SSE streamingweb target.EventSource(WebTarget endpoint, boolean open)Create new SSE event source pointing at a SSE streamingweb target.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description voidclose()Close this event source.booleanclose(long timeout, TimeUnit unit)Close this event source and wait for the internal event processing task to complete for up to the specified amount of wait time.booleanisOpen()Check if this event source instance has already beenopened.voidonEvent(InboundEvent inboundEvent)Invoked when an event is received.voidopen()Open the connection to the supplied SSE underlyingweb targetand start processing incomingevents.voidregister(EventListener listener)Register newevent listenerto receive all streamedSSE events.voidregister(EventListener listener, String eventName, String... eventNames)Add name-boundevent listenerwhich will be called only for incoming SSEeventswhosenameis equal to the specified name(s).static EventSource.Buildertarget(WebTarget endpoint)Create a newevent source builderthat provides convenient way how to configure and fine-tune various aspects of a newly prepared event source instance.
-
-
-
Field Detail
-
RECONNECT_DEFAULT
public static final long RECONNECT_DEFAULT
Default SSEEventSourcereconnect delay value in milliseconds.- Since:
- 2.3
- See Also:
- Constant Field Values
-
-
Constructor Detail
-
EventSource
public EventSource(WebTarget endpoint)
Create new SSE event source and open a connection it to the supplied SSE streamingweb target. This constructor is performs the same series of actions as a call to:EventSource.target(endpoint).open()
The created event source instance automatically
opens a connectionto the supplied SSE streaming web target and starts processing incomingevents.The incoming events are processed by the event source in an asynchronous task that runs in an internal single-threaded
scheduled executor service.- Parameters:
endpoint- SSE streaming endpoint. Must not benull.- Throws:
NullPointerException- in case the supplied web target isnull.
-
EventSource
public EventSource(WebTarget endpoint, boolean open)
Create new SSE event source pointing at a SSE streamingweb target. This constructor is performs the same series of actions as a call to:if (open) { EventSource.target(endpoint).open(); } else { EventSource.target(endpoint).build(); }If the supplied
openflag istrue, the created event source instance automaticallyopens a connectionto the supplied SSE streaming web target and starts processing incomingevents. Otherwise, if theopenflag is set tofalse, the created event source instance is not automatically connected to the web target. In this case it is expected that the user who created the event source will manually invoke itsopen()method.Once the event source is open, the incoming events are processed by the event source in an asynchronous task that runs in an internal single-threaded
scheduled executor service.- Parameters:
endpoint- SSE streaming endpoint. Must not benull.open- iftrue, the event source will immediately connect to the SSE endpoint, iffalse, the connection will not be established untilopen()method is called explicitly on the event stream.- Throws:
NullPointerException- in case the supplied web target isnull.
-
-
Method Detail
-
target
public static EventSource.Builder target(WebTarget endpoint)
Create a newevent source builderthat provides convenient way how to configure and fine-tune various aspects of a newly prepared event source instance.- Parameters:
endpoint- SSE streaming endpoint. Must not benull.- Returns:
- a builder of a new event source instance pointing at the specified SSE streaming endpoint.
- Throws:
NullPointerException- in case the supplied web target isnull.- Since:
- 2.3
-
open
public void open()
Open the connection to the supplied SSE underlyingweb targetand start processing incomingevents.- Throws:
IllegalStateException- in case the event source has already been opened earlier.
-
isOpen
public boolean isOpen()
Check if this event source instance has already beenopened.- Returns:
trueif this event source is open,falseotherwise.
-
register
public void register(EventListener listener)
Register newevent listenerto receive all streamedSSE events.- Parameters:
listener- event listener to be registered with the event source.- See Also:
register(EventListener, String, String...)
-
register
public void register(EventListener listener, String eventName, String... eventNames)
Add name-boundevent listenerwhich will be called only for incoming SSEeventswhosenameis equal to the specified name(s).- Parameters:
listener- event listener to register with this event source.eventName- inbound event name.eventNames- additional event names.- See Also:
register(EventListener)
-
onEvent
public void onEvent(InboundEvent inboundEvent)
Invoked when an event is received.The default
EventSourceimplementation is empty, users can override this method to handle incomingInboundEvents.Note that overriding this method may be necessary to make sure no
InboundEvent incoming eventsare lost in case the event source is constructed usingEventSource(jakarta.ws.rs.client.WebTarget)constructor or in case atrueflag is passed to theEventSource(jakarta.ws.rs.client.WebTarget, boolean)constructor, since the connection is opened as as part of the constructor call and the event processing starts immediately. Therefore anyEventListeners registered later after the event source has been constructed may miss the notifications about the one or more events that arrive immediately after the connection to the event source is established.- Specified by:
onEventin interfaceEventListener- Parameters:
inboundEvent- received inbound event.
-
close
public void close()
Close this event source. The method will wait up to 5 seconds for the internal event processing task to complete.
-
close
public boolean close(long timeout, TimeUnit unit)Close this event source and wait for the internal event processing task to complete for up to the specified amount of wait time.The method blocks until the event processing task has completed execution after a shutdown request, or until the timeout occurs, or the current thread is interrupted, whichever happens first.
In case the waiting for the event processing task has been interrupted, this method restores the
interruptflag on the thread before returningfalse.- Parameters:
timeout- the maximum time to wait.unit- the time unit of the timeout argument.- Returns:
trueif this executor terminated andfalseif the timeout elapsed before termination or the termination was interrupted.
-
-