跳至主要内容

JAX-RS 2.1: Server Sent Event

Server Sent Event

Jersey itself supports SSE for years, now it is standardized as a part of JAXRS 2.1.
A simple SSE example.
@Path("events")
@RequestScoped
public class SseResource {

    @GET
    @Produces(MediaType.SERVER_SENT_EVENTS)
    public void eventStream(@Context Sse sse, @Context SseEventSink eventSink) {
        // Resource method is invoked when a client subscribes to an event stream.
        // That implies that sending events will most likely happen from different
        // context - thread / event handler / etc, so common implementation of the
        // resource method will store the eventSink instance and the application 
        // logic will retrieve it when an event should be emitted to the client.

        // sending events:
        eventSink.send(sse.newEvent("event1"));
    }    
}
Notice, you should declare @Produces value as text/event-stream( via MediaType.SERVER_SENT_EVENTS). SseEventSink should be request aware, Sse is helpful to build event payloads etc.
An example of Sse client.
WebTarget target = ClientBuilder.newClient().target("http://localhost:8080/jaxrs-sse/rest/events");

try (SseEventSource eventSource = SseEventSource.target(target).build()) {

 // EventSource#register(Consumer<InboundSseEvent>)
 // Registered event handler will print the received message.
 eventSource.register(System.out::println);

 // Subscribe to the event stream.
 eventSource.open();
 
 // Consume events for just 500 ms
 Thread.sleep(500);
} catch (InterruptedException e) {
 e.printStackTrace();
}
The following is an example demonstrates the usage of SseBroadcaster, which allow you send messages to all registered clients.
@Path("broadcastEvents")
@Singleton
public class BroadcastResource {

    @Context
    private Sse sse;

    private volatile SseBroadcaster sseBroadcaster;

    @PostConstruct
    public void init() {
        this.sseBroadcaster = sse.newBroadcaster();
    }

    @GET
    //@Path("register")
    @Produces(MediaType.SERVER_SENT_EVENTS)
    public void register(@Context SseEventSink eventSink) {
        eventSink.send(sse.newEvent("welcome!"));
        sseBroadcaster.register(eventSink);
    }

    @POST
    //@Path("broadcast")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public void broadcast(@FormParam("event") String event) {
        sseBroadcaster.broadcast(sse.newEvent(event));
    }

    public void eventStreamCdi(@Observes Message msg) {
        sseBroadcaster.broadcast(
                sse.newEventBuilder()
                        .mediaType(MediaType.APPLICATION_JSON_TYPE)
                        .id(UUID.randomUUID().toString())
                        .name("message from cdi")
                        .data(msg)
                        .build()
        );
    }
}
Grab the source codes from my github account, and have a try.

评论

此博客中的热门博文

Build a Reactive application with Angular 5 and Spring Boot 2.0

I have created a post to describe Reactive programming supports in Spring 5 and its subprojects, all codes of this article are updated the latest Spring 5 RELEASE, check spring-reactive-sample under my Github account.
In this post, I will create a simple blog system, including:
A user can sign in and sign out.An authenticated user can create a post.An authenticated user can update a post.Only the user who has ADMIN role can delete a post.All users(including anonymous users) can view post list and post details.An authenticated user can add his comments to a certain post. The backend will be built with the latest Spring 5 reactive stack, including:
Spring Boot 2.0, at the moment the latest version is 2.0.0.M7Spring Data MongoDB supports reactive operations for MongoDBSpring Session adds reactive support for WebSessionSpring Security 5 aligns with Spring 5 reactive stack The frontend is an Angular based SPA and it will be generated by Angular CLI.
The source code is hosted on Github, …

Activating CDI in JSF 2.3

Activating CDI in JSF 2.3 When I upgraed my Java EE 7 sample to the newest Java EE 8, the first thing confused me is the CDI beans are not recoganized in Facelects template in a JSF 2.3 based web applicaiton, which is working in the development version, but in the final release version, they are always resolved as null. I filed an issue on Mojarra and discussed it with the developers from communities and the JSF experts.
According to the content of README, In a JSF 2.3 application, to activate CDI support, declaring a 2.3 versioned faces-config.xml and adding javax.faces.ENABLE_CDI_RESOLVER_CHAIN in web.xml is not enough, you have to declare @FacesConfig annotated class to enable CDI.
Here is the steps I created a workable JSF 2.3 applicatoin in Java EE 8.
Create a Java web application, this can be done easily by NetBeans IDE, or generated by Maven archetype, for exmaple.
$ mvn archetype:generate -DgroupId=com.example -DartifactId=demo -DarchetypeArtifactId=maven-archetype-w…

JSF 2.3:Websocket support

Websocket support One of the most attractive features is JSF 2.3 added native websocket support, it means you can write real-time applications with JSF and no need extra effort.
To enable websocket support, you have to add javax.faces.ENABLE_WEBSOCKET_ENDPOINT in web.xml.
<context-param> <param-name>javax.faces.ENABLE_WEBSOCKET_ENDPOINT</param-name> <param-value>true</param-value> </context-param> Hello Websocket Let's start with a simple example.
@ViewScoped@Named("helloBean") publicclassHelloBeanimplementsSerializable { privatestaticfinalLoggerLOG=Logger.getLogger(HelloBean.class.getName()); @Inject@PushPushContext helloChannel; String message; publicvoidsendMessage() { LOG.log(Level.INFO, "send push message"); this.sendPushMessage("hello"); } privatevoidsendPushMessage(Objectmessage) { helloChannel.send(""+ message +" at &…