By Steven Douglas Olson
Book Price: $29.99 USD
£20.99 GBP
PDF Price: $23.99
Cover | Table of Contents | Colophon
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.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./<tomcat install directory>/bin/startup.sh
\<tomcat install directory>\bin\startup.bat
shutdown.sh (Linux) or shutdown.bat (Windows) from your install directory.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 http://ant.apache.org and grab the latest version.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.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
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.
<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>
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.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.
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( );
}
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.
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.
/*
* 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("?");
}
}
}
http://ant.apache.org.TOMCAT_HOME to the directory where you installed Tomcat. Refer back to Chapter 1 for setup details.
<?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>
http://localhost:8080/ajax-decimal/index.html.
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.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.
<converted-values>
<decimal>97</decimal>
<hexadecimal>0x61</hexadecimal>
<octal>0141</octal>
<hyper>&0x61;</hyper>
<binary>1100001B</binary>
</converted-values>
StringBuffer to wrap the data with XML tags. Later, we'll look at other ways to create the XML document.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.
/*
* 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>&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("?");
}
}
}
<!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:
<input class="borderless" type="text" readonly id="keypressed"
maxlength="1" size="1">
</td>
</tr>
<tr>
<td align="center"> Decimal </td>
<td align="center">Hexadecimal</td>
<td align="center"> Octal </td>
<td align="center">
Binary
</td>
<td align="center">
HTML
</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>
<!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>
<?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>
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.
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.
{"conversion":{
"decimal": "120",
"hexadecimal": "78",
"octal": "170",
"hyper": "&0x78",
"binary": "1111000B"}
}
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.
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( );
}
}
XMLHTTPRequest, and built-in XML with JSON parsers, you have something revolutionary—even though the individual pieces have been around for a while.
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>
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
onkeyup( ) and get the result set for the letters in the suggestion field.
<!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>
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.dojo.io
dojo.rpc
dojo.json
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.dojo.lang
dojo.string
dojo.dom