Developer: J2EE
   DOWNLOAD
 Oracle JDeveloper 10g
 Oracle Database XE
   TAGS
ajax, java, jdeveloper, All

Validating Forms with Ajax


by Deepak Vohra

Learn how to build a dynamic, form-based Web application using Ajax.

Published May 2006

Asynchronous JavaScript and XML (Ajax) is a Web development technique that combines JavaScript, Document Object Model (DOM), and XMLHttpRequest technologies to provide dynamic interaction between a client and server.

As an example, suppose a user fills out a form to add data to a database table. Without Ajax, the validity of data in the form is not checked until the form is submitted. With Ajax, the data added to the form can be dynamically validated as the data is added to form fields using business logic in a server application. Thus, a complete form does not have to be posted to the server to check if data in the form is valid.

In this article, you'll learn how to create a Web application using Ajax in Oracle JDeveloper 10g (10.1.3). But first, let's cover some background.

Overview of XMLHttpRequest

As a J2EE developer, you're probably familiar with DOM and JavaScript, but not necessarily so with XMLHttpRequest. In Ajax, the XMLHttpRequest object is what provides the asynchronous communication between Web applications and underlying servers and business services. With the XMLHttpRequest object, clients may retrieve and submit XML data directly to the Web server without reloading the page. XML data is converted to renderable HTML on the client side using DOM and Extensible Stylesheet Transformations (XSLT).

Originally introduced by Microsoft as an ActiveX component, XMLHttpRequest is now supported by most modern browsers. However, prior to April 2006, XMLHttpRequest was implemented differently across browsers. For example, Internet Explorer 6 implements XMLHttpRequest as an ActiveX object. An instance of XMLHttpRequest object is created in IE 6 with:

var req = new ActiveXObject("Microsoft.XMLHTTP");

With Internet Explorer 7, XMLHttpRequest is available as a window object property. An instance of XMLHttpRequest object in IE7 and later is created with:

var req = new XMLHttpRequest();

In April 2006, a W3C Working draft of the XMLHttpRequest object was introduced. As XMLHttpRequest object becomes a formal W3C standard, the implementation of the XMLHttpRequest object is likely to become even more standardized. The XMLHttpRequest object has various properties and methods to provide HTTP client functionality. The XMLHttpRequest properties are discussed in Table 1.

Table 1. XMLHttpRequest Properties

Property

Description

onreadystatechange

Sets the event handler for asynchronous requests

readyState

Retrieves the current state of a request. The different values of readyState are:

0-XMLHttpRequest object has been created, but not initialized. The open() method has not been called.

1-The object has been created and initialized, but the send() method has not been called.

2-The send() method has been called, but the status and headers are not available.

3-Some data has been received, but invoking the responseXML produces null, because response headers and status are not completely available. Invoking responseText produces partial data.

4-All the data has been received.

responseText

Retrieves the response from server as text.

responseXML

Retrieves the response from server as XML DOM object.

responseBody

Retrieves the response body. responseBody property is defined in IE7 and later window object, but not in W3C XMLHttpRequest specification.

status

Retrieves the HTTP status code of the request. Examples of status code are 404 for “Not Found” and 200 for “OK”.

statusText

Retrieves the text of the HTTP status.

XMLHttpRequest object methods are discussed in Table 2.

Table 2. XMLHttpRequest Methods

Method

Description

Abort()

Cancels the current HTTP request.

getAllResponseHeaders()

Returns all the response headers. Returns null if readyState is other than 3 or 4.

getResponseHeader(string header)

Returns a specified response header. Returns null if readyState is other than 3 or 4.

open(string method, string url, boolean asynch, string username, string password)

Opens a HTTP request, but does not send the request. Invoking the open() method sets the readyState property to 1. responseText, responseXML, status, and statusText properties are set to their initial values. The HTTP method and server URL (relative or absolute) are required to be specified in the open() method. Boolean value for asynch specifies if HTTP request is asynchronous; Boolean value parameter is not required to be specified and default value is true. Username and password are specified for server side authentication and are optional.

send(data)

Sends a HTTP request to the server and receives a response. The data sent with the send() method may be string, an array of unsigned bytes, or an XML DOM object. The data sent with send() method is optional and may be null. The send() method is synchronous or asynchronous based on the value of the asynch argument in the open() method. If synchronous, the method does not return until the entire response is received. If asynchronous, the method returns immediately. The readyState property is set to 2 after invoking the send() method. The readyState property is set to 4 when the request has completed loading.

setRequestHeader(string headerName, string headerValue)

Sets HTTP headers to the request

Preliminary Setup

First, you'll need to download and install JDeveloper 10.1.3. Then, create a JDeveloper application and project with File>New>General> Application. In the project, add a JSP file, input.jsp, with File>New>Web Tier>JSP>JSP for creating a Ajax Web application. In the JSP File frame, specify a file name and click on Next. In the Error Page Options frame select default settings and click on Next. In Tag libraries frame, select default settings and click on Next. In HTML Options frame, select default settings and click on Next. The JSP provides the client side of the Ajax application. Similarly, add JSPs, catalog.jsp and error.jsp for redirecting the client application based on if the Web application generates an error. For server side processing, add a HTTP Servlet with File>New>Web Tier> Servlets>HTTP Servlet.

Figure 1
Figure 1: Creating a Servlet

In Mapping Information frame, specify a Servlet name, FormValidationServlet, specify a servlet mapping URL (validateForm for example), and click on Next.

Figure 2
Figure 2: Specifying Servlet Mapping

In Servlet Parameters frame, specify any servlet parameters, if required, and click on Finish. The resulting Ajax application structure is shown in Figure 3.

Figure 3
Figure 3: Ajax Application Directory Structure

Next, add some libraries to the Ajax project with Tools>Project Properties>Libraries>Add Library. Add libraries JSP Runtime, Servlet Runtime, and Oracle JDBC.

Figure 4
Figure 4: Adding Project Libraries

The Ajax application in this article retrieves data and updates data in a Oracle Database 10g Express Edition (Oracle's free developer edition) table. Download and nstall Oracle Database XE, including the sample schemas, and create a database instance. Create a database table, Catalog, with the SQL script below.

CREATE TABLE OE.Catalog(CatalogId VARCHAR(25) PRIMARY KEY, Journal VARCHAR(25),
Publisher Varchar(25), Edition VARCHAR(25), Title Varchar(45), Author
Varchar(25));


INSERT INTO OE.Catalog VALUES('catalog1', 'Oracle Magazine',  
'Oracle Publishing', 'Nov-Dec 2004', 'Database Resource Manager', 
'Kimberly Floss');


INSERT INTO OE.Catalog VALUES('catalog2', 'Oracle Magazine',   
'Oracle Publishing', 'Nov-Dec 2004', 'From ADF UIX to JSF', 
'Jonas Jacobi');


INSERT INTO OE.Catalog VALUES('catalog3', 'Oracle Magazine',   
'Oracle Publishing', 'March-April 2005', 'Starting with Oracle ADF ', 
'Steve Muench');

Next, define a JDBC Connection with the Oracle database in the Connections-Navigator. To create a JDBC connection, right-click on the Database node in Connections-Navigator and select New Database Connection. The Create Database Connection wizard gets started. In the Type frame, specify a connection name, and select the default Connection Type, Oracle (JDBC). Click on Next. In the Authentication frame, specify Username and Password, and click on Next. In the Connection frame, select the thin Driver, specify Host Name as localhost, and JDBC Port as 1521. Specify the SID and click on Next. In the Test frame, click on Test Connection button. A JDBC connection gets established and a node for the connection gets added to Connections-Navigator.

A DBConnection1 in Connections-Navigator is available as datasource with resource name jdbc/DBConnection1DS. To the web.xml configuration file, add a <resource-def/> element.

<resource-ref>
  <res-ref-name>jdbc/DBConnection1DS</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

Sending a Request

In this article, you will create an Ajax application that validates data input in a HTML form. Data added to the HTML form is sent asynchronously to the server. On the server side, a HTTP servlet processes the input from the form and returns a response as an XML DOM object. In the client application, the response from the server is processed and a message is output about the validity of the data added. In the example application, an input form is used to create a catalog entry that is sent to the server and updated in the database in a server side Servlet.

You will probably be interested in ascertaining if a catalog Id specified in the input form is not already taken in the catalog database. As the client specifies the catalog Id field, a XMLHttpRequest is sent to the server with each modification in the input field. A response from the server in the form of an XML DOM object provides information to the client about the validity of the catalog Id value specified. Without Ajax, the complete form would have to be posted to the server and the client JSP reloaded after a response is received from the server. The procedure to send a XMLHttpRequest request is as follows.

  1. Create a XMLHttpRequest object.
  2. Open a XMLHttpRequest request.
  3. Register a callback method to be invoked when the request is complete.
  4. Send a XMLHttpRequest request.
  5. Process the XML response and set HTML page content.

A XMLHttpRequest is initiated from an HTML form that has input fields for creating a catalog entry. The XMLHttpRequest is initiated from the Catalog Id field, which is required to be validated. A JavaScript function, validateCatalogId(), is invoked with onkeyup event.

<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 JavaScript function validateCatalogId(), create a new XMLHttpRequest object.

<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, construct the URL to which the XMLHttpRequest is to be sent. As the FormValidationServlet is mapped to servlet URL validateForm, the URL is validateForm with a catalogId parameter. The catalogId value is encoded into the url with the encodeURIComponent(string) JavaScript function.

var catalogId=document.getElementById("catalogId");
xmlHttpRequest.open("GET", "validateForm?catalogId="+ 
encodeURIComponent(catalogId.value), true);

Register a callback event handler with the XMLHttpRequest object using the onreadystatechange property. In the example application, the callback method is the processRequest() JavaScript function.

xmlHttpRequest.onreadystatechange=processRequest;

Send the XMLHttpRequest to the server using the send(data) method. As the HTTP method is GET, data sent with the send method is set to null.

xmlHttpRequest.send(null);

As the callback method is processRequest, the processRequest function is invoked when value of the readyState property changes. In the processRequest function, the readyState property value is retrieved to determine if request has loaded completely and if HTTP status is “OK”. A readyState value of 4 indicates that the request has loaded completely. A status value of 200 indicates that the HTTP status is “OK”.

function processRequest(){

if(xmlHttpRequest.readyState==4){
   if(xmlHttpRequest.status==200){
    
      processResponse();

    }
  }
}

Processing a Request on the Server side

The XMLHttpRequest is sent to url validateForm?catalogId=<catalogId>.

Variable <catalogId> is the value of parameter catalogId. As the FormValidationServlet is mapped to url validateForm, the servlet is invoked. 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.

String catalogId = request.getParameter("catalogId");

To obtain data from the database, create a JDBC connection from a datasource. Create a DataSource object using an InitialContext object lookup and from the DataSource object obtain a Connection object.

  InitialContext initialContext = new InitialContext();
  javax.sql.DataSource ds = (javax.sql.DataSource)
  initialContext.lookup("java:comp/env/jdbc/DBConnection1DS");
  java.sql.Connection conn = ds.getConnection();

Create a Statement object, specify a SQL query to retrieve data from the database for the catalogId value specified in the input form, and obtain a ResultSet object with the executeQuery(String query) method of the Statement object.

Statement stmt = conn.createStatement();
            String query = "SELECT * from OE.Catalog WHERE catalogId=" + "'" +
                catalogId + "'";
ResultSet rs = stmt.executeQuery(query);

Set the content type of the HttpServletResponse to text/xml, and set the cache-control header to no-cache.

response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");

The response from the servlet is in the form of a XML DOM object. Construct an XML DOM object that contains instructions about the validity of the catalogId field value. If the ResultSet object is empty, the catalogId field value is not defined in the database table Catalog, therefore the catalogId field value is valid. If the ResultSet object has data, the catalogId value is already defined in the database, therefore, the catalogId field value is not valid. If a catalog entry is already defined for the catalogId value, include the field values of the different fields in the input form in the XML DOM object. The XML DOM object is required to have a root element. In the example application, the XML DOM object has a <valid></valid> element that specifies the validity of the Catalog Id field value.

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, a new catalog entry may be added for the catalogId value by obtaining a JDBC connection to the database, and adding the catalog entry with an INSERT statement. Click here to view FormValidationServlet.

Processing a Response

If the readyState property value is 4, which corresponds to a completed XMLHttpRequest, and the status property value is 200, which corresponds to HTTP status “OK”, the processResponse() function gets invoked. In the processResponse function, obtain the value for the responseXML property.

var xmlMessage=xmlHttpRequest.responseXML;

As an alternative to processing an XML response, you could use xmlHttpRequest.responseText if you just are receiving “true”...

The responseXML object is an XML DOM object. Obtain the value of the <valid/> element using getElementsByTagName(String) method.

var valid=xmlMessage.getElementsByTagName("valid")[0].firstChild.nodeValue;

If the <valid/> element value is true, set the HTML of validationMessage div element in the Catalog Id field row to “Catalog Id is Valid”. Enable the submit button in the input form.

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 false, set the HTML of the validationMessage div element in Catalog ID field row to "Catalog Id is not Valid". Disable the submit button, and set the values of the other input fields.

if(valid=="false"){
var validationMessage=document.getElementById("validationMessage");
validationMessage.innerHTML = "Catalog Id is not Valid";
document.getElementById("submitForm").disabled = true;
}

Click here to view the JSP input.jsp.

Next, run the Ajax application in JDeveloper 10.1.3. Right-click on the input.jsp file in Applications Navigator, and select Run.

Figure 5
Figure 5: Running the Ajax Application

The input form gets displayed. Start adding data to Catalog Id field. An XMLHttpRequest is sent to the server to verify the validity of the data being added.

If the Catalog Id field value is valid, a “Catalog Id is Valid” message gets displayed.

Figure 6
Figure 6: Input Form with Dynamic Validation

A XMLHttpRequest is sent with each modification to the Catalog Id input field.

Figure 7
Figure 7: Modifying Input Field Value

If a value is added that is already defined in the database, a “Catalog Id is not Valid” message gets displayed and the Submit button gets disabled.

Figure 8
Figure 8: Invalid Input Field Value

Specify a Catalog Id field value that is valid and click on Create Catalog button to add a catalog entry.

Figure 9
Figure 9: Adding a Catalog Entry

The form is posted to the server with POST method, because the method specified in <form/> element is POST. A catalog entry for the specified field values gets added to the database. If subsequently, a Catalog Id value of Catalog4 is re-specified, an XMLHttpRequest gets sent to the server, and the response has <valid/> element set to false.

Figure 10
Figure 10: Form Disabled for an Invalid Input Field

Congratulations, you have just created an "Ajaxian" Web application!

Conclusion

As you've seen here, the Ajax technique provides dynamic validation of data added to an input form using the XMLHttpRequest object. Furthermore, a combination other than JavaScript, DOM, and Servlet may be used. For example, the server side application may be a PHP script instead of a servlet.

Happy Ajax coding!


Deepak Vohra ( dvohra09@yahoo.com) is a Sun Certified Java Programmer, a NuBean consultant, and has been published in onjava.com, XML Journal, WebLogic Developer's Journal, and OTN.