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:
public class MoodServlet extends HttpServlet { private final List<String> celebrities; private final List<String> activities; private final List<String> cities; private final 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 protected void 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(); } private String 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 interesting parts in the code is :
- 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> <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>The above message as interpreted by the browser would be:
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 = new String[] {"red","blue","green"}; 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");We have introduced three new events - "red","green","blue". Here we preceded our message with information about the event type. Along the lines of
event: X \n data: Y \n data: Z \n\nThen some change in the browser to listen for different events:
function start() { 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); }The output looks like below:
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.
No comments:
Post a Comment