Get tips on using enterprise Java technologies and APIs, such as those in Java Platform, Enterprise Edition (Java EE).
Enterprise Tech Tips
Archives
« May 2008
SunMonTueWedThuFriSat
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
       
Today
Click me to subscribe
Search

Links
 

Today's Page Hits: 891

« Improving JSF Securi... | Main | Testing Interoperabi... »
Friday Oct 26, 2007
Client-Side Polling With Dynamic Faces

By Roger Kitain

The world of dynamic web applications offers various ways for a client and server to interact. Two approaches are particularly well suited for situations when information on the server changes frequently. These approaches are:

In HTTP streaming, the client/server connection is left open for an extended period of time so that data is streamed from the server to the client. This approach is also known as server-side push, reverse Ajax, or comet. As information changes on the server, updates are pushed to the client.

With client polling, the browser periodically issues an XMLHttpRequest call to obtain new information from the server. For example, a client can send an XMLHttpRequest to the server every five seconds to get new information. This approach is also known as periodic refresh.

The Dynamic Faces framework brings the power of Ajax to traditional JavaServer Faces Technology (often abbreviated as JSF) applications. Ajax function calls are typically made in JavaScript, which can be unfamiliar to Java developers. With Dynamic Faces, you can add Ajax functionality to a JSF application with little or no JavaScript. Dynamic Faces provides a small "out of the box" JavaScript library that you can use with a JSF application.

This tip will show you how you can use Dynamic Faces to build a real-time, stock query application that does client-side polling. You'll see that you don't have to do much JavaScript coding. A package that contains the code for the sample application accompanies the tip. The code examples in the tip are taken from the source code of the sample (which is included in the package).

The Stock Query Application

This tip uses a stock query application to demonstrate client-side polling with Dynamic Faces.

First, let's take a look at the user interface (UI) for the application.

User Interface

Stock Query
Stock Query
 

The UI is pretty basic. You enter one or more space-delimited stock symbols in the Symbol text field and click the Search button. In response, the application displays a table of data pertinent to the stocks represented by the symbols you entered.

You enter proxy information in the Proxy Host and Proxy Port fields if you are behind a firewall.

The most interesting feature of the UI is the Streaming field. The choices are On or Off. If Streaming is set to On, the client polls the server, firing Ajax transactions every 10 seconds (or a specified time interval).

The Remote/Local field allows you to choose either Local or Remote. If you select Local, the application uses local data. This is the choice to make if a network connection is not available. If you select Remote, the application calls the Yahoo Stock Quoting service to get the stock data.

The size of the result table dynamically changes depending on the number of symbols that you enter.

Now let's take a look at the artifacts used in the application.

Artifacts

There are only three artifacts used in the application:

JSP Page

Here's a snippet of the JSP page for the application, home.jsp, showing the relevant parts:

   <f:view>
   <html>
   <head>
   ...
   ...
   <jsfExt:scripts/>
   <script type="text/javascript">
   ...
   ...
   include_js('javascripts/stock-faces.js');
   </script>
   </head>
   <body>
     <h:form id="form" prependId="false">
     ...
     <h:panelGrid border="1" columns="1" 
        styleClass="panel-input-border">
             <h:panelGrid border="1" columns="7">
                 <h:outputText value="Symbol:"/>
                 <h:inputText id="symbol"/>
                 <h:commandButton id="search" value="Search"
                    onclick="DynaFaces.fireAjaxTransaction(
                    this, {});return false;"
               actionListener="#{bean.getStockInfo}" />
               ...
               <h:selectOneMenu id="streaming" value="Off" 
                  onchange="toggleStreaming()">
               ...
             </h:panelGrid>
     </h:panelGrid>  
     
     <h:panelGrid id="stockdata" border="1" columns="8"
       styleClass="panel-data-border" rendered="false">
     ...
   </body>
   </html>
   </f:view> 

Here are some things to notice in the code snippet:

JavaScript File

Here is the JavaScript file, stockfaces.js, for the application:

   var pollId;
   
   /** Delay between requests to the server when polling. */ 
   var pollDelay = 10000;
   
   /** Start polling the server */
   function start() {
       pollId = setInterval(poll, pollDelay);
   }  
   
   /** Stop polling the server */
   function stop() {
       clearInterval(pollId);
   } 
   
   function poll() {
       queueEvent();
       DynaFaces.fireAjaxTransaction(null, {});
   }
   
   function queueEvent() {
       var actionEvent =
           new DynaFaces.ActionEvent("search",
           DynaFaces.PhaseId.INVOKE_APPLICATION);
       DynaFaces.queueFacesEvent(actionEvent);
       return false;
   }
   
   function toggleStreaming() {
       var menu = document.getElementById("streaming");
       var idx = menu.selectedIndex;
       var streaming = menu[idx].value;
       if (streaming == "Off") {
           stop();
       } else if (streaming == "On") {
           start();
       }
   }

Here's what the JavaScript code in the file does:

JSF Managed Bean

Here's a snippet of the JSF managed bean, Bean.java, showing the relevant parts:

   /**
    * This bean has methods to retrieve stock information from 
    * the Yahoo quote service.
    */
   public class Bean {
   
       private static final String SERVICE_URL =
          "http://quote.yahoo.com/d/quotes.csv";
       /**
        * Action method that is used to retrieve stock 
        * information. This method uses two helper methods - one 
        * to get the stock information, and the other to 
        * dynamically build the "data" components for the UI.
        */
       public void getStockInfo(ActionEvent ae) {
   ...
   ...                       
          stockData = getStockData(symbols);                       
          buildUI(stockData);
   ...
    }
    
    /**
     * Helper method to get the stock data (remotely).
     */
    private String[] getStockData(String[] symbols)
        throws IOException, MalformedURLException {
        String[] data = new String[symbols.length];
        for (int i=0; i<symbols.length; i++) {
            StringBuffer sb = new StringBuffer(SERVICE_URL);
    ...
    ...
        }
        return data;
    }
    
    /**
     * Helper method to dynamically add JSF components to 
     * display the data.
     */
    private void buildUI(String[] stockData) {
        FacesContext context = 
            FacesContext.getCurrentInstance();
        UIForm form = 
            (UIForm)context.getViewRoot().findComponent("form");
        UIPanel dataPanel = 
            (UIPanel)form.findComponent("stockdata");
    ...
    ...
        // Create and add components with data values
    
        // Symbol
        ...
        dataPanel.getChildren().add(outputComponent);
        
        // Name
        ...
        dataPanel.getChildren().add(outputComponent);
        
        // Open Price (if any)
        ...
        dataPanel.getChildren().add(outputComponent);
        ...
        ...
        }
        dataPanel.setRendered(true);
    }

This JSF Managed Bean has an action method, getStockInfo, that does two things:

The action method, getStockInfo, is called when the Search button is pressed. It is also called as the result of an Ajax poll request. This is because each client poll queues an action event tied to this event handler. Refer to the queueEvent method in the stock-faces.js JavaScript file.

Running the Sample Code

A sample package accompanies this tip that demonstrates the techniques covered in the tip. You can deploy the sample package on any web container that supports the Servlet 2.5 API, JavaServer Pages (JSP) Technology 2.1, and JavaServer Faces Technology 1.2. These instructions assume that you are using GlassFish.

To install and run the sample:

  1. If you haven't already done so, download and install GlassFish.

  2. Download the sample application for the tip and extract its contents. You should now see the newly extracted directory as <sample_install_dir>/client-poll-dfaces, where <sample_install_dir> is the directory where you installed the sample application. For example, if you extracted the contents to C:\ on a Windows machine, then your newly created directory should be at C:\client-poll-dfaces.

  3. Start GlassFish by entering the following command:

    <GF_HOME>/bin/asadmin start-domain domain1

    where <GF_HOME> is the directory where you installed GlassFish.

  4. Deploy the sample by copying

    <sample_install_dir>/client-poll-dfaces/stock-faces.war to <GF_HOME>/domains/domain1/autodeploy

  5. Open your browser to the URL: http://localhost:8080/stock-faces/. You should see the Stock Query Application UI.

    Stock Query
    Stock Query
     
  6. Enter one or more stock symbols delimited by a space, for example, JAVA LMT IBM. If you are behind a firewall, specify the pertinent proxy information in the Proxy Host and Proxy Port fields. Click the Search button. You should see a table of stock data displayed for the symbols you entered.

    Stock Query
    Stock Query
     
  7. Try different combinations of streaming and Local/Remote settings, and see what happens. You'll notice that if Streaming is set to On, you don't have to press the Search button. The stock symbols that you specified in the Symbol text field are automatically sent using the Ajax mechanism to the server. If you choose Local, the names and prices are simulated, so that the data will likely be different than the result of a Remote selection.

Summary

This tip demonstrated how you can combine JSF with Ajax to produce dynamic applications. This application illustrated two features of Dynamic Faces:

You can find out more about Dynamic Faces in the jsf-extensions project. Also see Ed Burns's blog Introducing Project Dynamic Faces.

About the Author

Roger Kitain is the JavaServer Faces technology co-specification lead. He has been extensively involved with server-side web technologies and products since 1997. Roger started working on JSF in 2001 as a member of the reference implementation team. He has experience with Java Servlet technology, JSP, and most recently has been involved with different rendering technologies for JSF.

Posted at 01:22PM Oct 26, 2007 by edort in Sun  |  Comments[3]

Comments:

Hi,

First of All Thanks a lot for publishing this artical and it is also informative.

Posted by Nihar Bhatt on December 19, 2007 at 10:49 AM PST #

Hi....

Thanks a lot .... i run your sample successfully ... and it is really helpful to me...

Posted by Nihar Bhatt on December 19, 2007 at 10:55 AM PST #

Thanks for the positive feedback.

Posted by Ed Ort on December 20, 2007 at 08:45 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed