Navigation Bar

Tuesday, February 2, 2010

Jakarta Struts : Using AJAX to populate form data

 In the GetQuote example we provide a list of stocks in a drop down. When a particular stock is selected we want to automatically display the stock description. 


index.jsp

<%@ page language="java" %>
<%@ page import="java.sql.*" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

<script type="text/javascript" src="Ajax.js"></script>

<html>
<head>
    <title>Stock Quote Struts Application</title>
</head>

<body>
    <table width="500" border="0" cellspacing="0" cellpadding="0">
        <tr>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td height="68" width="48%">
                <div align="left">
                    <img src="images/stockquote.jpg" alt="Logo">
                </div>
            </td>
        </tr>
        <tr>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>&nbsp;</td>
        </tr>       
    </table>

    <h2>Enter a Stock Symbol</h2>

    <!-- Begin Struts form -->
    <html:form action="Lookup">
        <table width="45%" border="0">
            <tr>
                <td>Stock Symbol:</td>
                <select name="symbol" onchange="retrieveURL('/getquoteAjax/stockname.do?','lookupForm',this);">
       <option value="-1">Select</option>

       <%
            Connection conn = null;
            String url = "jdbc:mysql://localhost:3306/stocks?useSSL=false&allowPublicKeyRetrieval=true";
            String user = "root";
            String pass = "mysql";
            int sumcount = 0;
            Statement st;

            try {
                Class.forName("com.mysql.jdbc.Driver").newInstance();
                conn = DriverManager.getConnection(url, user, pass);
                String query = "select * from stocks";
                st = conn.createStatement();
                ResultSet rs = st.executeQuery(query);
        %>
        <%
            while (rs.next()) {
        %>
        <option value="<%=rs.getString(1)%>"><%=rs.getString(1)%></option>
        <%
            }
        %>
        <%
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        %>
        </select>
         </tr>
         <tr><td><b>Stock Name:</b></td>
         <td><span id="stockName"><input type="text" name="stock_name" id="sname" value=""></span></td></tr>   
            <tr>
                <td colspan="2">
                    <html:submit value="Get Quote" />
                </td>
            </tr>
        </table>
    </html:form>
</body>
</html>


Ajax.js

/**
 * Ajax.js
 *
 * Collection of Scripts to allow in page communication from browser to (struts) server
 * ie can reload part instead of full page
 *
 * How to use
 * ==========
 * 1) Call retrieveURL from the relevant event on the HTML page (e.g. onclick)
 * 2) Pass the url to contact (e.g. Struts Action) and the name of the HTML form to post
 * 3) When the server responds ...
 *         - the script loops through the response , looking for <span id="name">newContent</span>
 *          - each <span> tag in the *existing* document will be replaced with newContent
 *
 * NOTE: <span id="name"> is case sensitive. Name *must* follow the first quote mark and end in a quote
 *         Everything after the first '>' mark until </span> is considered content.
 *         Empty Sections should be in the format <span id="name"></span>
 */

//global variables
//  var req;
 // var which;


  /**
   * Get the contents of the URL via an Ajax call
   * url - to get content from (e.g. /struts-ajax/sampleajax.do?ask=COMMAND_NAME_1)
   * nodeToOverWrite - when callback is made
   * nameOfFormToPost - which form values will be posted up to the server as part
   *                    of the request (can be null)
   */
    function retrieveURL(url, nameOfFormToPost, selectElement) {
    // Get symbol value from the select element
    var symbolValue = selectElement.value;
    
    console.log("retrieveURL called", selectElement);
    console.log("Symbol value:", symbolValue);
    console.log("Base URL:", url);
    
    // Validate selection
    if (!symbolValue || symbolValue === "-1" || symbolValue === "") {
        alert("Please select a valid stock symbol");
        return;
    }
    
    // Build final URL with symbol parameter
    // Since url already ends with '?', just append the parameter
    var finalUrl = url + "symbol=" + encodeURIComponent(symbolValue);
    
    console.log("Final URL:", finalUrl);
    
    // Create XMLHttpRequest
    var req;
    
    if (window.XMLHttpRequest) { // Non-IE browsers
        req = new XMLHttpRequest();
        
        req.onreadystatechange = function() {
            processStateChange(req);
        };
        
        try {
            req.open("GET", finalUrl, true);
            req.send(null);
        } catch (e) {
            alert("Problem Communicating with Server\n" + e);
        }
        
    } else if (window.ActiveXObject) { // IE
        req = new ActiveXObject("Microsoft.XMLHTTP");
        if (req) {
            req.onreadystatechange = function() {
                processStateChange(req);
            };
            req.open("GET", finalUrl, true);
            req.send();
        }
    }
}


function processStateChange(req) {
        console.log("ReadyState:", req.readyState);
        console.log("Status:", req.status);
        if (req.readyState == 4) { // Complete
            if (req.status == 200) { // OK response
                console.log("Processing response..........");
                console.log("Ajax response:", req.responseText);
                // Split the text response into Span elements
                var spanElements = splitTextIntoSpan(req.responseText);
                console.log("Span elements:", spanElements);
                //alert("Span elements:", spanElements);
                // Use these span elements to update the page
                replaceExistingWithNewHtml(spanElements);
            } else {
                alert("Problem with server response:\n " + req.statusText);
            }
        }
    }


    
 

 
 /**
 * Splits the text into <span> elements
 * @param the text to be parsed
 * @return array of <span> elements - this array can contain nulls
 */
 function splitTextIntoSpan(textToSplit){
 
      //Split the document
     returnElements=textToSplit.split("</span>")
    
     //Process each of the elements    
     for ( var i=returnElements.length-1; i>=0; --i ){
        
         //Remove everything before the 1st span
         spanPos = returnElements[i].indexOf("<span>");       
        
         //if we find a match , take out everything before the span
         if(spanPos>0){
             subString=returnElements[i].substring(spanPos);
             returnElements[i]=subString;
        
         }
     }
    
     return returnElements;
 }
 
 /*
  * Replace html elements in the existing (ie viewable document)
  * with new elements (from the ajax requested document)
  * WHERE they have the same name AND are <span> elements
  * @param newTextElements (output of splitTextIntoSpan)
  *                    in the format <span id=name>texttoupdate
  */
 function replaceExistingWithNewHtml(newTextElements){
 
     //loop through newTextElements
     for ( var i=newTextElements.length-1; i>=0; --i ){
 
         //check that this begins with <span
         if(newTextElements[i].indexOf("<span")>-1){
            
             //get the name - between the 1st and 2nd quote mark
             startNamePos=newTextElements[i].indexOf('"')+1;
             endNamePos=newTextElements[i].indexOf('"',startNamePos);
             name=newTextElements[i].substring(startNamePos,endNamePos);
            
             //get the content - everything after the first > mark
             startContentPos=newTextElements[i].indexOf('>')+1;
             content=newTextElements[i].substring(startContentPos);
            
             //Now update the existing Document with this element
            
                 //check that this element exists in the document
                console.log("element check:", document.getElementById(name));
                console.log("element name:", name);
                 if(document.getElementById(name)){
                
                     //alert("Replacing Element:"+name);
                     document.getElementById(name).innerHTML = content;
                 } else {
                     //alert("Element:"+name+"not found in existing document");
                 }
         }
     }
 }
 

struts-config.xml changes

        <action path="/stockname"
            type="org.StockNameAction"
            name="lookupForm" >
        <forward name="success" path="/index.jsp" />
        <forward name="failure" path="/index.jsp" />
        </action>    


StockNameAction.java

package org;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.io.*;

import org.apache.log4j.Logger;


public class StockNameAction extends Action {
    protected final Logger log = Logger.getLogger(getClass());
    protected String getStockName ( HttpServletRequest request, String symbol) {
        String stockName = null;
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        DataSource dataSource = null;
        try {
            dataSource = getDataSource(request);
            conn = dataSource.getConnection();
            stmt = conn.createStatement();
            rs = stmt.executeQuery ("select stock_name from stocks where symbol = '" + symbol + "'");
            if (rs.next()){
                String tmp = "";
                tmp = rs.getString("stock_name");
                stockName = new String(tmp);
                System.err.println ("stockName : " + stockName);
            } //end rs.next
            else {
                System.err.println("Symbol not found returning null [" + symbol);
            }   
        }    //end try
        catch (SQLException sqle) {
                    System.err.println (sqle.getMessage());
        }
        finally {
            if (rs != null) {
                try {
                    rs.close();
                }
                catch (SQLException sqle) {
                    System.err.println (sqle.getMessage());
                }
                rs = null;   
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } //end try
                catch (SQLException sqle) {
                    System.err.println (sqle.getMessage());
                }
                stmt = null;   
            } // end stmt not null
            if (conn != null) {
                try {
                    conn.close();
                } //end try
                catch (SQLException sqle) {
                    System.err.println (sqle.getMessage());
                }
                conn = null;   
            } // end conn not null
        } //end finally   
        if ( symbol.equalsIgnoreCase ("SUNWWWW") ) {
            return new String ("SUNWWWW");
        }
        return stockName;
    } //end Action
    
    public ActionForward execute (ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response )
                throws IOException, ServletException {
            String stockName = null;
           
            String target = new String ("success");
            if (form != null ) {
                //Use the LookupForm to get the request parameters
                LookupForm lookupForm = (LookupForm) form;
                String symbol = lookupForm.getSymbol();
            //    request.getParameter(symbol);
            //    System.err.println("In execute Symbol " + symbol);
                log.debug("StockNameAction " + symbol);
                stockName = getStockName(request, symbol);
                StringBuilder html = new StringBuilder();
                html.append("<span id=\"stockName\">")
                .append("<input type=\"text\" name=\"stock_name\" id=\"sname\" value=\"")
                .append(stockName)
                .append("\" readonly>")
                .append("</span>");
               
                System.out.println("Generated HTML: " + html.toString());
               
                // Write directly to response
                response.setContentType("text/html;charset=UTF-8");
                response.setHeader("Cache-Control", "no-cache");
               
                PrintWriter out = response.getWriter();
                out.print(html.toString());
                out.flush();
                out.close();
               
                System.out.println("=== getStockName END ===");
       
           
            }
            
            return null; // Important: return null when writing directly to response
    } //execute
}





No comments:

Post a Comment