Here is the zip code example. This web site also explains how to do it.
Ajax = Asynchronous javascript and XML
Ajax is not a standard, it is a combination of HTML, javascript, XML, and HTML dom.
DHTML - Dynamic HTML - not a standard, more of a marketing term. Includes HTML, stylesheets, javascript, etc.
Ajax is based on the XMLHttpRequest object - a javascript object
In a normal web application, users fill out a form, click submit, and the data from the form is sent to the server, the server processes the data and sends back a complete new page. (usually HTML).
Ajax puts Javascript and the XMLHttpRequest between your web object and the server. Data from the form is sent to some javascript code, which sends a request to the server. This is done asynchronously (the first A in ajax), so the user can continue entering data, scrolling around etc.
The server sends data back to the javascript code, which can update the HTML DOM
Getting the Request Object
In a browser other than IE, this should work.
<<script language="javascript" type="text/javascript"> var xmlHttp = new XMLHttpRequest(); </script>Microsoft has two different versions of javascript so you need code like this.
var xmlhttp = false;
try {
xmlhttp = new ActiveXObject("Msxmlw.XMLHTTP");
}
catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e2) {
xmlhttp = false;
}
}
This code tries to create the object using one version of MSXML, if
that fails, it tries the other version. If neither works, you have
to do something different
Note, lots of people turn off javascript for security reasons, In that case, this does not work. Also, this will not work in really old browsers.
Here are some methods of an XMLHttpRequest
open(method,URL[, asyncFlag[,userName [, password]]]) which opens the connection. Method is either GET or POST, URL is the name of the document or the query string. If the third argument is true then the script runs asynchronously (the default), that is, the code continues running after the call and does not wait for a reply. If the third argument is false, then the running script is halted until a reply is received. (Note: open is a poor name for this because no connection is opened).
send(content) This actually sends the request. If the method is GET, then the argument is null; if the method is POST, then the argument is the data.
There are some member variables.
onreadystatechange = callbackfunction() If the call is made asynchronously, then the callbackfunction is triggered when the reply is received.
readyState a numeric value. This should be 4 if the server replied successfully.
status The status code in the reply line of the response from the server. This will be 200 if successful, 404 if the document was not found, etc.
responseTextIf the reply is plaintext, this will contain the string
responseXML If the reply is an xml document, this will contain the document.
Here are the steps.
Here is a trivial example which pops up an alert box containing whatever text is in test.txt
<html>
<head>
<title>AJAX DEMO</title>
<script type="text/javascript" language="javascript">
var http_request = false;
function makeRequest(url) {
if (window.XMLHttpRequest) { // Mozilla, Opera, Safari,...
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
http_request.onreadystatechange = alertContents;
http_request.open('GET', url, true);
http_request.send(null);
}
function alertContents() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
alert(http_request.responseText);
} else {
alert('There was a problem with the request.');
}
}
}
</script>
</head>
<body>
<span
style="cursor: pointer; text-decoration: underline"
onclick="makeRequest('test.txt')">
Make a request
</span>
</body>
</html>
When you summon the function, a call is made to the url test.txt, and the
content of this file is returned to the browser. This is done asynchronously,
so the user can continue to do other things while waiting for the return.
(In the more typical synchronous call, the pointer changes to a little hourglass
and the user cannot do anything in that window until the data is received).
Note that the XMLHttpRequest can only make a request to the same domain that provided the original file.
When the file has been returned, the callback function will be triggered. The program can get the text with responseText member.
Notice that the callback function checks two values, the ready state and the status. The status is the familiar http status value (200=OK, 404=File Not Found etc). There are four values of ready state.
This was a trivial example, because all it did was display an alert box, and it received plaintext from the server. Here is an example of a program that requests an xml file from the server, parses the data from the file, and uses it to update the data displayed in a table.
Before looking at the code, run it to see what it does.
<html>
<head>
<title>AJAX STOCK DEMO</title>
<script type="text/javascript" language="javascript">
var http_request = false;
function makerequest() {
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
http_request.onreadystatechange = updateStocks;
http_request.open('GET','PriceUpdate.xml', true);
http_request.send(null);
}
function updateStocks() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
var xmldoc = http_request.responseXML;
var nodes = xmldoc.getElementsByTagName('Price');
var len = nodes.length;
for (i=0;i < len;i++) {
var x = document.getElementById("stocktable").rows[i+1].cells;
x[1].innerHTML = nodes[i].firstChild.nodeValue;
}
}
else {
alert('There was a problem with the request.');
}
}
}
</script>
</head>
<body>
<h3>Stock Values</h3>
<p>
<table id="stocktable">
<th>Stock</th><th>price</th>
<tr><td>IBM</td><td id="ibmrpice">47</td></tr>
<tr><td>Microsoft</td><td id="microsoftprice">123</td></tr>
<tr><td>Google</td><td id="googleprice">300</td></tr>
</table>
<p>
<form>
<input type="button" onclick="makerequest()" value="Update prices">
</form>
</body>
</html>
Here is the file PriceUpdate.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<PriceUpdate>
<Stock>
<Name>IBM</Name>
<Price>56</Price>
</Stock>
<Stock>
<Name>Microsoft</Name>
<Price>156</Price>
</Stock>
<Stock>
<Name>Google</Name>
<Price>456</Price>
</Stock>
</PriceUpdate>
This example does two things differently. It retrieves an xml file, not a text file. The member responseXML is used to retrieve this. Rather than returning text, it returns a parsed xml file in the DOM format, so you can use all of the DOM functions to access the contents.
Second, it uses the data to update the html dom, that is, it modifies the contents of the html.
Passing data from the browser to the server
Both of these examples have requested hard coded files (test.txt in the first case, PriceUpdate.xml in the second case). It is common to pass some dynamic data to the server. This can be done using either GET or POST; the former is more common. This is done by appending the query onto the url using urlencoding.
Here is an implementation of the zip code example. Note how the argument is passed.
<html>
<head>
<title>Zip Code Demo</title>
<script language="javascript" type="text/javascript">
var http_request;
var url="ajax3.php?zip="
function updateCityState() {
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
http_request.onreadystatechange = alertContents;
var zipValue = document.getElementById("zip").value;
http_request.open("GET",url+escape(zipValue), true);
http_request.send(null);
}
function alertContents() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
results = http_request.responseText.split(",");
document.getElementById('city').value = results[0];
document.getElementById('state').value = results[1];
}
else {
alert('There was a problem with the request.');
}
}
}
</script>
</head>
<body>
<p>
<h3>Zip Code Demo</h3>
<center>
Using Ajax<br>
From<a href=http://www.webpasties.com/xmlHttpRequest/index.html>
The Web Pasties Ajax tutorial</a><br>
</center>
<p>
<form method="GET">
<p>
ZIP code:
<input type="text" size="5" name="zip" id="zip" onblur="updateCityState();" />
</p>
City:
<input type="text" name="city" id="city" />
State:
<input type="text" size="2" name="state" id="state" />
</form>
</body>
</html>
The function escape, used in the call to open, converts characters to url encoding. Although it is not needed for this example, it is a good idea to call this when passing data as a urlencoded string.
Using the POST Method
Most ajax applications use the GET method, as shown in the above example. If you want to use the POST method, you have to make these changes:
Ajax is used in sites like gmail or Flickr or google maps. Content is updated dynamically using data downloaded from the server but without having to redraw the entire page. This is a good tool for name autocompletions or suggestions.
Required Reading
Go through the W3schools AJAX tutorial
Also read the web pasties page
IBM has an excellent four part article on Ajax. It is not required reading, but students who are interested in learning more Ajax should read this.
This completes our discussion of client side programming. What is on the server side.
Dynamic Content - started with cgi
Then came servlets - why are servlets better than cgi?
But you still have to generate the entire html from within your program
Other similar technologies include Microsoft ASP, BEA weblogic, Cold Fusion, IBM WebSphere, Sun's Java Web Server, Allaire's JRun,
More recently, server scripting languages like PHP and Ruby have become popular, and Perl has been used as a cgi server scripting language for years.
Tomcat
Apache Jakarta Tomcat is a servlet container. You should download it from http://tomcat.apache.org and install it on your laptop.
You need jdk1.4 or higher (latest is 1.5) installed.
To test your installation, point your browser to http://localhost:8080 and you should see the tomcat home page.
CATALINA_HOME refers to the jakarta directory
The tomcat directory has a number of subdirectories.
Servlets
Servlets are java programs running inside a web server. They are accessed thru a URL and typically return html.
Here is a the structure of a basic servlet to handle get requests
/* servlet skeleton compile with
-classpath CATALINA_HOME\common\lib\servlet-api.jar */
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class SomeServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
String s = request.getParamater(pName);
PrintWriter out = response.getWriter();
// Use ``out'' to send content to browser
}
}
Here is the on-line help page for the HttpServlet class
An httpServeletRequest has a method getParameter which can be used to get the value of a parameter sent by the client. Here is the on-line help for an HttpServletRequest
Here is a full java program to convert dollars to euros, CurrencyConverter.java
/* CurrencyConverter.java: A servlet to convert dollars to euros */
/* compile with -classpath <CATALINA_HOME>\common\lib\servlet-api.jar */
import java.io.*;
import java.util.*;
import java.text.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class CurrencyConverter extends HttpServlet {
private static final double EXCHANGE_RATE = 0.79;
public void doGet(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<html>");
out.println("<head><title>Currency Conversion</title></head>");
out.println("<body>");
String amount = req.getParameter("amount");
try {
NumberFormat nf = NumberFormat.getInstance();
double Value = nf.parse(amount).doubleValue();
Value *= EXCHANGE_RATE;
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
out.println("<big>" + "$" +
amount + " = €" +
nf.format(Value) + "</BIG>");
}
catch (ParseException e) {
out.println("Bad number format");
}
out.println("</body></html>");
}
}
Here is the html front end for it, CurrencyConverter.html.
<html>
<head>
<title>Currency Converter</title>
</head>
<body>
<form method=GET action="servlet/CurrencyConverter">
<h3>Simple Currency Converter</h3>
<p>Use this form to convert US dollars to Euros (€)
</p>
Type the amount to be converted in the box
<input type=text name="amount">
<input type=submit>
</form>
</body>
</html>
To deploy this
<web-app>
....
<servlet>
<servlet-name>CurrencyConverter</servlet-name>
<servlet-class>CurrencyConverter</servlet-class>
</servlet>
...
<servlet-mapping>
<servlet-name>CurrencyConverter</servlet-name>
<url-pattern>/servlet/CurrencyConverter</url-pattern>
</servlet-mapping>
...