/** * Close this event source. * * The method will wait up to 5 seconds for the internal event processing task to complete. */ public void close() { close(5, TimeUnit.SECONDS); }
private EventSource(final WebTarget target, final String name, final long reconnectDelay, final boolean disableKeepAlive, final boolean open) { if (target == null) { throw new NullPointerException("Web target is 'null'."); } this.target = SseFeature.register(target); this.reconnectDelay = reconnectDelay; this.disableKeepAlive = disableKeepAlive; final String esName = (name == null) ? createDefaultName(target) : name; this.executor = new CloseableClientExecutor(Executors.newSingleThreadScheduledExecutor( new ThreadFactoryBuilder().setNameFormat(esName + "-%d") .setDaemon(true) .build())); if (open) { open(); } }
/** * Register new {@link EventListener event listener} to receive all streamed {@link InboundEvent SSE events}. * * @param listener event listener to be registered with the event source. * @see #register(EventListener, String, String...) */ public void register(final EventListener listener) { register(listener, null); }
/** * Build new SSE event source pointing at a SSE streaming {@link WebTarget web target}. * <p> * The returned event source is already {@link EventSource#open() connected} to the SSE endpoint * and is processing any new incoming events. In case you want to build an event source instance * that is already ready, but not automatically connected to the SSE endpoint, use the event source * builder {@link #build()} method instead. * </p> * <p> * The incoming events are processed by the event source in an asynchronous task that runs in an * internal single-threaded {@link ScheduledExecutorService scheduled executor service}. * </p> * * @return new event source instance, already connected to the SSE endpoint. * @see #build() */ public EventSource open() { // opening directly in the constructor is just plain ugly... final EventSource source = new EventSource(endpoint, name, reconnect, disableKeepAlive, false); source.open(); return source; } }
EventSource eventSource = EventSource.target(target).build(); eventSource.register(new EventHandler(RestconfDiscoveryNode.this)); eventSource.open(); log.info("Connected to SSE source"); while (running) { try { log.info("SSE state " + eventSource.isOpen()); Thread.sleep(5000); } catch (InterruptedException e) { eventSource.close(); log.info("Closed connection to SSE source");
@Override public Optional<AutoCloseable> subscribe(@NonNull String rel, @NonNull SSEObserver<S> observer, @NonNull String mainEventName, long reconnectionTime) { checkArgument(reconnectionTime > 0); CallContext pair = resolve(rel); if (pair == null) { return Optional.empty(); } // this hack is needed because of // https://github.com/jersey/jersey/pull/3600 // setting a global last event id header via LastEventIdHeaderFilter and // synchronizing all sse // sources :-( synchronized (lock) { // this hack is needed because of // https://github.com/jersey/jersey/pull/3600 if (observer.lastKnownEventId().isPresent()) { pair.target.property(SseFeature.LAST_EVENT_ID_HEADER, observer.lastKnownEventId().get()); } EventSource eventSource = EventSource.target(pair.target).named("SSE" + UUID.randomUUID()) .usePersistentConnections().reconnectingEvery(reconnectionTime, TimeUnit.MILLISECONDS).build(); SSEListener<S> sseListener = new SSEListener<>(responseClass, responseBuilder, observer, mainEventName, uri); eventSource.register(sseListener); EventSourceWithCloseGuard ev = new EventSourceWithCloseGuard(eventSource, reconnectionTime, sseListener); ev.open(); return Optional.of(ev); } }
public void open() { eventSource.open(); timer.schedule(new TimerTask() { @Override public void run() { synchronized (closeLock) { if (!eventSource.isOpen() && !isShuttingDown) { try { close(); } finally { sseListener.onConnectionError(); } } } } }, reconnectionTime, reconnectionTime / 2 + 1); }
/** * Build new SSE event source pointing at a SSE streaming {@link WebTarget web target}. * <p> * The returned event source is ready, but not {@link EventSource#open() connected} to the SSE endpoint. * It is expected that you will manually invoke its {@link #open()} method once you are ready to start * receiving SSE events. In case you want to build an event source instance that is already connected * to the SSE endpoint, use the event source builder {@link #open()} method instead. * </p> * <p> * 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 {@link ScheduledExecutorService * scheduled executor service}. * </p> * * @return new event source instance, ready to be connected to the SSE endpoint. * @see #open() */ public EventSource build() { return new EventSource(endpoint, name, reconnect, disableKeepAlive, false); }
/** * Add name-bound {@link EventListener event listener} which will be called only for incoming SSE * {@link InboundEvent events} whose {@link InboundEvent#getName() name} is equal to the specified * name(s). * * @param listener event listener to register with this event source. * @param eventName inbound event name. * @param eventNames additional event names. * @see #register(EventListener) */ public void register(final EventListener listener, final String eventName, final String... eventNames) { if (eventName == null) { unboundListeners.add(listener); } else { addBoundListener(eventName, listener); if (eventNames != null) { for (String name : eventNames) { addBoundListener(name, listener); } } } }
shutdown(); try { if (!executor.awaitTermination(timeout, unit)) {
@Override public void run() { synchronized (closeLock) { if (!eventSource.isOpen() && !isShuttingDown) { try { close(); } finally { sseListener.onConnectionError(); } } } } }, reconnectionTime, reconnectionTime / 2 + 1);
/** * Build new SSE event source pointing at a SSE streaming {@link WebTarget web target}. * <p> * The returned event source is already {@link EventSource#open() connected} to the SSE endpoint * and is processing any new incoming events. In case you want to build an event source instance * that is already ready, but not automatically connected to the SSE endpoint, use the event source * builder {@link #build()} method instead. * </p> * <p> * The incoming events are processed by the event source in an asynchronous task that runs in an * internal single-threaded {@link ScheduledExecutorService scheduled executor service}. * </p> * * @return new event source instance, already connected to the SSE endpoint. * @see #build() */ public EventSource open() { // opening directly in the constructor is just plain ugly... final EventSource source = new EventSource(endpoint, name, reconnect, disableKeepAlive, false); source.open(); return source; } }
/** * Build new SSE event source pointing at a SSE streaming {@link WebTarget web target}. * <p> * The returned event source is ready, but not {@link EventSource#open() connected} to the SSE endpoint. * It is expected that you will manually invoke its {@link #open()} method once you are ready to start * receiving SSE events. In case you want to build an event source instance that is already connected * to the SSE endpoint, use the event source builder {@link #open()} method instead. * </p> * <p> * 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 {@link ScheduledExecutorService * scheduled executor service}. * </p> * * @return new event source instance, ready to be connected to the SSE endpoint. * @see #open() */ public EventSource build() { return new EventSource(endpoint, name, reconnect, disableKeepAlive, false); }
/** * Add name-bound {@link EventListener event listener} which will be called only for incoming SSE * {@link InboundEvent events} whose {@link InboundEvent#getName() name} is equal to the specified * name(s). * * @param listener event listener to register with this event source. * @param eventName inbound event name. * @param eventNames additional event names. * @see #register(EventListener) */ public void register(final EventListener listener, final String eventName, final String... eventNames) { if (eventName == null) { unboundListeners.add(listener); } else { addBoundListener(eventName, listener); if (eventNames != null) { for (String name : eventNames) { addBoundListener(name, listener); } } } }
shutdown(); try { if (!executor.awaitTermination(timeout, unit)) {
private EventSource(final WebTarget target, final String name, final long reconnectDelay, final boolean disableKeepAlive, final boolean open) { if (target == null) { throw new NullPointerException("Web target is 'null'."); } this.target = SseFeature.register(target); this.reconnectDelay = reconnectDelay; this.disableKeepAlive = disableKeepAlive; final String esName = (name == null) ? createDefaultName(target) : name; this.executor = Executors.newSingleThreadScheduledExecutor( new ThreadFactoryBuilder().setNameFormat(esName + "-%d").setDaemon(true).build()); if (open) { open(); } }
/** * Build new SSE event source pointing at a SSE streaming {@link WebTarget web target}. * <p> * The returned event source is already {@link EventSource#open() connected} to the SSE endpoint * and is processing any new incoming events. In case you want to build an event source instance * that is already ready, but not automatically connected to the SSE endpoint, use the event source * builder {@link #build()} method instead. * </p> * <p> * The incoming events are processed by the event source in an asynchronous task that runs in an * internal single-threaded {@link ScheduledExecutorService scheduled executor service}. * </p> * * @return new event source instance, already connected to the SSE endpoint. * @see #build() */ public EventSource open() { // opening directly in the constructor is just plain ugly... final EventSource source = new EventSource(endpoint, name, reconnect, disableKeepAlive, false); source.open(); return source; } }
/** * Register new {@link EventListener event listener} to receive all streamed {@link InboundEvent SSE events}. * * @param listener event listener to be registered with the event source. * @see #register(EventListener, String, String...) */ public void register(final EventListener listener) { register(listener, null); }
/** * Close this event source. * * The method will wait up to 5 seconds for the internal event processing task to complete. */ public void close() { close(5, TimeUnit.SECONDS); }