BUY THIS BOOK
Add to Cart

Print Book $29.99


Add to Cart

Print+PDF $38.99

Add to Cart

PDF $23.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £20.99

What is this?

Looking to Reprint or License this content?


Ajax on Java
Ajax on Java

By Steven Douglas Olson
Book Price: $29.99 USD
£20.99 GBP
PDF Price: $23.99

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Setup
To begin, you'll need to set up the environment for developing and deploying the Ajax examples in this book. This environment is different from that used for many other technologies.
To clarify, Ajax isn't a language or a software package; there is no single source of Ajax technology. If you're a Java developer, you probably already have many of the tools you need to work with Ajax.
Let's review the minimum requirements that you will need to develop an Ajax application with Java:
Browser
You will need a browser that supports JavaScript (Internet Explorer, Safari, Mozilla, Opera, Firefox, etc.).
Java Development Kit
You will need a Java compiler and libraries, preferably for Java 5 or Java 6.
Apache Ant
You will need Apache Ant. You can get by without Ant, but only if you're a masochist. (An alternative is Maven. The examples in this book assume you're using Ant, but adapting them to Maven shouldn't be difficult.)
Application server
The server piece can be any application server that can host Java servlets and can communicate via HTTP. The examples in this book have been developed using Sun's JDK 1.5 and Apache Tomcat 5.0, but there are many other application servers (such as JRun, JBoss, Resin, WebLogic, WebSphere, and Glassfish) that you can use with Ajax.
If you are going to use a servlet container other than Tomcat, you can skip the "Installing Tomcat" section. However, I advise you to use Tomcat first; after you understand an example and have it running, then try it on a different server.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Requirements
To clarify, Ajax isn't a language or a software package; there is no single source of Ajax technology. If you're a Java developer, you probably already have many of the tools you need to work with Ajax.
Let's review the minimum requirements that you will need to develop an Ajax application with Java:
Browser
You will need a browser that supports JavaScript (Internet Explorer, Safari, Mozilla, Opera, Firefox, etc.).
Java Development Kit
You will need a Java compiler and libraries, preferably for Java 5 or Java 6.
Apache Ant
You will need Apache Ant. You can get by without Ant, but only if you're a masochist. (An alternative is Maven. The examples in this book assume you're using Ant, but adapting them to Maven shouldn't be difficult.)
Application server
The server piece can be any application server that can host Java servlets and can communicate via HTTP. The examples in this book have been developed using Sun's JDK 1.5 and Apache Tomcat 5.0, but there are many other application servers (such as JRun, JBoss, Resin, WebLogic, WebSphere, and Glassfish) that you can use with Ajax.
If you are going to use a servlet container other than Tomcat, you can skip the "Installing Tomcat" section. However, I advise you to use Tomcat first; after you understand an example and have it running, then try it on a different server.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Installing Tomcat
Start by downloading and installing the latest released version of Tomcat (browse to http://jakarta.apache.org/tomcat/ and select the Current Releases link under the Downloads section). If you have never used Tomcat, you're in for a pleasant surprise. Tomcat is a great servlet engine that is used as the reference for the Java Servlet and JavaServer Pages technologies.
Tomcat is free, and Tomcat is mature. If you get a released production version, you will find that it is as stable as any production-version commercial application server. The Tomcat project also has good documentation; take advantage of it. If you're new to Tomcat, another good resource is Jason Brittain and Ian Darwin's Tomcat: The Definitive Guide (O'Reilly).
For Linux/Unix, download the tar.gz file and install it by running tar -zxvf in the directory where you want Tomcat to reside (e.g., /usr/local/tomcat). For Windows, Tomcat ships as a self-extracting executable: just download and run setup.exe to install it.
Once you've installed Tomcat, start it running on Linux or Unix with the following command:
/<tomcat install directory>/bin/startup.sh
On Windows, use the following command:
\<tomcat install directory>\bin\startup.bat
Then start up a browser and browse to http://localhost:8080 to see the Tomcat home page. From there you can run the example servlets to ensure that your installation is working correctly.
To shut down Tomcat, run the command shutdown.sh (Linux) or shutdown.bat (Windows) from your install directory.
All the examples in this book will be built and deployed with Ant. (If you're not familiar with Ant and the concept of build files, you might want to take some time to familiarize yourself with them now.) The build files will require the TOMCAT_HOME environment variable to be set properly, to ensure that when you deploy your applications, build.xml will copy everything you need into the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Installing Ant
To run the examples in this book, you'll also need to download and install the Ant project. Browse to http://ant.apache.org and grab the latest version.
Make sure that the bin directory of your Ant installation is in your path, and then type ant at the command prompt. Ant should come back with the message "Build file does not exist." This message means that Ant is installed correctly and could not find the build.xml file when it tried to load it.
If you don't have Ant installed correctly, you will see an error such as "executable file ant not found." In this case, check to make sure that your PATH environment variable is set to include the bin directory of the Ant installation. As with TOMCAT_HOME, Windows users can set the PATH variable through System Properties (Start → Control Panel → System Properties → Advanced → Environment Variables), while Linux and Unix users must add lines such as the following to their shell's initialization file (most likely .bashrc):
export TOMCAT_HOME=/usr/local/tomcat/Tomcat5.0
export PATH=$PATH:$TOMCAT_HOME/bin
Once you have Ant installed correctly, you can use it to build the applications presented in this book. If you need more information on Ant, consult the documentation at http://ant.apache.org or one of the many books written about Ant. Steve Holzner's Ant: The Definitive Guide (O'Reilly) is the reference I use, and it has served me well.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: JavaScript for Ajax
Ajax is centered around the clever use of JavaScript. It isn't a web framework, like Struts or Tapestry, and it isn't some fancy new technology with a cool acronym; Ajax boils down to using JavaScript to interact directly with the web server, avoiding the submit/response cycle all too familiar to web users.
Java programmers have typically avoided JavaScript, sometimes for good reasons and sometimes for bad ones. Certainly, adding another layer of scripting to a JSP page can only add to the confusion. However, JavaScript runs entirely on the browser and is therefore very fast. There's no waiting for the server to generate a response: JavaScript can compute a result and update the page immediately.
Ajax adds server interaction, but without the Submit button. Whenever data is needed, the JavaScript in the web page makes a request, and the server replies with data—but not another HTML page. The server returns data that the JavaScript displays in the existing page. The result is that your web application feels a lot more like a desktop application. In short, you can achieve a rich application experience in your web pages by using Ajax.
This book won't attempt to teach JavaScript, or even to analyze its pros and cons. I assume that you have had some exposure to JavaScript. If you're new to it, check out JavaScript: The Definitive Guide, by David Flanagan (O'Reilly). This is the best JavaScript reference available. JavaScript isn't Java, though reading JavaScript code shouldn't be hard for any Java developer. You will find that the JavaScript used in this chapter is pretty easy; as long as you can get through the syntax, you shouldn't need to review or study JavaScript just yet.
We'll begin with the complete HTML and JavaScript code for our first application, a simple web page that displays the decimal value of any character. Then we'll break apart the JavaScript and examine it.
The HTML is presented in Example 2-1.
Example 2-1.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Creating the Application
We'll begin with the complete HTML and JavaScript code for our first application, a simple web page that displays the decimal value of any character. Then we'll break apart the JavaScript and examine it.
The HTML is presented in Example 2-1.
Example 2-1. index.html
<html>
<head>
    <link rel="stylesheet" type="text/css" href="style.css">
    <SCRIPT language="JavaScript" src="ajax.js"></SCRIPT>
    <title>Ajax On Java, Chapter 2 Example</title>
</head>
<body onload="focusIn( );">
    <h1> AJAX CHARACTER DECODER </h1>
    <h2> Press a key to find its value. </h2>
    <table>
        <tr>
            <td>
                Enter Key Here ->
                <input type="text" id="key" name="key"
                       onkeyup="convertToDecimal( );">

            </td>
        </tr>
    </table>
    <br />
    <table>
        <tr>
            <td colspan="5" style="border-bottom:solid black 1px;">
                Key Pressed:
                <input type="text" readonly id="keypressed">
            </td>
        </tr>
        <tr>
            <td> Decimal </td>
        </tr>
        <tr>
            <td><input type="text" readonly id="decimal"></td>
        </tr>
    </table>
</body>
</html>
For the most part, this is standard HTML. There are only two JavaScript references: focusIn( ) and convertToDecimal( ). The focusIn( ) function merely puts the cursor in the right input field when the page loads, so the user doesn't have to move it there with the mouse.
The convertToDecimal( ) function will be our entry into the Ajax world. Example 2-2 lays out the JavaScript code that supports our web page, ajax.js.
Example 2-2. ajax.js
var req;

function convertToDecimal( ) {
    var key = document.getElementById("key");
    var keypressed = document.getElementById("keypressed");
    keypressed.value = key.value;
    var url = "/ajaxdecimalcodeconverter/response?key=" + escape(key.value);
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest( );
    }
    else if (window.ActiveXObject) {
        req = new ActiveXObject("Microsoft.XMLHTTP");
    }
    req.open("Get",url,true);
    req.onreadystatechange = callback;
    req.send(null);
}

function callback( ) {
    if (req.readyState==4) {
        if (req.status == 200) {
            var decimal = document.getElementById('decimal');
            decimal.value = req.responseText;
        }
    }
    clear( );
}
function clear( ) {
    var key = document.getElementById("key");
    key.value="";
}
function focusIn( ) {
    document.getElementById("key").focus( );
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Running the Example
If you download the code for this example from this book's web site (http://www.oreilly.com/catalog/9780596101879), you can simply copy the files from the ch02 directory. Some developers prefer to hand-type the example code, which does help solidify the examples in one's mind.
To run the example:
  1. Save the HTML code from Example 2-1 in a file called index.html.
  2. Save the JavaScript from Example 2-2 in a file called ajax.js in the same directory.
  3. Save the CSS code from Example 2-3 in a file called style.css in the same directory.
  4. Open index.html with a browser; you should see something similar to Figure 2-1.
Figure 2-1: The Ajax Character Decoder running in Internet Explorer
When you press a key, the key will show up in the "Key Pressed:" field and the input field will be cleared. Since the server isn't implemented yet, you won't see the decimal value. In the next chapter, we'll hook up a servlet that populates the Decimal field.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: A Simple Ajax Servlet
In the previous chapter, we wrote a JavaScript/HTML client for a system that converts keystrokes to the corresponding decimal values. Now we need to focus on the backend: the Java servlet that provides the client with the information it needs. The XMLHTTPRequest( ) function in the client sends a request out into the ether; it doesn't care what kind of server replies. The response can come from a PHP server, a .NET server, a server hosting Ruby on Rails, a Java server, and so on. Any server that can receive an HTTPRequest and respond with an HTTPResponse will do.
Since this is a book for Java developers, we'll create a servlet that intercepts the request, converts the keystroke into its decimal representation, and sends the resulting data back to the client.
The first version of our servlet is very simple: it computes a single result (the value of the keystroke in decimal) and sends it back to the client. The complete servlet code is presented in Example 3-1.
Example 3-1. The AjaxResponseServlet
/*
 * Converts a character to decimal and sends back the
 * value in the response.
 */
package com.oreilly.ajax.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AjaxResponseServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {

        String key = req.getParameter("key");
        if (key != null) {
            // extract the first character from key
            // as an int, then convert that int to a String
            int keychar = key.charAt(0);
            String decimalString = Integer.toString(keychar);
            // set up the response
            res.setContentType("text/xml");
            res.setHeader("Cache-Control", "no-cache");
            // write out the response string
            res.getWriter( ).write(decimalString);
        }
        else {
            // if key comes back as a null, return a question mark
            res.setContentType("text/xml");
            res.setHeader("Cache-Control", "no-cache");
            res.getWriter( ).write("?");
        }
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building and Deploying the Ajax Application
We now have all the components required to build the example. If you have never used Ant, you are about to be surprised by a powerful tool.
An Ant tutorial is beyond the scope of this book. If you don't understand the build.xml file in this section, you should refer to the Ant documentation at http://ant.apache.org.
The build.xml file presented in Example 3-3 builds the project and moves it to the tomcat/webapps directory; that's all Tomcat needs in order to begin running the web application. Make sure you have set TOMCAT_HOME to the directory where you installed Tomcat. Refer back to Chapter 1 for setup details.
Example 3-3. build.xml
<?xml version="1.0"?>
<project name="CH03 AJAX-CODECONVERTER" default="compile" basedir=".">

    <property environment="env"/>
    <property name="src.dir" value="src"/>
    <property name="war.dir" value="war"/>
    <property name="class.dir" value="${war.dir}/WEB-INF/classes"/>
    <property name="lib.dir" value="${war.dir}/WEB-INF/lib"/>
    <property name="webapp.dir"
              value="${env.TOMCAT_HOME}/webapps/ch03-ajaxcharacterconverter"/>

    <path id="ajax.class.path">
        <fileset dir="${lib.dir}">
            <include name="*.jar"/>
        </fileset>
    </path>

    <target name="init">
        <mkdir dir="${class.dir}"/>
    </target>

    <target name="compile" depends="init"
            description="Compiles all source code.">
        <javac srcdir="${src.dir}" destdir="${class.dir}" debug="on"
               classpathref="ajax.class.path"/>
    </target>

    <target name="clean" description="Erases contents of classes dir">
        <delete dir="${class.dir}"/>
    </target>

    <target name="deploy" depends="compile"
            description="Copies the contents of web-app to destination dir">
        <copy todir="${webapp.dir}">
            <fileset dir="${war.dir}"/>
        </copy>
    </target>

</project>
When you've created the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Running the Example
Start Tomcat and open a browser. Enter the address where you deployed the application. If you deployed it using the build.xml file in this book, the address should be http://localhost:8080/ajax-decimal/index.html.
Your browser should display the page shown in Figure 3-2. When you press a key, the JavaScript will move the key pressed to the "Key Pressed:" field, clear the input field, and make a request to the server to convert the key to its decimal value. The server then does the simple conversion and returns the value, which is picked up by the callback function and put into the Decimal field.
Figure 3-2: Ajax Character Decoder running in Mozilla Firefox
Congratulations! You've just completed a full Ajax-enhanced Java application. As simple as the application is, it demonstrates most of the major components you need in order to develop Ajax applications with Java.
Notice that I said most, not all, of the components. We are still missing an important piece of Ajax: XML. And, to be sure, there are fancier, cleverer ways to do things: we can use JSF components and the like, and we can come up with better ways to handle the IE/Firefox differences. But still, we now have a working application. Everything else is icing on the cake.
It's true, there is no XML in this example. I avoided XML for two reasons: I wanted to keep the first example as simple as possible, and to show that you don't really have to use XML with Ajax.
So how does XML fit into Ajax? Because Ajax is about passing data back and forth between the browser and the server, there is a need to parse that data. In this very simple example, we only passed one field from the browser to the server and one field back from the server to the browser. In this case, XML is overkill. However, for real-world applications, you'll need to move more complex data, and you'll want a more structured way to represent your data.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: XML and JSON for Ajax
Do you really need XML for an Ajax application? The previous chapter showed that you don't always need XML. In particular, if you only have one data point, XML is overkill. But the fact is, most web applications deal with multiple data points: usernames, passwords, addresses, cities, states, zip codes, etc. How will you decipher those fields when they're sent back from the server?
In some cases, passing a string of delimited values may seem like the simplest approach, but using XML has advantages. For one thing, XML is self-documenting. During debugging, you can look at the XML string and see exactly what goes where; that is a luxury you won't have with a string of comma-separated values.
Another reason for using XML is that an XML parser is built into most browsers. The parsing work has already been done for you; all you have to do is leverage the built-in parser. Sure, you could pass the data in other formats—Java properties files, comma or tab-separated values, YAML files, or a cute custom format that you've designed yourself—but then you would have to write your own parser in JavaScript.
There is another good way to send data to and from the server: JavaScript Object Notation (JSON). We will discuss JSON toward the end of this chapter.
The example in this chapter is similar to the one in the previous chapter, but instead of the server returning one data point, it's going to return five. Retuning a small collection of data shows what happens when you go beyond a single data point and illustrates why most Ajax applications need XML or some other way to structure the data that is passed from the server to the client.
Figure 4-1 shows how the user interface of the application will look when we're done. The design is simple enough: we send a character to the server using XMLHttpRequest( ), and the server responds with a String containing the five conversions in XML format (decimal, octal, hexadecimal, binary, and HTML). The callback( ) function in the client then calls a function to parse the XML and populate the fields in the browser.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Character Decoder
The example in this chapter is similar to the one in the previous chapter, but instead of the server returning one data point, it's going to return five. Retuning a small collection of data shows what happens when you go beyond a single data point and illustrates why most Ajax applications need XML or some other way to structure the data that is passed from the server to the client.
Figure 4-1 shows how the user interface of the application will look when we're done. The design is simple enough: we send a character to the server using XMLHttpRequest( ), and the server responds with a String containing the five conversions in XML format (decimal, octal, hexadecimal, binary, and HTML). The callback( ) function in the client then calls a function to parse the XML and populate the fields in the browser.
Figure 4-1: The complete Ajax Character Decoder example
Now it starts to get fun. One keystroke fills in all the data fields, and although it doesn't look like much is going on from the user's perspective, from the programmer's perspective we know that the application is communicating with the server without a clunky submit or reload or any waiting for the page to refresh.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Setting Up a Simple XML Document
Before we delve into the code, we need to make some decisions. We're going to return data using XML, but how should that XML be structured? What should our XML response look like? We don't want anything complex, so we'll aim to create an XML document that looks like this:
<converted-values>
    <decimal>97</decimal>
    <hexadecimal>0x61</hexadecimal>
    <octal>0141</octal>
    <hyper>&amp;0x61;</hyper>
    <binary>1100001B</binary>
</converted-values>
With this format, the browser can use its document object model (DOM) parser to index and retrieve the data.
There are many ways to create this XML document. For the sake of simplicity, we'll first use a StringBuffer to wrap the data with XML tags. Later, we'll look at other ways to create the XML document.
When I talk about XML formatting, I'm referring to the server wrapping the data in XML. The client receives the XML-formatted string in the HTTPResponse and parses it for the individual data fields. The client passes data through the request using either HTTPPost( ) or HTTPGet( ). There is no reason for the client to send XML data to the server, because the data is already wrapped in the request as name/value pairs.
Let's start by looking at the servlet code that wraps the data in XML. This servlet is shown in Example 4-1.
Example 4-1. The AjaxResponseServlet
/*
 * Converts a character to hex, decimal, binary, octal, and HTML, then
 * wraps each of the fields with XML and sends them back through the response.
 */
package com.AJAXbook.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class AjaxResponseServlet extends HttpServlet {

    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        // key is the parameter passed in from the JavaScript
        // variable named url (see index.html)
        String key = req.getParameter("key");
        StringBuffer returnXML = null;
        if (key != null) {
            // extract the first character from key
            // as an int, then convert that int to a String
            int keyInt = key.charAt(0);
            returnXML = new StringBuffer("\r\n<converted-values>");
            returnXML.append("\r\n<decimal>"+
                             Integer.toString(keyInt)+"</decimal>");
            returnXML.append("\r\n<hexadecimal>0x"+
                             Integer.toString(keyInt,16)+"</hexadecimal>");
            returnXML.append("\r\n<octal>0"+
                             Integer.toString(keyInt,8)+"</octal>");
            returnXML.append("\r\n<hyper>&amp;0x"+
                             Integer.toString(keyInt,16)+";</hyper>");
            returnXML.append("\r\n<binary>"+
                             Integer.toString(keyInt,2)+"B</binary>");
            returnXML.append("\r\n</converted-values>");

            // set up the response
            res.setContentType("text/xml");
            res.setHeader("Cache-Control", "no-cache");
            // write out the XML string
            res.getWriter().write(returnXML.toString( ));
        }
        else {
            // if key comes back as a null, return a question mark
            res.setContentType("text/xml");
            res.setHeader("Cache-Control", "no-cache");
            res.getWriter( ).write("?");
        }
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Back on the Client: Mining the XML
Here's where the fun begins. The client code in Example 4-5 shows how to mine the data fields from the XML document that the server sends.
Example 4-5. The client code
<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
    <STYLE type="text/css">
        .borderless {  color:black; text-align:center; background:powderblue;
                border-width:0;border-color:green;  }
    </STYLE>

    <title>function</title>
    <SCRIPT language="JavaScript" type="text/javascript">
        var req;

        function convertToXML( ) {
            var key = document.getElementById("key");
            var keypressed = document.getElementById("keypressed");
            keypressed.value = key.value;
            var url = "/ajaxcodeconverter-lab2/response?key=" + escape(key.value);
            if (window.XMLHttpRequest) {
                req = new XMLHttpRequest( );
            }
            else if (window.ActiveXObject) {
                req = new ActiveXObject("Microsoft.XMLHTTP");
            }
            req.open("Get",url,true);
            req.onreadystatechange = callback;
            req.send(null);
        }
        function nonMSPopulate( ) {
            xmlDoc = document.implementation.createDocument("","", null);
            var resp = req.responseText;
            var parser = new DOMParser( );
            var dom = parser.parseFromString(resp,"text/xml");

            decVal = dom.getElementsByTagName("decimal");
            var decimal = document.getElementById('decimal');
            decimal.value=decVal[0].childNodes[0].nodeValue;

            hexVal = dom.getElementsByTagName("hexadecimal");
            var hexadecimal = document.getElementById('hexadecimal');
            hexadecimal.value=hexVal[0].childNodes[0].nodeValue;

            octVal = dom.getElementsByTagName("octal");
            var octal = document.getElementById('octal');
            octal.value=octVal[0].childNodes[0].nodeValue;

            hyperVal = dom.getElementsByTagName("hyper");
            var hyper = document.getElementById('hyper');
            hyper.value=hyperVal[0].childNodes[0].nodeValue;

            binaryVal = dom.getElementsByTagName("binary");
            var bin = document.getElementById('bin');
            bin.value=binaryVal[0].childNodes[0].nodeValue;
        }

        function msPopulate( ) {
            var resp = req.responseText;

            var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.async="false";
            xmlDoc.loadXML(resp);

            nodes=xmlDoc.documentElement.childNodes;

            dec = xmlDoc.getElementsByTagName('decimal');
            var decimal = document.getElementById('decimal');
            decimal.value=dec[0].firstChild.data;

            hexi = xmlDoc.getElementsByTagName('hexadecimal');
            var hexadecimal = document.getElementById('hexadecimal');
            hexadecimal.value=hexi[0].firstChild.data;

            oct = xmlDoc.getElementsByTagName('octal');
            var octal = document.getElementById('octal');
            octal.value=oct[0].firstChild.data;

            bin = xmlDoc.getElementsByTagName('binary');
            var binary = document.getElementById('bin');
            binary.value=bin[0].firstChild.data;
            hypertextml = xmlDoc.getElementsByTagName('hyper');
            var hyper = document.getElementById('hyper');
            hyper.value=hypertextml[0].firstChild.data;
        }

        function callback( ) {
            if (req.readyState==4) {
                if (req.status == 200) {

                    if (window.XMLHttpRequest) {
                        nonMSPopulate( );
                    }
                    else if (window.ActiveXObject) {
                        msPopulate( );
                    }
                }
            }
            clear( );
        }

        function clear( ) {
            var key = document.getElementById("key");
            key.value="";
        }

    </SCRIPT>
</head>

<body>
    <H1>
        <CENTER>AJAX CHARACTER DECODER</CENTER>
    </H1>
    <H2>
        <CENTER>Press a key to find its value.</CENTER>
    </H2>
    <form name="form1" action="/ajaxcodeconverter-lab2" method="get">

    <table border="2" bordercolor="black" bgcolor="lightblue" valign="center"
           align="center">
        <tr>
            <td align="center">
                Enter Key Here ->
                <input type="text" id="key" name="key" maxlength="1" size="1"
                       onkeyup="convertToXML( );">
            </td>
        </tr>
    </table>
    <br>
    <table class="borderless" border="1" valign="center" align="center">
        <tr>
            <td align="center" colspan="5">
                Key Pressed:&nbsp;
                <input class="borderless" type="text" readonly id="keypressed"
                       maxlength="1" size="1">
            </td>
        </tr>
        <tr>
            <td align="center">&nbsp;&nbsp;Decimal&nbsp;&nbsp;</td>
            <td align="center">Hexadecimal</td>
            <td align="center">&nbsp;&nbsp;&nbsp;Octal&nbsp;&nbsp;&nbsp;</td>
            <td align="center">
                &nbsp;&nbsp;&nbsp;&nbsp;Binary&nbsp;&nbsp;&nbsp;&nbsp;
            </td>
            <td align="center">
                &nbsp;&nbsp;&nbsp;&nbsp;HTML&nbsp;&nbsp;&nbsp;&nbsp;
            </td>
        </tr>
        <tr>
            <td align="center"><input class="borderless" type="text" readonly
                id="decimal" maxlength="6" size="6"></td>
            <td align="center"><input class="borderless" type="text" readonly
                id="hexadecimal" maxlength="6" size="6"></td>
            <td align="center"><input class="borderless" type="text" readonly
                id="octal" maxlength="6" size="6"></td>
            <td align="center"><input class="borderless" type="text" readonly
                id="bin" maxlength="8" size="8"></td>
            <td align="center"><input class="borderless" type="text" readonly
                id="hyper" maxlength="6" size="6"></td>
        </tr>
    </table>

    </form>
</body>
</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building the Application
Now that we have reviewed the code, let's build it and try it out. It's very similar to the example in the previous chapter, and because I don't like to overwrite my work, I put the new application in its own directory tree. The directory structure I used is shown in Figure 4-2.
Figure 4-2: Directory structure for Ajax Character Decoder (second version)
This is just a guide so you can see how I built the sample. You can name your directories differently as long as you know how to configure the application server properly.
The web.xml file for the project is presented in Example 4-8.
Example 4-8. web.xml
<!DOCTYPE web-app
    PUBLIC  "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>
    <servlet>
        <servlet-name>AjaxResponseServlet</servlet-name>
        <servlet-class>
            com.AJAXbook.servlet.AjaxResponseServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>AjaxResponseServlet</servlet-name>
        <url-pattern>/response</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>
The build.xml file for the project is shown in Example 4-9.
Example 4-9. build.xml
<?xml version="1.0"?>
<project name="AJAX-CODECONVERTER " default="compile" basedir=".">

    <property environment="env"/>
    <property name="src.dir" value="src"/>
    <property name="test.dir" value="test"/>
    <property name="war.dir" value="war"/>
    <property name="db.dir" value="db"/>
    <property name="class.dir" value="${war.dir}/WEB-INF/classes"/>
    <property name="test.class.dir" value="${test.dir}/classes"/>
    <property name="lib.dir" value="${war.dir}/WEB-INF/lib"/>
    <property name="webapp.dir"
              value="${env.TOMCAT_HOME}/webapps/ajaxcodeconverter-lab2"/>

    <path id="ajax.class.path">
        <fileset dir="${lib.dir}">
            <include name="*.jar"/>
        </fileset>
    </path>

    <target name="testenv">
        <echo message="env.TomcatHome=${env.TOMCAT_HOME}"/>
        <echo message="env.ANT_HOME=${env.ANT_HOME}"/>
    </target>

    <target name="init">
        <mkdir dir="${class.dir}"/>
        <mkdir dir="${test.class.dir}"/>
    </target>

    <target name="compile" depends="init"
            description="Compiles all source code.">
        <javac srcdir="${src.dir}" destdir="${class.dir}" debug="on"
               classpathref="ajax.class.path"/>
    </target>

    <target name="clean" description="Erases contents of classes dir">
        <delete dir="${class.dir}"/>
        <delete dir="${test.class.dir}"/>
    </target>

    <target name="deploy" depends="compile"
            description="Copies the contents of web-app to destination dir">
        <copy todir="${webapp.dir}">
            <fileset dir="${war.dir}"/>
        </copy>
    </target>

</project>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Running the Application on Tomcat
If you are running your application on the Tomcat server, you can use the Tomcat Web Application Manager (accessible through the URL http://localhost:8080/manager/html) to check whether it was deployed. The application manager is shown in Figure 4-3. As you can see in this figure, two versions of our Ajax converter have been deployed successfully and are currently running. The directory in which you installed the application becomes part of the path.
Figure 4-3: Tomcat Web Application Manager
Click the link under Applications to open a browser window that accesses the directory of your application. Then click the "index.html" link to see the application.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Passing Data with JSON
Now that you've seen how to use XML as the data vehicle, we must talk about some of the problems with XML. One major drawback is speed. XML requires two tags per data point, plus extra tags for parent nodes and so on. All this extra data in transmission slows down the data exchange between the client and server. You can easily end up with a long document that contains only a few bytes' worth of data. Constructing the document can also be a rather elaborate process that requires a lot of memory on the server.
Fortunately, there is another way to send data to the client that is easier to parse and more compact. That alternative is JSON (pronounced Jason). JSON objects are typically smaller than the equivalent XML documents, and working with them is more memory-efficient.
The other great benefit of JSON is that you can parse it with JavaScript's eval( ) function. You don't need other libraries, and you don't need to worry as much about cross-browser functionality. As long as your browser has JavaScript enabled and supports the eval( ) function, you will be able to interpret the data.
You may still need to use XML (and now you know how), but if you have the option, there are compelling reasons to use JSON. In most cases, you will be better off with a JSON implementation.
This is our data object represented in JSON:
{"conversion":{
"decimal": "120",
"hexadecimal": "78",
"octal": "170",
"hyper": "&amp;0x78",
"binary": "1111000B"}
}
There are programmatic ways to build the JSON object, but to keep it simple we'll use a StringBuffer again and glue together the strings that will form the conversion object. Example 4-10 illustrates how we build the data object in the servlet.
Example 4-10. AjaxJSONServlet.java
package com.oreilly.ajax.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AjaxResponseServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        // key is the parameter passed in from the JavaScript
        // variable named url (see index.html)
        String key = req.getParameter("key");
        if (key != null) {
            // extract the first character from key
            // as an int, then convert that int to a String
            int keyInt = key.charAt(0);
            // set up the response
            res.setContentType("text/xml");
            res.setHeader("Cache-Control", "no-cache");
            // write out the XML string
            String outString = createStringBufferJSON(keyInt);
            res.getWriter( ).write(outString);
        }
        else {
            // if key comes back as a null, return a question mark
            res.setContentType("text/xml");
            res.setHeader("Cache-Control", "no-cache");
            res.getWriter( ).write("?");
        }
    }
    public String createStringBufferJSON(int keyInt) {
        StringBuffer returnJSON = new StringBuffer("\r\n{\"conversion\":{");
        returnJSON.append("\r\n\"decimal\": \""+
                          Integer.toString(keyInt)+"\",");
        returnJSON.append("\r\n\"hexadecimal\": \""+
                          Integer.toString(keyInt,16)+"\",");
        returnJSON.append("\r\n\"octal\": \""+
                          Integer.toString(keyInt,8)+"\",");
        returnJSON.append("\r\n\"hyper\": \"&0x"+
                          Integer.toString(keyInt,16)+"\",");
        returnJSON.append("\r\n\"binary\": \""+
                          Integer.toString(keyInt,2)+"B\"");
        returnJSON.append("\r\n}}");
        return returnJSON.toString( );
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
Remember that Ajax isn't a technology: it's a group of ideas that, used together, have proven very powerful. When you combine form manipulation with JavaScript, asynchronous callbacks with XMLHTTPRequest, and built-in XML with JSON parsers, you have something revolutionary—even though the individual pieces have been around for a while.
Combine these client-side technologies with Java's established server-side technologies, such as servlets, Struts, and JSF, and you've got a really powerful basis for building a new generation of interactive web applications.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 5: Getting Useful Data
Google Suggest was one of the first Ajax applications: it's actually older than the name Ajax. Google Suggest alters the experience of filling in an HTML form. Normally, you fill in your data, click Submit, and cross your fingers; more than likely, you'll find out that you've requested a username that already exists, made a typo in your area code, or made some other simple error that you have to correct. Google Suggest changes all that: as you type in a field, it continuously shows you possible completions that match entries in the database.
Order-entry applications aren't sexy, but they're everywhere—and Ajax could be one of the best things that's ever happened to them. In the world of web applications, it's all about ease of use and saving time. Google Suggest suggests a way of making the web experience much easier: using Suggest as a model, we can write web applications that tell users immediately when they have requested usernames that are already in use, that fill in a city and state automatically on the basis of a zip code, and that make it simpler to enter names (product names, customer names, etc.) that are already in the database.
That's what we'll do in this chapter, while exploring ways to make a signup page easier to use and manage. We'll start with a Customer Sign-up page, shown in Figure 5-1. This page has two fields that get special treatment: the username field and the zip code field. We'll call these fields suggestion fields. For the username field, we'll notify users immediately if they enter usernames that have already been taken, rather than waiting until the form is submitted to validate this data. We'll also utilize the value entered into the zip code field to autopopulate the city and state fields with the values that correspond to that zip code, saving users some work.
Figure 5-1: The Ajax Customer Sign-up page
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Form Entry with Ajax
Order-entry applications aren't sexy, but they're everywhere—and Ajax could be one of the best things that's ever happened to them. In the world of web applications, it's all about ease of use and saving time. Google Suggest suggests a way of making the web experience much easier: using Suggest as a model, we can write web applications that tell users immediately when they have requested usernames that are already in use, that fill in a city and state automatically on the basis of a zip code, and that make it simpler to enter names (product names, customer names, etc.) that are already in the database.
That's what we'll do in this chapter, while exploring ways to make a signup page easier to use and manage. We'll start with a Customer Sign-up page, shown in Figure 5-1. This page has two fields that get special treatment: the username field and the zip code field. We'll call these fields suggestion fields. For the username field, we'll notify users immediately if they enter usernames that have already been taken, rather than waiting until the form is submitted to validate this data. We'll also utilize the value entered into the zip code field to autopopulate the city and state fields with the values that correspond to that zip code, saving users some work.
Figure 5-1: The Ajax Customer Sign-up page
We'll begin by validating the username to ensure that it does not currently exist in the database. To accomplish this, all we have to do is register the onblur JavaScript control with the username field:
<td>User Name:</td>
<td align="left">
    <input type="text" id="ajax_username" name="ajax_username"
           onblur="validateUsername( );">
</td>
The JavaScript onblur event fires whenever the field loses focus—for example, when the user presses Tab to move the cursor to the next field or clicks anywhere outside of the input field. When
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Suggestion Field
Building the suggestion field is the most fun but also the most complicated part of the next sample application. Our form will look like Figure 5-2.
Figure 5-2: The Ajax Customer Management page
When you type "M," the application finds all the names in the database starting with the letter M; in this case, there are three. If you type "Ma," the selection displays only "Mary." Hitting Return then calls up the record for Mary, as shown in Figure 5-3.
Figure 5-3: Ajax suggestion field lookup for one record
This application takes a few shortcuts. The first is the lookup: it doesn't go to the database and look up the matching set of names for every character that's typed. We could implement it that way, but it wouldn't improve the application and it would require more requests to the database, which has the potential for creating efficiency problems.
Even though Ajax applications are more responsive than traditional web applications, it's easy to imagine users cursing an application that makes a round trip to the server with every character that is typed. Instead, this application loads all of the usernames at the beginning. This approach wouldn't be ideal if there were hundreds or thousands of users, but if the application is only pulling a small amount of data, this simpler, single-query design is more efficient. For a bigger database, you could trigger the query with onkeyup( ) and get the result set for the letters in the suggestion field.
The HTML code for the form is presented in Example 5-4.
Example 5-4. The Ajax Customer Management code
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <LINK REL="stylesheet" TYPE="text/css" HREF="oreillyajax.css">
    <title>Ajax on Java Customer Management Page</title>
    <script language="JavaScript" src="oreillySuggest.js"></script>
    <script language="JavaScript">
        window.onload = function ( ) {
            init("ajax_username");
        }
    </script>
</head>
<body >
    <h1>AJAX CUSTOMER MANAGEMENT</h1>

    <form name="form1" action="/ch05-suggest" method="get">

    <label for="ajax_username">Username:</label>
    <input  class="cm_label" type="text" id="ajax_username" autocomplete="off">
    <br /><br />

    <label class="cm_label" for="password">Password:</label>
    <input class="cm_input" type="text" id="password" name="password"><br /><br />

    <label class="cm_label" for="confirmpassword">Name:</label>
    <input class="cm_input" type="text" id="name" name="name"><br /><br />

    <label class="cm_label" for="email">Email:</label>
    <input class="cm_input" type="text" id="email" name="email"><br /><br />

    <label class="zlabel" for="address">Address:</label>
    <input class="cm_input" type="text" id="address" name="address"><br /><br />

    <label class="cm_label" for="zipcode">Zip Code:</label>
    <input class="cm_input" type="text" id="zipcode" name="zipcode"><br /><br />

    <label class="cm_label" for="state">State:</label>
    <input class="cm_input" type="text"  id="state" name="state"><br /><br />

    <label class="cm_label" for="city">City:</label>
    <input class="cm_input" type="text" id="city" name="city"><br /><br />

    </form>

    <a href="index.html">Sign up</a>

</body>
</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 6: Ajax Libraries and Toolkits
When the term Ajax was first coined, many developers were surprised by the power of JavaScript. They had been using JavaScript for years but hadn't figured out that they could use it to create web applications with functionality that rivaled that of native desktop applications. That "eureka" moment led to hype, which in turn created the energy that has allowed Ajax to mature. When Ajax was getting started, developers had to build their applications without any help (as we have done in the past few chapters): they had to write all the JavaScript, parse the XML or JSON by hand, and create servlets to handle the asynchronous interaction with the client. That's no longer the case. The number of frameworks that exist now to simplify the task of creating Ajax applications is solid proof that Ajax is more than just hype: it's a valid, thriving architecture.
All I can say is, "Cool, bring it on!" As web developers, we have waited a long time to bring this functionality to our web applications. Swing developers, beware: Ajax levels the playing field.
Up until now, we've been building our Ajax applications with XMLHttpRequest. We have used XMLHttpRequest to send requests to the server, and we have set up callback methods to intercept the responses coming back from the server.
We can make that portion of our code more resilient by using libraries. An Ajax toolkit or library can help us build the request object and set up the callback function. Using a toolkit also eliminates one of the ugliest parts of our JavaScript code: the separate code we have to write to handle Internet Explorer and the other browsers.
This chapter will introduce the following Ajax libraries:
  • The Dojo Toolkit
  • The Rico Toolkit
  • The DWR Toolkit
  • Scriptaculous
  • Prototype
We'll start our look at Ajax frameworks with the Dojo Toolkit. Dojo is an open source DHTML toolkit written in JavaScript. It includes many utilities that go beyond Ajax. The libraries that we are most interested in include:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using the Dojo Toolkit
We'll start our look at Ajax frameworks with the Dojo Toolkit. Dojo is an open source DHTML toolkit written in JavaScript. It includes many utilities that go beyond Ajax. The libraries that we are most interested in include:
dojo.io
Platform-independent input/output APIs
dojo.rpc
RPC, the Dojo way
dojo.json
JSON, the Dojo way
Although we are only going to use the dojo.io library for this example, you should look at the Dojo manual (http://manual.dojotoolkit.org) for information on dojo.rpc and dojo.json.
The other libraries that Dojo contains are:
dojo.lang
Utility routines to make JavaScript easier to use
dojo.string
String manipulation routines
dojo.dom
DOM manipulation routines