Server-Sent Events using GlassFish (TOTD #179)

Posted by arungupta on Oracle Blogs See other posts from Oracle Blogs or by arungupta
Published on Fri, 15 Jun 2012 10:00:00 +0000 Indexed on 2012/06/15 15:23 UTC
Read the original article Hit count: 234

Filed under:
Bhakti blogged about Server-Sent Events on GlassFish and I've been planning to try it out for past some days. Finally, I took some time out today to learn about it and build a simplistic example showcasing the touch points.

Server-Sent Events is developed as part of HTML5 specification and provides push notifications from a server to a browser client in the form of DOM events. It is defined as a cross-browser JavaScript API called EventSource. The client creates an EventSource by requesting a particular URL and registers an onmessage event listener to receive the event notifications. This can be done as shown

var url = 'http://' + document.location.host + '/glassfish-sse/simple';
eventSource = new EventSource(url);

eventSource.onmessage = function (event) {
var theParagraph = document.createElement('p');
theParagraph.innerHTML = event.data.toString();
document.body.appendChild(theParagraph);
}

This code subscribes to a URL, receives the data in the event listener, adds it to a HTML paragraph element, and displays it in the document. This is where you'll parse JSON and other processing to display if some other data format is received from the URL.

The URL to which the EventSource is subscribed to is updated on the server side and there are multipe ways to do that. GlassFish 4.0 provide support for Server-Sent Events and it can be achieved registering a handler as shown below:

@ServerSentEvent("/simple")
public class MySimpleHandler extends ServerSentEventHandler {

public void sendMessage(String data) {
try {
connection.sendMessage(data);
} catch (IOException ex) {
. . .
}
}
}

And then events can be sent to this handler using a singleton session bean as shown:

@Startup
@Stateless
public class SimpleEvent {

@Inject @ServerSentEventContext("/simple")
ServerSentEventHandlerContext<MySimpleHandler> simpleHandlers;

@Schedule(hour="*", minute="*", second="*/10")
public void sendDate() {
for(MySimpleHandler handler : simpleHandlers.getHandlers()) {
handler.sendMessage(new Date().toString());
}
}
}

This stateless session bean injects ServerSentEventHandlers listening on "/simple" path. Note, there may be multiple handlers listening on this path. The sendDate method triggers every 10 seconds and send the current timestamp to all the handlers. The client side browser simply displays the string.

The HTTP request headers look like:

Accept: text/event-stream
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cache-Control: no-cache
Connection: keep-alive
Cookie: JSESSIONID=97ff28773ea6a085e11131acf47b
Host: localhost:8080
Referer: http://localhost:8080/glassfish-sse/faces/index2.xhtml
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5

And the response headers as:

Content-Type: text/event-stream
Date: Thu, 14 Jun 2012 21:16:10 GMT
Server: GlassFish Server Open Source Edition 4.0
Transfer-Encoding: chunked
X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 4.0 Java/Apple Inc./1.6)

Notice, the MIME type of the messages from server to the client is text/event-stream and that is defined by the specification.

The code in Bhakti's blog can be further simplified by using the recently-introduced Twitter API for Java as shown below:

@Schedule(hour="*", minute="*", second="*/10")
public void sendTweets() {
for(MyTwitterHandler handler : twitterHandler.getHandlers()) {
String result = twitter.search("glassfish", String.class);
handler.sendMessage(result);
}
}

The complete source explained in this blog can be downloaded here and tried on GlassFish 4.0 build 34. The latest promoted build can be downloaded from here and the complete source code for the API and implementation is here.

I tried this sample on Chrome Version 19.0.1084.54 on Mac OS X 10.7.3.

© Oracle Blogs or respective owner

Related posts about /General