In the past few posts I have seen some techniques to pull of Push Notifications. HTML5 has introduced a couple of new methods - one of them is Server -Sent Events. In this post I am trying to build one such Servlet based implementation.
One of the prime points to note is that I do not need Servlet 3.x to pull this off. I can do with old style Servlet. What I do need is an HTML5 compatible web browser.
I decided to build a servlet that tells me the mood of a famous personality at any given time. The code is nothing but overuse of Randomness to pull of the statements:
This whole is one single message. This message will now be processed at our client:One of the prime points to note is that I do not need Servlet 3.x to pull this off. I can do with old style Servlet. What I do need is an HTML5 compatible web browser.
I decided to build a servlet that tells me the mood of a famous personality at any given time. The code is nothing but overuse of Randomness to pull of the statements:
publicclass MoodServlet extends HttpServlet {The interesting parts in the code is :
privatefinal List<String> celebrities;
privatefinal List<String> activities;
privatefinal List<String> cities;
privatefinal List<String> companions;
{
celebrities = Arrays.asList("Amitabh Bachchan", "Tom Cruise", "Steve Buscemi",
"Madhuri Dixit", "Mary Kom", "Sachin Tendulkar");
activities = Arrays.asList("reading News", "watching Tennis", "out for a walk",
"at a bar", "working ", " taking a pleasant nap");
cities = Arrays.asList("Mumbai", "Pune", "Goa", "Kerala", "Jammu", "Ladakh");
companions = Arrays.asList("Family", "Friends", "dog", "Colleages", "kids", "spouse",
"neighbors");
}
@Override
protectedvoid doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
int waitTimeBetweenPosts = (int) (Math.random() * 5);
String statement1 = getCelebrityMood();
String statement2 = getCelebrityMood();
// content type must be set to text/event-stream
resp.setContentType("text/event-stream");
// encoding must be set to UTF-8
resp.setCharacterEncoding("UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("data: wait time - " + waitTimeBetweenPosts + " seconds " + "\n");
writer.write("data:" + statement1+ "\n");
try {
Thread.sleep(waitTimeBetweenPosts * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
writer.write("data: " + statement2+ "\n");
writer.write("\n");
writer.flush();
writer.close();
}
privateString getCelebrityMood() {
return celebrities.get((int) (Math.random() * celebrities.size()))
+ " : I wish I was " + activities.get((int) (Math.random() * activities.size()))
+ " at " + cities.get((int) (Math.random() * cities.size())) + " with my "
+ companions.get((int) (Math.random() * companions.size()));
}
}
- The class is a normal HttpServlet.
- The content type however distinguishes this as server side events - "text/event-stream"
- Each write to the stream is prefixed with "data:" and ended with as "\n"
- The end of message is indicated by a "\n".
data: wait time - 2 seconds
\ndata: Tom Cruise : I wish I was reading News at Goa with my spouse\n
data: Madhuri Dixit : I wish I was watching Tennis at Goa with my spouse\n\n
<!DOCTYPE HTML>The above message as interpreted by the browser would be:
<html>
<body>
<b> What's trending on Page 3 </b>:
<div id="messages"></div>
<br/><br/>
<button onclick="start()">GetMessaged</button>
<script type="text/javascript">
function start() {
if (!!window.EventSource) {
var eventSource = new EventSource("mood");
} else {
alert("Your client does not suport server sent events !")
}
eventSource.onmessage = function(event) {
var value = document.getElementById('messages').innerHTML;
document.getElementById('messages').innerHTML = value
+ "<br/>" + event.data;
};
}
</script>
</body>
</html>
wait time - 2 seconds Tom Cruise : I wish I was reading News at Goa with my spouse Madhuri Dixit : I wish I was watching Tennis at Goa with my spouseThe page looks as follows:
If we look at Firebug, we can see that the browser sent requests at regular intervals to this page:
The cool thing about server sent events is that we can associate an event with our data. I made a small change to the servlet code:
String[] events = newString[] {"red","blue","green"};We have introduced three new events - "red","green","blue". Here we preceded our message with information about the event type. Along the lines of
writer.write("event: " + events[(int) (Math.random()*events.length)] +"\n");
writer.write("data: wait time - " + waitTimeBetweenPosts + " seconds " + "\n");
writer.write("data: " + statement1 + "\n");
pause(waitTimeBetweenPosts);
//Failed to create two events in a single message
// writer.write("event: " + events[(int) (Math.random()*events.length)] +"\n");
writer.write("data: " + statement2 + "\n");
writer.write("\n");
event: X \nThen some change in the browser to listen for different events:
data: Y \n
data: Z \n\n
function start() {The output looks like below:
if (!!window.EventSource) {
var eventSource = new EventSource("mood");
} else {
alert("Your client does not suport server sent events !")
}
eventSource.addEventListener('green', function(event) {
var value = document.getElementById('messages').innerHTML;
document.getElementById('messages').innerHTML = value
+ "<br/> <font color='green'>" +event.data+"</font>";
}, false);
eventSource.addEventListener('red', function(event) {
var value = document.getElementById('messages').innerHTML;
document.getElementById('messages').innerHTML = value
+ "<br/> <font color='red'>" +event.data+"</font>";
}, false);
eventSource.addEventListener('blue', function(event) {
var value = document.getElementById('messages').innerHTML;
document.getElementById('messages').innerHTML = value
+ "<br/> <font color='blue'>" +event.data+"</font>";
}, false);
eventSource.onerror( function(event) {
alert("Failed to execute the event");
}, false);
}
I tried to included multiple events in a single message but that did not work.
Also there is an onError event available in java script to process any failures in the code.