# LAB-5558: Developing Revolutionary Web Applications, Using Ajax Push or Comet

Expected Duration: 120 minutes
Contacts: Carol McDonald Doris Chen Justin Bolter

Introduction | Exercise 0 | Exercise 1 | Exercise 2 | Exercise 3 | Exercise 4 | Summary
2. Introduction Background Information Steps to Follow Summary ## Exercise 3: Server Interact with Chat Application (20 minutes) In this exercise, you will learn how to implement a servlet to interact with the Chat application by using Grizzly comet framework API. ### Background Information For the Chat application developed in exercise 1, we only need to implement the application in the client with Dojo or other Ajax components. It is very easy to develop as it is server agnostic if the server supports Bayeux and cometd. However, if we want to have some control on the server side like receiving some messages from the server, or interacting with server in certain way, we will need to use Grizzly comet framework to implement the interaction between server and client. ### Steps to Follow Step 1: Continue on chat Web Application project We will continue on the chat application created in exercise 1. This will all run on our familiar Glassfish server and many of the steps you will be familiar with from previous exercises. If NetBeans is not already running, start it. Let's make a copy of the chat application. Right click on chat application and select copy from the list as illustrated in the following figure. In copy project panel, type chat_externalServlet as the project name and choose location where you want to put this project and then select copy to execute copy project. Now create a new servlet in the project. Right click Source Packages and choose New from the list and then select Other as shown below. In New File panel , select Web as the Categories and Servlet as the File Types and then select Next to continue Now configure the New Servlet. Type ChatExternalServlet as the Class Name, choose <default package> as the Package, and then select Finish to create the servlet. Now we need to add the Comet libraries to our project. Right click the `chat_externalServlet` node and select Properties from the list. Find the project's Libraries in the left hand side of the window and select it. Click Add JAR/Folder button on the right side. Select the following two JAR's from the ``<lab_root`>/``exercises/exercise3.`Click OK to finish Library selection. grizzly-comet.jar grizzly-cometd.jar Step 2: Develop A Simple Servlet We will develop a simple servlet that will interact with the chat application via a simple HTTP request. Open ChatExternalServlet.java under Sources Package in NetBeans. The following is a simple servlet to start with with. Copy and paste the code below into ChatExternalServlet.java in NetBeans. Pay particular attention to the code in bold.
       import com.sun.grizzly.comet.CometContext;
       import com.sun.grizzly.comet.CometEngine;
       import com.sun.grizzly.cometd.bayeux.Data;
       import com.sun.grizzly.cometd.bayeux.DeliverResponse;
       import java.io.IOException;
       import java.util.HashMap;
       import java.util.Map;
       import java.util.concurrent.ScheduledThreadPoolExecutor;
       import java.util.concurrent.TimeUnit;
       import javax.servlet.ServletConfig;
       import javax.servlet.ServletException;
       import javax.servlet.ServletOutputStream;
       import javax.servlet.http.HttpServlet;
       import javax.servlet.http.HttpServletRequest;
       import javax.servlet.http.HttpServletResponse;

       /**
        * Simple Servlet that update the chat application via a simple Http request
        *
        * <code>
        * http://localhost:port/cometd/ChatExternalServlet?user=me&message=hello
        * </code>
        *
        * @author Doris Chen
        */
       public class ChatExternalServlet extends HttpServlet {

        /**
        * All request to that channel will be considered as cometd enabled.
        */
        private String channel ="/chat/demo";

        /**
        * Initialize the Servlet.
        */
        @Override
        public void init(ServletConfig config) throws ServletException {
        super.init(config);

        if (config.getInitParameter("channel") != null){
        channel = config.getInitParameter("channel");

        }
        }

        @Override
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
        }

        /**
        * See
        * @param request
        * @param response
        * @throws javax.servlet.ServletException
        * @throws java.io.IOException
        */
        @Override
        public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // message and user are part of the simple HTTP request will invoke late.
        String message = request.getParameter("message");
        String user = request.getParameter("user");
        ServletOutputStream out = response.getOutputStream();

        //create the comet context with the specified channel.
        CometEngine engine = CometEngine.getEngine();
        CometContext context = engine.getCometContext(channel);

        if (context != null && message != null) {
        Map<String, Object> map = new HashMap<String, Object>();
        // text and user are defined entry in the previous chat application.
        map.put("text", message);
        map.put("user", user);

        //Construct a Bayeux response message using Data and DeliverResponse.
        Data data = new Data();
        data.setMapData(map);

        DeliverResponse deliverResponse = new DeliverResponse();
        deliverResponse.setChannel(channel);
        deliverResponse.setData(data);
        deliverResponse.setLast(true);
        deliverResponse.setFollow(true);
        deliverResponse.setFinished(true);

        //send the Bayeux message out by invoking notify().
        context.notify(deliverResponse);

        out.println("Data is sent.");

        } else {
        out.println("No data is sent.");
        }
        }
       }
Understanding the code. In the example above, we will generate a cometd Bayeux message in a servlet ChatExternalServlet.java. First, we import all the Grizzly Comet Framework packages at the beginning:
    import com.sun.grizzly.comet.CometContext;
    import com.sun.grizzly.comet.CometEngine;
    import com.sun.grizzly.cometd.bayeux.Data;
    import com.sun.grizzly.cometd.bayeux.DeliverResponse;
In doPost() implementation, one can get a CometContext as follows:
    CometEngine engine = CometEngine.getEngine();
    CometContext context = engine.getCometContext(channel);
1. In our case, the channel is "/chat/demo" which is defined in exercise 1 chat application. In doPost(), we construct a Bayeux response message by using classes in package com.sun.grizzly.cometd.bayeux. The classes that we need to use are DeliverResponse and Data. It is constructed as follows: Map<String, Object> map = new HashMap<String, Object>(); map.put("text", message); map.put("user", user); Data data = new Data(); data.setMapData(map); DeliverResponse deliverResponse = new DeliverResponse(); deliverResponse.setChannel(channel); deliverResponse.setData(data); deliverResponse.setLast(true); deliverResponse.setFollow(true); deliverResponse.setFinished(true); Note that text and user headers are defined in exercise 1 chat application. deliverResponse.setLast(true) indicates that this is the last Bayeux message in this Http response. deliverResponse.setFollow(true) indicates that this is not the first Bayeux message in this Http response. deliverResponse.setFinished(true) indicates that the underlying connection needs to be resumed. Then we can send the Bayeux message as follows: context.notify(deliverResponse); Step 3: Run the project With the NetBeans IDE Open sun-web.xml in NetBeans. The sun-web.xml is located in chat_ExternalServlet project under /Web Pages/WEB-INF. In Context Root area, type /cometd so it will enable comet servlet once the project is invoked. Make sure the comet is already enabled in GlassFish and GlassFish is already started. See exercise 0 for detail on how to enable comet support in Glassfish if you haven't done son. In the Projects tab, right click and select Run. Run option will compile, build and invoke the application in the default browser, let's call it browser A1 as shown below. Enter name to join the chat and then enter some message. You will see the chat application running as you have seen in exercise 1. Open another browser A2, preferably with different profile or different brand of browser, and type http://localhost:8080/cometd to access the application. Enter name to join the chat and then enter some message. Open another browser B and type http://localhost:8080/cometd/ChatExternalServlet?user=me&message=hello and hit return. It will invoke the servlet ChatExternalServlet. Notice user=me&message=hello are in the HTTP request. The following shows the response in browser B. The following is the response in browser A1: me: hello message is sent by the ChatExternalServlet and received in client chat browser. Browser A2 will have the same response. Step 4: Implement Periodic Message in Servlet ChatExternalServlet We will add a timer service to generate some periodic maintenance message to the chat client. In ChatExternalServlet.java, first add the following code to define the timer.
       /**
        * Push message on the chat room every 10 seconds.
        */
        public ScheduledThreadPoolExecutor timer =
        new ScheduledThreadPoolExecutor(1);
2. It will look like the following in NetBeans IDE In servlet init() method, add a timer service routine like the following code template. You will need to complete the code based on the instruction in red. This wake up message is scheduled to push to the chat client every 10 seconds.
       timer.scheduleAtFixedRate(new Runnable(){
        public void run(){
        CometEngine engine = CometEngine.getEngine();
        CometContext context = engine.getCometContext(channel);

        if (context != null) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("text", "Wake up call form the chatroom :-)");
        map.put("user", "ChatMonitor");
        //Construct Bayeux Data by creating the Data and add the map into it.

        DeliverResponse deliverResponse = new DeliverResponse();
        //Construct DeliveryResponse by setChannel, setData, setLast, setFollow, and setFinished.

        try{
        context.notify(deliverResponse);

        } catch(IOException ex){
        ex.printStackTrace();
        }
        }
        }
        }, 10, 10, TimeUnit.SECONDS);
3. After you have completed the code in inti() method, it will look like the following in NetBeans. One last step is to clean up the resources of the timer. Add the following destroy() method to the servlet.
          @Override
          public void destroy(){
              timer.shutdown();
          }
Step 5: Run the Project With the NetBeans IDE Now repeat the steps in Step 3 from 2 to 5. Now you will see the timer is generating all the message to the chat client as shown below. ### Summary In this exercise, you have learned how to easily develop a servlet to interact with the chat clients by using Grizzly Comet Framework APIs. Back to top Next exercise