This article is more than 1 year old
Introduction to Developing Web Applications with AJAX - Part 2
A better way of filling out web forms
Tutorial Suppose you fill out a form that requires a unique field value, for example a userid in a registration form. Ordinarily, you would specify a userid value and the other field values and submit the form with the Submit button. If the userid is not already taken you would be able to register, but if the userid is taken you would get a message that the user id value is invalid and you would have to fill out and resubmit the entire form.
With the AJAX web technique the userid value may be validated at the time the value is specified in the input form, thus avoiding any need to resubmit the form.
In the previous AJAX tutorial, we introduced the AJAX technology and performed the preliminary setup for a sample AJAX application. Now, we shall run the AJAX application we configured in the previous article.
The example AJAX application validates data input in an HTML form. The input form requires a unique CatalogId to create a catalogue entry, so the input CatalogId in the form is validated against the database content to see if it is already specified.
Note that data added to the HTML form are sent to the server as the data is added (not when the form is completed) and an HTTP servlet “immediately” returns an XML response that contains information about the validity of the input data.
In the client application, the XMLHttpRequest
response from the server is processed and if the instructions indicate that the data input is valid, a message “Catalog Id is Valid” is displayed. An XMLHttpRequest
is sent to the server and a response received with each modification in the input field.
The procedure to send an XMLHttpRequest
request involves the following procedure:
- Invoke a JavaScript function from an HTML event.
- Create an
XMLHttpRequest
object in the JavaScript function. - Open an
XMLHttpRequest
request, which specifies the URL and the HTTP method. - Register a callback event handler that gets invoked when the request is complete.
- Send an
XMLHttpRequest
request asynchronously. - Retrieve the XML response and modify HTML page.
To initiate an XMLHttpRequest
, register a JavaScript function with an event generated from the HTML form’s input field CatalogId, which is required to be validated. In the example application, a JavaScript function, validateCatalogId()
is invoked with onkeyup
event as listed here:
<form name="validationForm" action="validateForm" method="post"> <table> <tr><td>Catalog Id:</td><td><input type="text" size="20" id="catalogId" name="catalogId" autocomplete="off" onkeyup="validateCatalogId()"></td> <td><div id="validationMessage"></div></td> </tr> ….. …. </table></form>
In the JavaScript function validateCatalogId()
, we need to create a new XMLHttpRequest
object. If a browser supports the XMLHttpRequest
object as an ActiveX object (as in IE 6), the procedure to create an XMLHttpRequest
object is different to when the XMLHttpRequest
object is a window object property (as it is in IE 7 and Netscape).
IE 6 supports the XMLHttpRequest
object as an ActiveX object as shown in the following listing:
<script type="text/javascript"> function validateCatalogId(){ var xmlHttpRequest=init(); function init(){ if (window.XMLHttpRequest) { return new XMLHttpRequest(); } else if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); } } </script>
Next, we need to construct the URL to which the XMLHttpRequest
will be sent. In the example application, we shall invoke a servlet, FormServlet
. The FormServlet
is mapped to servlet URL validateForm
as shown in web.xml in the Resources zip file.
Therefore, specify the URL as validateForm?catalogId=encodeURIComponent(catalogId.value)
. Parameter catalogId specifies the value of CatalogId input in the HTML form. The encodeURIComponent(string)
method is used to encode the CatalogId value. The HTTP method specified is GET
, because form data is encoded into the URL as shown in following listing:
var catalogId=document.getElementById("catalogId"); xmlHttpRequest.open("GET", "validateForm?catalogId="+ encodeURIComponent(catalogId.value), true);
We need to register a callback event handler with the XMLHttpRequest
object using onreadystatechange
property. In the example application, the callback method is JavaScript function processRequest
as shown in the following listing:
xmlHttpRequest.onreadystatechange=processRequest;
We need to send a HTTP request using the send()
method (as the HTTP method is GET
, data sent with the send
method is set to null) as shown in following listing:
xmlHttpRequest.send(null);
As the callback event handler is processRequest
, the processRequest
function gets invoked when the value of the readyState
property changes. In the processRequest
function, the readyState
property value is retrieved.
If the request has loaded completely, corresponding to readyState
value 4, and HTTP status is “OK”, we invoke a JavaScript function to process the response from the server as shown below:
function processRequest(){ if(xmlHttpRequest.readyState==4){ if(xmlHttpRequest.status==200){ processResponse(); } } }
Next, we shall discuss the server side processing of the XMLHttpRequest
request sent. The XMLHttpRequest
is sent to url validateForm
, which invokes the FormServlet servlet. As the XMLHttpRequest
method is GET
, the doGet()
method of the servlet gets invoked. In the doGet
method, retrieve the value of the catalogId parameter as shown in following listing.
String catalogId = request.getParameter("catalogId");
We shall obtain data from the database to check if a CatalogId value is already specified in the database. We need to create a Connection object with the database and, using the CatalogId value specified in the input form, create an SQL query to retrieve the data from the database. Run the SQL query using executeQuery(String)
method to obtain a ResultSet
object. We need to set the content type of the HttpServletResponse
to text/xml, and the cache-control header to no-cache as shown in following listing.
response.setContentType("text/xml"); response.setHeader("Cache-Control", "no-cache");
The FormServlet servlet sends a response in the form of an XML string. Therefore, we construct an XML DOM object that contains instructions about the validity of the CatalogId field value.
An empty ResultSet object implies that the CatalogId field value is not defined in the database table Catalog, thus, the CatalogId field value is valid.
A ResultSet object that contains data implies that the CatalogId value is already defined in the database, thus, the CatalogId field value is not valid.
For a non-valid CatalogId, construct an XML string that includes the different field values for the CatalogId. The XML string is required to have a root element, which is catalog in the example application. In the example application, the XML string includes a <valid></valid> element that specifies the validity of the CatalogId field value a shown below (the variable rs represents a ResultSet).
if (rs.next()) { out.println(“<catalog>” + “<valid>false</valid>” + “<journal>” + rs.getString(2) + “</journal>” + “<publisher>” + rs.getString(3) + “</publisher>” + “<edition>” + rs.getString(4) + “</edition>” + “<title>” + rs.getString(5) + “</title>” + “<author>” + rs.getString(6) + “</author>” + “</catalog>”); } else { out.println(“<valid>true</valid>”); }
If the CatalogId field value is not defined in the database, the input form may be posted to the server. In the servlet, create a JDBC connection to the MySQL database and add a catalog entry with the INSERT
statement.
The FormServlet is available in the Resources zip file.
In the processRequest()
JavaScript function, if the HTTP request has loaded completely, which corresponds to readyState property value 4, and the HTTP status is ”OK”, which corresponds to status property value 200, the processResponse()
JavaScript function gets invoked. In the processResponse()
function, we need to obtain the value of the responseXML
property. This contains the XML string that was set in the doGet()
method of FormServlet.
var xmlMessage=xmlHttpRequest.responseXML;
The responseXML
property contains instructions in XML form about the validity of the CatalogId value specified in the input form. We need to obtain the value of the <valid/> element using getElementsByTagName(string)
method as shown in following listing.
var valid=xmlMessage.getElementsByTagName("valid")[0].firstChild.nodeValue;
If the <valid/> element is set to true, set the HTML validationMessage div
to “Catalog Id is Valid”, and enable the submit button in the input form, as shown below:
if(valid=="true"){ var validationMessage=document.getElementById("validationMessage"); validationMessage.innerHTML = "Catalog Id is Valid"; document.getElementById("submitForm").disabled = false; }
If the <valid/> element value is set to false, set the HTML of validationMessage div
in CatalogID field row to "Catalog Id is not Valid", and disable the submit button.
The values of the other input fields may also be set as shown for the journal
field below. Setting the values of the other fields corresponding to a CatalogId is an example of auto-completion with AJAX.
if(valid=="false"){ var validationMessage=document.getElementById("validationMessage"); validationMessage.innerHTML = "Catalog Id is not Valid"; document.getElementById("submitForm").disabled = true; var journal=xmlMessage.getElementsByTagName("journal")[0].firstChild.nodeValue; var journalElement=document.getElementById("journal"); journalElement.value = journal; }
The inputForm.jsp
JSP is available in the Resources zip file.
We need to deploy the AJAX web application to a JBoss application server and run the application. When the build.xml script is run in Eclipse, an ajax.war web application gets deployed in JBoss application server. The build.xml file was run in Eclipse in the Creating an Eclipse Project section in the first part of this AJAX tutorial.
So, the ajax.war web application is copied to the deploy directory of the default web server and we then need to start the JBoss application server using the run batch file in the bin directory. The ajax.war web application gets deployed in the JBoss application server. Subsequently, we need to run the inputForm.jsp JSP in a browser using URL http://localhost:8080/ajax/inputForm.jsp.
The inputForm.jsp gets displayed as shown in Figure 1.
To validate a CatalogId value, specify a CatalogId field value. An HTTP request gets sent to the server and the XML response is returned to the client application. If CatalogId field value is valid, a message “Catalog Id is Valid” gets displayed, as shown in Figure 2.
If a CatalogId field value is specified that is not valid, a message “Catalog Id is not Valid” gets displayed and the submit button gets disabled as shown in Figure 3. Also, the field values for the CatalogId get specified.
To create a catalog entry, specify a valid CatalogId and click on the Create Catalog button as shown in Figure 4.
A catalogue entry gets created in the database. If a previously specified CatalogId value is re-specified, the message “Catalog Id is not Valid” gets displayed.
Congratulations! You have just developed an AJAX application.