| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
| "http://www.w3.org/TR/html4/loose.dtd"> |
| |
| <html> |
| <head> |
| <meta name="author" content="troy.giunipero@sun.com"> |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8"> |
| <meta name="description" content="A brief introduction to Ajax using the NetBeans IDE, Java bundle"> |
| |
| <meta name="keywords" content="NetBeans, IDE, integrated development environment, Ajax, XML, |
| XMLHttpRequest, XMLHttpRequest object, callback function, asynchronous, Java, JavaScript, |
| JavaScript Editor, open source, web technology"> |
| |
| <link rel="stylesheet" type="text/css" href="../../../netbeans.css"> |
| <link rel="stylesheet" type="text/css" href="../../../lytebox.css" media="screen"> |
| <script type="text/javascript" src="../../../images_www/js/lytebox-compressed.js"></script> |
| |
| <title>Introduction to Ajax for Java Web Applications - NetBeans IDE Tutorial</title> |
| </head> |
| |
| <body> |
| |
| <!-- |
| Copyright (c) 2009, 2010, 2011 Oracle and/or its affiliates. All rights reserved. |
| --> |
| |
| <h1>Introduction to Ajax for Java Web Applications</h1> |
| |
| <p>This document provides an introduction to Ajax and demonstrates some of the features in the |
| NetBeans IDE that allow you to program faster and more efficiently when working with Ajax-related |
| technologies. While learning about the low-level functionality of Ajax, you build a simple |
| application that employs auto-completion in a text field. Content here has been adapted from |
| Greg Murray's article and sample application from |
| <a href="http://weblogs.java.net/blog/gmurray71/archive/2005/12/using_ajax_with_1.html">Using |
| Ajax with Java Technology</a>.</p> |
| |
| <p>Ajax stands for Asynchronous JavaScript and XML. In essence, Ajax is an efficient way for |
| a web application to handle user interactions with a web page - a way that reduces the need |
| to do a page refresh or full page reload for every user interaction. This enables rich behavior |
| (similar to that of a desktop application or plugin-based web application) using a browser. |
| Ajax interactions are handled asynchronously in the background. As this happens, a user can |
| continue working with the page. Ajax interactions are initiated by JavaScript code. When |
| the Ajax interaction is complete, JavaScript updates the HTML source of the page. The changes |
| are made immediately without requiring a page refresh. Ajax interactions can be used to do |
| things such as validate form entries (while the user is entering them) using server-side |
| logic, retrieve detailed data from the server, dynamically update data on a page, and submit |
| partial forms from the page.</p> |
| |
| |
| <p><strong>Contents</strong></p> |
| |
| <img src="../../../images_www/articles/73/netbeans-stamp-80-74-73.png" class="stamp" alt="Content on this page applies to NetBeans IDE 7.2, 7.3, 7.4 and 8.0" title="Content on this page applies to the NetBeans IDE 7.2, 7.3, 7.4 and 8.0" > |
| |
| <ul class="toc"> |
| <li><a href="#overview">Overview of the Application</a></li> |
| <li><a href="#client1">Programming the Client-Side: Part 1</a> |
| <ul> |
| <li><a href="#html">Using the HTML Editor</a></li> |
| <li><a href="#javascript">Using the JavaScript Editor</a></li> |
| </ul></li> |
| <li><a href="#serverside">Programming the Server-Side</a> |
| <ul> |
| <li><a href="#data">Creating the Data Store</a></li> |
| <li><a href="#servlet">Creating a Servlet</a></li> |
| </ul></li> |
| <li><a href="#client2">Programming the Client-Side: Part 2</a> |
| <ul> |
| <li><a href="#callback">Adding Callback Functionality</a></li> |
| <li><a href="#htmldom">Updating the HTML DOM</a></li> |
| <li><a href="#stylesheet">Attaching a Stylesheet</a></li> |
| </ul></li> |
| <li><a href="#run">Running the Application</a> |
| <ul> |
| <li><a href="#httpMonitor">Using the HTTP Server Monitor</a></li> |
| </ul></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| <li><a href="#seeAlso">See Also</a></li> |
| </ul> |
| |
| <p><strong>To complete this tutorial, you need the following software and resources.</strong></p> |
| |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">NetBeans |
| IDE, Java EE bundle</a></td> |
| <td class="tbltd1">7.3, 7.4, 8.0</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">7 or 8</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://glassfish.java.net/">GlassFish server</a> |
| <br><em class="indent margin-around">or</em> |
| <br><a href="http://tomcat.apache.org/index.html">Tomcat server</a></td> |
| <td class="tbltd1">Open Source Edition 3.1.x or 4.x |
| <br><em class="margin-around indent"> </em> |
| <br>version 7.x or 8.x</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p class="notes"><strong>Notes:</strong></p> |
| |
| <ul> |
| <li>The Java EE installation of the IDE enables you to optionally install the GlassFish server |
| and the Apache Tomcat servlet container.</li> |
| |
| <li>This tutorial assumes that you have a working knowledge of the various technologies it |
| employs (i.e., HTML, CSS, JavaScript, Java and JSP). It attempts to provide |
| an overview of the functionality provided by the code, but <em>does not</em> explain |
| how the code works on a line-to-line basis.</li> |
| |
| <li>If you need to compare your project with a working solution, you can <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaScript%252FMyAjaxApp.zip">download |
| the sample application</a>.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="overview">Overview of the Application</h2> |
| |
| <p>Imagine a web page in which a user can search for information about musical composers. The |
| page includes a field where the user can enter the name of the composer. In the example application, |
| the entry field has an auto-complete feature. In other words, the user can type in part of |
| the composer name, and the web application attempts to complete the name by listing all composers |
| whose first or last name begins with the characters entered. The auto-complete feature saves |
| the user from having to remember the complete name of the composer and can provide a more |
| intuitive and direct path to the sought-after information.</p> |
| |
| <div class="indent"> |
| <img src="../../../images_www/articles/73/web/ajax-intro/sample-app.png" |
| alt="Sample application displayed in browser" class="margin-around b-all" |
| title="Sample application displayed in browser"> |
| </div> |
| |
| <p>Implementing auto-completion in a search field is something that can be performed using Ajax. |
| Ajax works by employing an <code>XMLHttpRequest</code> object to pass requests and responses |
| asynchronously between the client and server. The following diagram illustrates the process |
| flow of the communication that takes place between the client and server.</p> |
| |
| <div id="flow-diagram" class="indent"> |
| <img src="../../../images_www/articles/73/web/ajax-intro/ajax-process-flow.png" |
| alt="Ajax process flow diagram" class="margin-around" |
| title="Ajax process flow diagram"> |
| </div> |
| |
| <br> |
| <p>The process flow of the diagram can be described by the following steps:</p> |
| |
| <ol> |
| <li>The user triggers an event, for example by releasing a key when typing in a name. This |
| results in a JavaScript call to a function that initializes an <code>XMLHttpRequest</code> |
| object.</li> |
| |
| <li>The <code>XMLHttpRequest</code> object is configured with a request parameter that includes |
| the ID of the component that triggered the event, and any value that the user entered. |
| The <code>XMLHttpRequest</code> object then makes an asynchronous request to the web |
| server.</li> |
| |
| <li>On the web server, an object such as a servlet or listener handles the request. Data |
| is retrieved from the data store, and a response is prepared containing the data in the |
| form of an XML document.</li> |
| |
| <li>Finally, the <code>XMLHttpRequest</code> object receives the XML data using a callback |
| function, processes it, and updates the HTML DOM (Document Object Model) to display the |
| page containing the new data.</li> |
| </ol> |
| |
| <p>This tutorial demonstrates how to construct the auto-complete scenario by following the |
| process flow indicated in the above diagram. You first create the client-side files for the |
| presentation and functionality needed to generate the <code>XMLHttpRequest</code> object. |
| Then, you set up the server-side by creating the data store and business logic using Java-based |
| technology. Finally, you return to the client-side and implement <code>callback()</code>, |
| and other JavaScript functionality to update the HTML DOM.</p> |
| |
| |
| <br> |
| <h2 id="client1">Programming the Client-Side: Part 1</h2> |
| |
| <p>Begin by creating a new web application project in the IDE. The IDE contains built-in templates |
| for numerous project types.</p> |
| |
| <ol> |
| <li>Choose File > New Project. Under Categories, select Java Web. Under Projects, select Web |
| Application then click Next.</li> |
| |
| <li>In the Name and Location panel, enter <code>MyAjaxApp</code> for Project Name. The Project |
| Location field enables you to specify the location of the project on your computer. Leave |
| other options at their defaults and click Next. |
| |
| <br> |
| <img src="../../../images_www/articles/73/web/ajax-intro/java-name-location.png" |
| title="Specify the name and location for your application project" |
| class="margin-around b-all" alt="New Web Application wizard - Name and Location panel"></li> |
| |
| <li>In the Server and Settings panel, select the server you want to deploy your application |
| to. Only servers that are registered with the IDE are listed. |
| |
| <br> |
| <img src="../../../images_www/articles/73/web/ajax-intro/java-server-settings.png" |
| title="Specify the server your application will be deployed to" |
| class="margin-around b-all" alt="New Web Application wizard - Server Settings panel"></li> |
| |
| <li>Accept other default settings and click Finish. The project is generated in your |
| file system and opens in the IDE.</li> |
| </ol> |
| |
| <p>When Java-based web projects are created, an <a href="http://ant.apache.org/">Ant</a> build |
| script is automatically generated which enables you to compile the project so that it can |
| be immediately deployed and run on a server that has been registered in the IDE.</p> |
| |
| <p>A default entry page is generated and opens in the IDE's Source Editor. |
| Depending on the target server, the entry page will be either <code>index.jsp</code> or <code>index.html</code>. |
| </p> |
| |
| <div class="indent"> |
| <div class="indent"> |
| <img src="../../../images_www/articles/73/web/ajax-intro/java-proj-win.png" |
| alt="Projects window containing newly created project" class="margin-around b-all" |
| title="Projects window displays MyAjaxApp project"> |
| </div> |
| </div> |
| |
| <p>Before beginning to code, quickly try running the application to ensure that configuration |
| between the IDE, your server, and browser is set up properly.</p> |
| |
| <ol> |
| <li><p>In the Projects window, right-click the project node and choose Run.</p> |
| |
| <p>The application is compiled, the application server starts and the application is |
| deployed to it and run. The IDE opens your default browser and displays the default |
| entry page.</p> |
| </li> |
| </ol> |
| |
| <div class="indent"> |
| <a name="html"></a> |
| <h3>Using the HTML Editor</h3> |
| |
| <div class="indent"> |
| <img src="../../../images_www/articles/73/web/ajax-intro/palette.png" |
| alt="Palette displaying HTML elements" class="right margin-around b-all" |
| title="Palette displaying HTML elements"> |
| |
| <br> |
| <p class="margin-around">Now that you are certain your environment is set up correctly, |
| begin by transforming your index page into the auto-completion interface that will |
| be viewed by users.</p> |
| |
| <p class="margin-around">One of the advantages of using an IDE is that the editor you |
| work in often provides you with code completion which, if you learn to apply it when |
| you code, can rapidly increase your productivity. The IDE's Source Editor generally |
| adapts to the technology you are using, so if you are working in an HTML page, pressing |
| the code completion key combination (Ctrl-Space) will produce suggestions for HTML |
| tags and attributes. As will later be shown, the same applies for other technologies, |
| such as CSS and JavaScript.</p> |
| |
| <p class="margin-around"> |
| A second feature you can make use of is the IDE's Palette. The Palette provides easy-to-use |
| templates for elements that are commonly applied in the technology you are coding |
| in. You simply click on an item, and drag it to a location in the file open in the |
| Source Editor.</p> |
| |
| <p class="tips margin-around">You can view large icons (as displayed here) by right-clicking |
| in the Palette and choosing Show Big Icons.</p> |
| </div> |
| |
| <br clear="all"> |
| <ol> |
| <li>Replace the content for the <code><title></code> and <code><h1></code>tags to read: <code>Auto-Completion |
| using AJAX</code>. The index |
| page requires no server-side scripting code, so you can safely delete any remnants |
| that were created by default. The index page should now appear as shown below. |
| |
| <pre class="examplecode"> |
| <!DOCTYPE html> |
| |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <title>Auto-Completion using AJAX</title> |
| </head> |
| <body> |
| <h1>Auto-Completion using AJAX</h1> |
| </body> |
| </html> |
| </pre></li> |
| |
| <li>Add some explanatory text to describe the purpose of the text field. You can copy |
| and paste in the following text at a point just beneath the <code><h1></code> |
| tags: |
| |
| <pre class="examplecode"> |
| <p>This example shows how you can do real time auto-completion using Asynchronous |
| JavaScript and XML (Ajax) interactions.</p> |
| |
| <p>In the form below enter a name. Possible names that will be completed are displayed |
| below the form. For example, try typing in "Bach," "Mozart," or "Stravinsky," |
| then click on one of the selections to see composer details.</p> |
| </pre></li> |
| |
| <li>Add an HTML form to the page. You can do this by making use of the elements listed |
| in the IDE's Palette. If the Palette is not open, choose Window > Palette from |
| the main menu. Then, under HTML Forms, click on and drag a Form element into the |
| page to a point beneath the <code><p></code> tags that you just added. The |
| Insert Form dialog box opens. Specify the following: |
| |
| <br><br> |
| <ul> |
| <li>Action: autocomplete</li> |
| <li>Method: GET</li> |
| <li>Name: autofillform</li> |
| </ul> |
| |
| <img src="../../../images_www/articles/73/web/ajax-intro/insert-form.png" |
| alt="Insert form dialog" class="margin-around b-all" |
| title="Insert form dialog"> |
| |
| <p>Click OK. The HTML <code><form></code> tags are inserted into the page containing |
| the attributes you specified. (GET is applied by default, and so is not explicitly |
| declared.)</p></li> |
| |
| <li>Add an HTML table to the page. Under the HTML category in the Palette, click on a |
| Table element and drag it to a point between the <code><form></code> tags. |
| The Insert Table dialog box opens. Specify the following: |
| |
| <br><br> |
| <ul> |
| <li>Rows: 2</li> |
| <li>Columns: 2</li> |
| <li>Border Size: 0</li> |
| <li>Cell Padding: 5</li> |
| </ul> |
| |
| <img src="../../../images_www/articles/73/web/ajax-intro/insert-table.png" |
| alt="Insert table dialog" class="margin-around b-all" |
| title="Insert table dialog"> |
| </li> |
| |
| <li>Right-click inside the Source Editor and choose Format. This tidies up the code. |
| Your form should now display similar to that below: |
| |
| <pre class="examplecode"> |
| <form name="autofillform" action="autocomplete"> |
| <table border="0" cellpadding="5"> |
| <thead> |
| <tr> |
| <th></th> |
| <th></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td></td> |
| <td></td> |
| </tr> |
| <tr> |
| <td></td> |
| <td></td> |
| </tr> |
| </tbody> |
| </table> |
| </form> |
| </pre></li> |
| |
| <li>Within the first row of the table, type the following text into the first column |
| (changes in <strong>bold</strong>): |
| |
| <pre class="examplecode"><td><strong><strong>Composer Name:</strong></strong></td></pre></li> |
| |
| <li>Within the second column of the first row, instead of dragging a Text Input field |
| from the Palette, type in the code below manually (changes in <strong>bold</strong>): |
| |
| |
| <pre class="examplecode"> |
| <td> |
| <strong><input type="text" |
| size="40" |
| id="complete-field" |
| onkeyup="doCompletion();"></strong> |
| </td> |
| </pre> |
| |
| When you type, try using the IDE's built-in code completion support. For example, |
| type in <code><i</code>, then press Ctrl-Space. A list of suggested options displays |
| below your cursor, and a description of the selected element appears in a box above. |
| You can in fact press Ctrl-Space at anytime you are coding in the Source Editor to |
| bring up possible options. Also, if there is only one possible option, pressing Ctrl-Space |
| will automatically complete the element name. |
| |
| <br> |
| <img src="../../../images_www/articles/73/web/ajax-intro/code-completion.png" |
| class="margin-around b-all" alt="Code completion displayed in the Source Editor" |
| style="width:688px" title="Press Ctrl-Space in the editor to invoke code completion and documentation support"> |
| </li> |
| |
| </ol> |
| |
| <p>The <code>onkeyup</code> attribute that you typed in above points to a JavaScript function |
| named <code>doCompletion()</code>. This function is called each time a key is pressed |
| in the form text field, and maps to the JavaScript call depicted in the Ajax <a href="#flow-diagram">flow |
| diagram</a> above.</p> |
| |
| |
| <h3 id="javascript">Using the JavaScript Editor</h3> |
| |
| <p>The IDE's JavaScript Editor provides many advanced editing capabilities, such as intelligent |
| code completion, semantic highlighting, instant renaming and refactoring capabilities, |
| as well as many more features. </p> |
| |
| <p>JavaScript code completion is automatically provided when you code in <code>.js</code> |
| files, as well as within <code><script></code> tags when you work with other technologies |
| (i.e., HTML, RHTML, JSP, PHP). |
| The IDE can provide you with some hints when you are editing JavaScript code. |
| You can specify the JavaScript hints options by choosing |
| Tools > Options (NetBeans > Preferences on Mac) to open the Options window |
| and then selecting the JavaScript language in the Hints tab in the Editor category. |
| You can also add your own JavaScript code templates in the Code Templates tab in the Options window.</p> |
| |
| <img src="../../../images_www/articles/73/web/ajax-intro/javascript-options.png" |
| alt="JavaScript Hint 0ptions in Options window" class="margin-around b-all" |
| title="JavaScript Hint 0ptions in Options window"> |
| |
| <p>Add a JavaScript file to the application and begin implementing <code>doCompletion()</code>.</p> |
| |
| <ol> |
| <li>In the Projects window, right-click the Web Pages node and choose New > JavaScript |
| file. (If JavaScript file is not listed, choose Other. Then choose JavaScript file |
| from the Web category in the New File wizard.)</li> |
| <li>Name the file <code>javascript</code> and click Finish. |
| The new JavaScript file appears in the Projects window within the Web Pages folder.</li> |
| <li>Type the code below into <code>javascript.js</code>. |
| |
| <pre class="examplecode"> |
| var req; |
| var isIE; |
| |
| function init() { |
| completeField = document.getElementById("complete-field"); |
| } |
| |
| function doCompletion() { |
| var url = "autocomplete?action=complete&id=" + escape(completeField.value); |
| req = initRequest(); |
| req.open("GET", url, true); |
| req.onreadystatechange = callback; |
| req.send(null); |
| } |
| |
| function initRequest() { |
| if (window.XMLHttpRequest) { |
| if (navigator.userAgent.indexOf('MSIE') != -1) { |
| isIE = true; |
| } |
| return new XMLHttpRequest(); |
| } else if (window.ActiveXObject) { |
| isIE = true; |
| return new ActiveXObject("Microsoft.XMLHTTP"); |
| } |
| }</pre> |
| |
| <p class="tips">The above code performs a simple browser compatibility check |
| for Firefox 3 and Internet Explorer versions 6 and 7). If you would like |
| to incorporate more robust code for compatibility issues, consider using |
| this <a href="http://www.quirksmode.org/js/detect.html">browser detect |
| script</a> from <a href="http://www.quirksmode.org">http://www.quirksmode.org</a>.</p></li> |
| |
| <li>Switch back to the index page and add a reference to the JavaScript file |
| between the <code><head></code> tags. |
| |
| <pre class="examplecode"> |
| <script type="text/javascript" src="javascript.js"></script></pre> |
| |
| <p class="tips">You can quickly toggle between pages opened in the Source Editor |
| by pressing Ctrl-Tab.</p></li> |
| |
| <li>Insert a call to <code>init()</code> in the opening <code><body></code> tag. |
| |
| <pre class="examplecode"> |
| <body <strong>onload="init()"</strong>></pre> |
| |
| This ensures that <code>init()</code> is called each time the page is loaded.</li> |
| </ol> |
| |
| <p>The role of <code>doCompletion()</code> is to:</p> |
| |
| <ul> |
| <li>create a URL that contains data that can be utilized by the server-side,</li> |
| <li>initialize an <code>XMLHttpRequest</code> object, and</li> |
| <li>prompt the <code>XMLHttpRequest</code> object to send an asynchronous request to |
| the server.</li> |
| </ul> |
| |
| <p>The <code>XMLHttpRequest</code> object is at the heart of Ajax and has become the de facto |
| standard for enabling XML data to be passed asynchronously over HTTP. <em>Asynchronous</em> |
| interaction implies that the browser can continue to process events in the page after the |
| request is sent. Data is passed in the background, and can be automatically loaded into |
| the page without requiring a page refresh.</p> |
| |
| <p>Notice that the <code>XMLHttpRequest</code> object is actually created by <code>initRequest()</code>, |
| which is called by <code>doCompletion()</code>. The function checks whether <code>XMLHttpRequest</code> |
| can be understood by the browser, and if so it creates an <code>XMLHttpRequest</code> |
| object. Otherwise, it performs a check on <code>ActiveXObject</code> (the <code>XMLHttpRequest</code> |
| equivalent for Internet Explorer 6), and creates an <code>ActiveXObject</code> if identified.</p> |
| |
| <p>Three parameters are specified when you create an <code>XMLHttpRequest</code> object: |
| a URL, the HTTP method (<code>GET</code> or <code>POST</code>), and whether or not the |
| interaction is asynchronous. In the above example, the parameters are:</p> |
| |
| <ul> |
| <li>The URL <code>autocomplete</code>, and the text entered into the <code>complete-field</code> |
| by the user: |
| |
| <pre class="examplecode">var url = "autocomplete?action=complete&id=" + escape(completeField.value);</pre></li> |
| |
| <li><code>GET</code>, signifying that HTTP interactions use the <code>GET</code> method, |
| and |
| <li><code>true</code>, signifying that the interaction is asynchronous: |
| |
| <pre class="examplecode">req.open("GET", url, true);</pre></li> |
| </ul> |
| |
| <p>If the interaction is set as asynchronous, a callback function must be specified. The |
| callback function for this interaction is set with the statement:</p> |
| |
| <div class="indent"> |
| <div class="indent"> |
| <pre class="examplecode">req.onreadystatechange = callback;</pre> |
| </div> |
| </div> |
| |
| <p>and a <code>callback()</code> function <a href="#callback">must later be defined</a>. |
| The HTTP interaction begins when <code>XMLHttpRequest.send()</code> is called. This action |
| maps to the HTTP request that is sent to the web server in the above <a href="#flow-diagram">flow |
| diagram</a>.</p> |
| </div> |
| |
| |
| <br> |
| <h2 id="serverside">Programming the Server-Side</h2> |
| |
| <p>The IDE provides comprehensive support for server-side web programming. While this includes |
| basic editor support for many popular programming and scripting languages, it also encompasses |
| web services, such as SOAP, REST, SaaS, and MVC-oriented frameworks, such as JSF, Spring |
| and Struts. Several NetBeans plugins are available from the |
| <a href="http://plugins.netbeans.org/">NetBeans Plugin Portal</a> |
| for Ajax-driven frameworks, including <a href="https://developers.google.com/web-toolkit/">GWT</a> and |
| <a href="http://struts.apache.org/2.x/">Struts2</a>.</p> |
| |
| <p>The application's business logic processes requests by retrieving data from the data store, |
| then preparing and sending the response. This is implemented here using a servlet. Before |
| you begin coding the servlet, set up the data store and the functionality required by the |
| servlet to access data.</p> |
| |
| <ul> |
| <li><a href="#data">Creating the Data Store</a></li> |
| <li><a href="#servlet">Creating a Servlet</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <a name="data"></a> |
| <h3>Creating the Data Store</h3> |
| |
| <p>For this simple application, you create a class called <code>ComposerData</code> that |
| retains composer data using a <a href="http://download.oracle.com/javase/1.5.0/docs/api/java/util/HashMap.html"><code>HashMap</code></a>. |
| A <code>HashMap</code> allows you to store pairs of linked items in key-value pairs. |
| You also create a <code>Composer</code> class that enables the servlet to retrieve data |
| from entries in the <code>HashMap</code>.</p> |
| |
| <ol> |
| <li>Right-click on the project node in the Projects window and choose New > Java Class.</li> |
| <li>Name the class <code>ComposerData</code>, and enter <code>com.ajax</code> in the |
| Package field. This creates a new package to contain the class, as well as other |
| classes that will later be created.</li> |
| <li>Click Finish. The class is created and opens in the Source Editor.</li> |
| <li>In the Source Editor, paste in the following code: |
| |
| <pre class="examplecode"> |
| package com.ajax; |
| |
| import java.util.HashMap; |
| |
| /** |
| * |
| * @author nbuser |
| */ |
| public class ComposerData { |
| |
| private HashMap composers = new HashMap(); |
| |
| public HashMap getComposers() { |
| return composers; |
| } |
| |
| public ComposerData() { |
| |
| composers.put("1", new Composer("1", "Johann Sebastian", "Bach", "Baroque")); |
| composers.put("2", new Composer("2", "Arcangelo", "Corelli", "Baroque")); |
| composers.put("3", new Composer("3", "George Frideric", "Handel", "Baroque")); |
| composers.put("4", new Composer("4", "Henry", "Purcell", "Baroque")); |
| composers.put("5", new Composer("5", "Jean-Philippe", "Rameau", "Baroque")); |
| composers.put("6", new Composer("6", "Domenico", "Scarlatti", "Baroque")); |
| composers.put("7", new Composer("7", "Antonio", "Vivaldi", "Baroque")); |
| |
| composers.put("8", new Composer("8", "Ludwig van", "Beethoven", "Classical")); |
| composers.put("9", new Composer("9", "Johannes", "Brahms", "Classical")); |
| composers.put("10", new Composer("10", "Francesco", "Cavalli", "Classical")); |
| composers.put("11", new Composer("11", "Fryderyk Franciszek", "Chopin", "Classical")); |
| composers.put("12", new Composer("12", "Antonin", "Dvorak", "Classical")); |
| composers.put("13", new Composer("13", "Franz Joseph", "Haydn", "Classical")); |
| composers.put("14", new Composer("14", "Gustav", "Mahler", "Classical")); |
| composers.put("15", new Composer("15", "Wolfgang Amadeus", "Mozart", "Classical")); |
| composers.put("16", new Composer("16", "Johann", "Pachelbel", "Classical")); |
| composers.put("17", new Composer("17", "Gioachino", "Rossini", "Classical")); |
| composers.put("18", new Composer("18", "Dmitry", "Shostakovich", "Classical")); |
| composers.put("19", new Composer("19", "Richard", "Wagner", "Classical")); |
| |
| composers.put("20", new Composer("20", "Louis-Hector", "Berlioz", "Romantic")); |
| composers.put("21", new Composer("21", "Georges", "Bizet", "Romantic")); |
| composers.put("22", new Composer("22", "Cesar", "Cui", "Romantic")); |
| composers.put("23", new Composer("23", "Claude", "Debussy", "Romantic")); |
| composers.put("24", new Composer("24", "Edward", "Elgar", "Romantic")); |
| composers.put("25", new Composer("25", "Gabriel", "Faure", "Romantic")); |
| composers.put("26", new Composer("26", "Cesar", "Franck", "Romantic")); |
| composers.put("27", new Composer("27", "Edvard", "Grieg", "Romantic")); |
| composers.put("28", new Composer("28", "Nikolay", "Rimsky-Korsakov", "Romantic")); |
| composers.put("29", new Composer("29", "Franz Joseph", "Liszt", "Romantic")); |
| |
| composers.put("30", new Composer("30", "Felix", "Mendelssohn", "Romantic")); |
| composers.put("31", new Composer("31", "Giacomo", "Puccini", "Romantic")); |
| composers.put("32", new Composer("32", "Sergei", "Rachmaninoff", "Romantic")); |
| composers.put("33", new Composer("33", "Camille", "Saint-Saens", "Romantic")); |
| composers.put("34", new Composer("34", "Franz", "Schubert", "Romantic")); |
| composers.put("35", new Composer("35", "Robert", "Schumann", "Romantic")); |
| composers.put("36", new Composer("36", "Jean", "Sibelius", "Romantic")); |
| composers.put("37", new Composer("37", "Bedrich", "Smetana", "Romantic")); |
| composers.put("38", new Composer("38", "Richard", "Strauss", "Romantic")); |
| composers.put("39", new Composer("39", "Pyotr Il'yich", "Tchaikovsky", "Romantic")); |
| composers.put("40", new Composer("40", "Guiseppe", "Verdi", "Romantic")); |
| |
| composers.put("41", new Composer("41", "Bela", "Bartok", "Post-Romantic")); |
| composers.put("42", new Composer("42", "Leonard", "Bernstein", "Post-Romantic")); |
| composers.put("43", new Composer("43", "Benjamin", "Britten", "Post-Romantic")); |
| composers.put("44", new Composer("44", "John", "Cage", "Post-Romantic")); |
| composers.put("45", new Composer("45", "Aaron", "Copland", "Post-Romantic")); |
| composers.put("46", new Composer("46", "George", "Gershwin", "Post-Romantic")); |
| composers.put("47", new Composer("47", "Sergey", "Prokofiev", "Post-Romantic")); |
| composers.put("48", new Composer("48", "Maurice", "Ravel", "Post-Romantic")); |
| composers.put("49", new Composer("49", "Igor", "Stravinsky", "Post-Romantic")); |
| composers.put("50", new Composer("50", "Carl", "Orff", "Post-Romantic")); |
| |
| } |
| }</pre></li> |
| </ol> |
| <p>You will notice that a warning is displayed in the left margin of the editor because the <tt>Composer</tt> |
| class cannot be found. Perform the following steps to create the <code>Composer</code> class.</p> |
| |
| <ol> |
| <li>Right-click on the project node in the Projects window and choose New > Java Class.</li> |
| <li>Name the class <code>Composer</code>, and choose <code>com.ajax</code> from the drop-down |
| list in the Package field. Click Finish. |
| <p>When you click Finish the IDE creates the class and opens the file in the Source Editor.</p></li> |
| <li>In the Source Editor, paste in the following code: |
| |
| <pre class="examplecode"> |
| package com.ajax; |
| |
| public class Composer { |
| |
| private String id; |
| private String firstName; |
| private String lastName; |
| private String category; |
| |
| public Composer (String id, String firstName, String lastName, String category) { |
| this.id = id; |
| this.firstName = firstName; |
| this.lastName = lastName; |
| this.category = category; |
| } |
| |
| public String getCategory() { |
| return category; |
| } |
| |
| public String getId() { |
| return id; |
| } |
| |
| public String getFirstName() { |
| return firstName; |
| } |
| |
| public String getLastName() { |
| return lastName; |
| } |
| }</pre></li> |
| </ol> |
| <p>After you create the <tt>Composer</tt> class if you look at the <tt>ComposerData</tt> class |
| in the editor you can see that the warning annotations are no longer there. |
| If you still see warning annotations in <tt>ComposerData</tt> you can try to resolve the error |
| by adding any missing import statements.</p> |
| |
| <h3 id="servlet">Creating a Servlet</h3> |
| |
| <p>Create a servlet to handle the <code>autocomplete</code> URL that is received by the incoming |
| request.</p> |
| |
| <ol> |
| <li>Right-click on the project node in the Projects window and choose New > Servlet to open the New Servlet wizard. |
| (Choose Other and select Servlet from the Web category if Servlet is not displayed by default in the popup menu.)</li> |
| <li>Name the servlet <code>AutoCompleteServlet</code>, and choose <code>com.ajax</code> |
| from the drop-down list in the Package field. Click Next.<br> |
| <img src="../../../images_www/articles/73/web/ajax-intro/newservlet-name-location.png" alt="New Servlet wizard, completed Name and Location pane" class="margin-around b-all"></li> |
| <li>In the Configure Servlet Deployment panel, change the URL pattern to <strong><code>/autocomplete</code></strong> so that it matches the URL that |
| you previously set in the <code>XMLHttpRequest</code> object. <br> |
| <img alt="New Servlet wizard, completed Configure Servlet Deployment panel" src="../../../images_www/articles/73/web/ajax-intro/newservlet-configure-deployment.png" class="margin-around b-all" > |
| |
| <p>This panel saves you |
| the step of needing to manually add these details to the deployment descriptor.</p></li> |
| <li>Optionally, select "Add servlet information to deployment descriptor." |
| This is so your project is the same as the downloaded sample. |
| With later versions of the IDE, by default the servlet is registered by a <code>@WebServlet</code> |
| annotation instead of in a deployment descriptor. |
| The project will still work if you use the <code>@WebServlet</code> annotation instead of a deployment descriptor.</li> |
| <li>Click Finish. The servlet is created and opens in the Source Editor.</li> |
| </ol> |
| |
| <p>The only methods you need to override are <code>doGet()</code>, to define how the servlet |
| handles the <code>autocomplete</code> <code>GET</code> request, and <code>init()</code>, |
| which needs to initiate a <code>ServletContext</code> so the servlet can access other |
| classes in the application once it is put into service.</p> |
| |
| <p>You can override methods from superclasses using the IDE's Insert Code popup menu. Implement |
| <code>init()</code> by performing the following steps.</p> |
| |
| <ol> |
| <li>Place your cursor beneath the <code>AutoCompleteServlet</code> class declaration |
| in the Source Editor. Press Alt-Insert (Ctrl-I on Mac) to open the Generate Code popup |
| menu. |
| |
| <br> |
| <img src="../../../images_www/articles/73/web/ajax-intro/insert-code.png" |
| alt="Insert Code popup menu displayed in Source Editor" class="margin-around b-all" |
| title="Insert Code popup menu displayed in Source Editor"></li> |
| |
| <li>Choose Override Method. In the dialog that displays, all classes that <code>AutoCompleteServlet</code> |
| inherits from are displayed. Expand the GenericServlet node and select <code>init(Servlet Config config)</code>. |
| |
| <br> |
| <img src="../../../images_www/articles/73/web/ajax-intro/new-override.png" |
| alt="Override dialog listing inherited classes" class="margin-around b-all" |
| title="Override dialog lists inherited classes"></li> |
| |
| <li>Click OK. The <code>init()</code> method is added in the Source Editor.</li> |
| |
| <li>Add a variable for a <code>ServletContext</code> object and modify <code>init()</code> |
| (changes in <strong>bold</strong>): |
| |
| <pre class="examplecode"> |
| <strong>private ServletContext context;</strong> |
| |
| @Override |
| public void init(ServletConfig <strong>config</strong>) throws ServletException { |
| <strong>this.context = config.getServletContext();</strong> |
| }</pre></li> |
| |
| <li>Add an import statement for <code>ServletContext</code>. You can do this by clicking |
| on the lightbulb icon that displays in the left margin of the Source Editor |
| |
| <br> |
| <img src="../../../images_www/articles/73/web/ajax-intro/import-hint.png" |
| alt="Import hint displayed in left margin of Source Editor" class="margin-around b-all" |
| title="Import hints display in left margin of the Source Editor"></li> |
| </ol> |
| |
| <p>The <code>doGet()</code> method needs to parse the URL of the request, retrieve data from |
| the data store, and prepare a response in XML format. Note that the method declaration |
| was generated when you created the class. To view it, you may need to expand the HttpServlet |
| methods by clicking on the expand icon (<img src="../../../images_www/articles/73/web/ajax-intro/expand-icon.png" |
| alt="expand icon">) in the left margin.</p> |
| |
| <ol> |
| <li>Add the following variable declarations beneath the <code>AutocompleteServlet</code> |
| class declaration. |
| |
| <pre class="examplecode"> |
| private ComposerData compData = new ComposerData(); |
| private HashMap composers = compData.getComposers();</pre> |
| |
| This creates a <code>HashMap</code> of all composer data, which is then employed |
| by <code>doGet()</code>.</li> |
| |
| <li>Scroll down to <code>doGet()</code> and implement the method as follows: |
| |
| <pre class="examplecode"> |
| @Override |
| public void doGet(HttpServletRequest request, HttpServletResponse response) |
| throws IOException, ServletException { |
| |
| String action = request.getParameter("action"); |
| String targetId = request.getParameter("id"); |
| StringBuffer sb = new StringBuffer(); |
| |
| if (targetId != null) { |
| targetId = targetId.trim().toLowerCase(); |
| } else { |
| context.getRequestDispatcher("/error.jsp").forward(request, response); |
| } |
| |
| boolean namesAdded = false; |
| if (action.equals("complete")) { |
| |
| // check if user sent empty string |
| if (!targetId.equals("")) { |
| |
| Iterator it = composers.keySet().iterator(); |
| |
| while (it.hasNext()) { |
| String id = (String) it.next(); |
| Composer composer = (Composer) composers.get(id); |
| |
| if ( // targetId matches first name |
| composer.getFirstName().toLowerCase().startsWith(targetId) || |
| // targetId matches last name |
| composer.getLastName().toLowerCase().startsWith(targetId) || |
| // targetId matches full name |
| composer.getFirstName().toLowerCase().concat(" ") |
| .concat(composer.getLastName().toLowerCase()).startsWith(targetId)) { |
| |
| sb.append("<composer>"); |
| sb.append("<id>" + composer.getId() + "</id>"); |
| sb.append("<firstName>" + composer.getFirstName() + "</firstName>"); |
| sb.append("<lastName>" + composer.getLastName() + "</lastName>"); |
| sb.append("</composer>"); |
| namesAdded = true; |
| } |
| } |
| } |
| |
| if (namesAdded) { |
| response.setContentType("text/xml"); |
| response.setHeader("Cache-Control", "no-cache"); |
| response.getWriter().write("<composers>" + sb.toString() + "</composers>"); |
| } else { |
| //nothing to show |
| response.setStatus(HttpServletResponse.SC_NO_CONTENT); |
| } |
| } |
| if (action.equals("lookup")) { |
| |
| // put the target composer in the request scope to display |
| if ((targetId != null) && composers.containsKey(targetId.trim())) { |
| request.setAttribute("composer", composers.get(targetId)); |
| context.getRequestDispatcher("/composer.jsp").forward(request, response); |
| } |
| } |
| }</pre></li> |
| </ol> |
| |
| <p>As you can see in this servlet, there is nothing really new you need to learn to write |
| server-side code for Ajax processing. The response content type needs to be set to <code>text/xml</code> |
| for cases where you want to exchange XML documents. With Ajax, you can also exchange |
| plain text or even snippets of JavaScript which may be evaluated or executed by the callback |
| function on the client. Note too that some browsers might cache the results, and so it |
| may be necessary to set the Cache-Control HTTP header to <code>no-cache</code>.</p> |
| |
| <p>In this example, the servlet generates an XML document that contains all composers with |
| a first or last name beginning with the characters typed in by the user. This document |
| maps to the XML Data depicted in the <a href="#flow-diagram">flow diagram</a> above. |
| Here is an example of an XML document that is returned to the <code>XMLHttpRequest</code> |
| object:</p> |
| |
| <div class="indent"> |
| <div class="indent"> |
| <pre class="examplecode"> |
| <composers> |
| <composer> |
| <id>12</id> |
| <firstName>Antonin</firstName> |
| <lastName>Dvorak</lastName> |
| </composer> |
| <composer> |
| <id>45</id> |
| <firstName>Aaron</firstName> |
| <lastName>Copland</lastName> |
| </composer> |
| <composer> |
| <id>7</id> |
| <firstName>Antonio</firstName> |
| <lastName>Vivaldi</lastName> |
| </composer> |
| <composer> |
| <id>2</id> |
| <firstName>Arcangelo</firstName> |
| <lastName>Corelli</lastName> |
| </composer> |
| </composers> |
| </pre> |
| </div> |
| </div> |
| |
| <p class="tips">You can use the IDE's <a href="#httpMonitor">HTTP Monitor</a> |
| to view the returned XML data once you complete the application.</p> |
| |
| </div> |
| |
| |
| <h2 id="client2">Programming the Client-Side: Part 2</h2> |
| |
| <p>You must now define the callback function to handle the server's response, and add any functionality |
| necessary to reflect changes in the page that is viewed by the user. This requires modifying |
| the HTML DOM. You need to create JSP pages to display the results of a successful request or the error messages of a failed request. |
| You can then create a simple stylesheet for the presentation.</p> |
| |
| <ul> |
| <li><a href="#callback">Adding Callback Functionality</a></li> |
| <li><a href="#htmldom">Updating the HTML DOM</a></li> |
| <li><a href="#displayresults">Displaying the Results</a></li> |
| <li><a href="#stylesheet">Attaching a Stylesheet</a></li> |
| </ul> |
| |
| <div class="indent"> |
| |
| <a name="callback"></a> |
| <h3>Adding Callback Functionality</h3> |
| |
| <p>The callback function is called asynchronously at specific points during HTTP interaction |
| when the <code>readyState</code> property of the <code>XMLHttpRequest</code> object changes. |
| In the application you are building, the callback function is <code>callback()</code>. |
| You recall that in <code>doCompletion()</code>, <code>callback</code> was set as the |
| <code>XMLHttpRequest.onreadystatechange</code> property to a function. Now, implement |
| the callback function as follows.</p> |
| |
| <ol> |
| <li>Open <code>javascript.js</code> in the Source Editor and type in the code below. |
| |
| <pre class="examplecode"> |
| function callback() { |
| if (req.readyState == 4) { |
| if (req.status == 200) { |
| parseMessages(req.responseXML); |
| } |
| } |
| }</pre></li> |
| </ol> |
| |
| <p>A <code>readyState</code> of "4" signifies the completion of the HTTP interaction. |
| The API for <code>XMLHttpRequest.readState</code> indicates that there are 5 possible |
| values that can be set. These are:</p> |
| |
| <div class="indent"> |
| <div class="indent"> |
| <table class="half-width"> |
| <thead class="tblheader"> |
| <tr> |
| <th class="innerpadding"><code>readyState</code> Value</th> |
| <th class="innerpadding">Object Status Definition</th> |
| </tr> |
| </thead> |
| <tbody class="tbltd0 align-center"> |
| <tr> |
| <td>0</td> |
| <td>uninitialized</td> |
| </tr> |
| <tr> |
| <td>1</td> |
| <td>loading</td> |
| </tr> |
| <tr> |
| <td>2</td> |
| <td>loaded</td> |
| </tr> |
| <tr> |
| <td>3</td> |
| <td>interactive</td> |
| </tr> |
| <tr> |
| <td>4</td> |
| <td>complete</td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| |
| <br> |
| <p>Notice that the <code>parseMessages()</code> function is called only when the |
| <code>XMLHttpRequest.readyState</code> is "4" and the <code>status</code> |
| -- the HTTP status code definition of the request -- is "200", signifying a |
| success. You will define <code>parseMessages()</code> next in <a href="#htmldom">Updating |
| the HTML DOM</a>.</p> |
| |
| <a name="htmldom"></a> |
| <h3>Updating the HTML DOM</h3> |
| |
| <p>The <code>parseMessages()</code> function handles the incoming XML data. In doing so, |
| it relies on several ancillary functions, such as <code>appendComposer()</code>, <code>getElementY()</code>, |
| and <code>clearTable()</code>. You must also introduce new elements to the index page, |
| such as a second HTML table which serves as the auto-complete box, and ID's for elements |
| so they can be referenced in <code>javascript.js</code>. Finally, you create new variables |
| corresponding to ID's for elements in the index page, initialize them in the |
| <code>init()</code> function that you previously implemented, and add some functionality |
| that is needed each time the index page is loaded.</p> |
| |
| <p class="notes"><strong>Note:</strong> The functions and elements that you create in the |
| following steps work interdependently. It is recommended that you work through this section, |
| then examine the code once it is all in place.</p> |
| |
| <ol> |
| <li>Open the index page in the Source Editor and type in the below code for the |
| second row of the HTML table you previously created. |
| |
| <pre class="examplecode"> |
| <tr> |
| <strong><td id="auto-row" colspan="2"> |
| <table id="complete-table" /> |
| </td></strong> |
| </tr></pre> |
| |
| The second row of the table contains another HTML table. This table represents the |
| auto-complete box that will be used to populate composer names.</li> |
| |
| <li>Open <code>javascript.js</code> in the Source Editor and the following three variables |
| to the top of the file. |
| |
| <pre class="examplecode"> |
| var completeField; |
| var completeTable; |
| var autoRow;</pre></li> |
| |
| <li>Add the following lines (in <strong>bold</strong>) to the <code>init()</code> function. |
| |
| <pre class="examplecode"> |
| function init() { |
| completeField = document.getElementById("complete-field"); |
| <strong>completeTable = document.getElementById("complete-table"); |
| autoRow = document.getElementById("auto-row"); |
| completeTable.style.top = getElementY(autoRow) + "px";</strong> |
| }</pre> |
| |
| One purpose of <code>init()</code> is to make elements inside the index page |
| accessible to other functions that will modify the index page's DOM.</li> |
| |
| <li>Add <code>appendComposer()</code> to <code>javascript.js</code>. |
| |
| <pre class="examplecode"> |
| function appendComposer(firstName,lastName,composerId) { |
| |
| var row; |
| var cell; |
| var linkElement; |
| |
| if (isIE) { |
| completeTable.style.display = 'block'; |
| row = completeTable.insertRow(completeTable.rows.length); |
| cell = row.insertCell(0); |
| } else { |
| completeTable.style.display = 'table'; |
| row = document.createElement("tr"); |
| cell = document.createElement("td"); |
| row.appendChild(cell); |
| completeTable.appendChild(row); |
| } |
| |
| cell.className = "popupCell"; |
| |
| linkElement = document.createElement("a"); |
| linkElement.className = "popupItem"; |
| linkElement.setAttribute("href", "autocomplete?action=lookup&id=" + composerId); |
| linkElement.appendChild(document.createTextNode(firstName + " " + lastName)); |
| cell.appendChild(linkElement); |
| }</pre> |
| |
| This function creates a new table row, inserts a link to a composer into it using |
| the data passed to the function via its three parameters, and inserts the row into |
| the index page's <code>complete-table</code> element.</li> |
| |
| <li>Add <code>getElementY()</code> to <code>javascript.js</code>. |
| |
| <pre class="examplecode"> |
| function getElementY(element){ |
| |
| var targetTop = 0; |
| |
| if (element.offsetParent) { |
| while (element.offsetParent) { |
| targetTop += element.offsetTop; |
| element = element.offsetParent; |
| } |
| } else if (element.y) { |
| targetTop += element.y; |
| } |
| return targetTop; |
| }</pre> |
| |
| This function is applied to find the vertical position of the parent element. This |
| is necessary because the actual position of the element, when it is displayed, is |
| often dependent on browser type and version. Note that the <code>complete-table</code> |
| element, when displayed containing composer names, is shifted to the lower right |
| of the table in which it exists. The correct height positioning is determined by |
| <code>getElementY()</code>. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> See <a href="http://www.quirksmode.org/js/findpos.html">this |
| explanation</a> of <code>offset</code> on <a href="http://www.quirksmode.org/">http://www.quirksmode.org/</a>.</p></li> |
| |
| <li>Add <code>clearTable()</code> to <code>javascript.js</code>. |
| |
| <pre class="examplecode"> |
| function clearTable() { |
| if (completeTable.getElementsByTagName("tr").length > 0) { |
| completeTable.style.display = 'none'; |
| for (loop = completeTable.childNodes.length -1; loop >= 0 ; loop--) { |
| completeTable.removeChild(completeTable.childNodes[loop]); |
| } |
| } |
| }</pre> |
| |
| This function sets the display of the <code>complete-table</code> element to 'none', |
| (i.e., makes it invisible), and it removes any existing composer name entries that |
| were created.</li> |
| |
| <li>Modify the <code>callback()</code> function to call <code>clearTable()</code> |
| each time new data is received from the server. Any composer entries that already |
| exist in the auto-complete box are therefore removed before it becomes populated |
| with new entries. |
| |
| <pre class="examplecode"> |
| function callback() { |
| |
| <strong>clearTable();</strong> |
| |
| if (req.readyState == 4) { |
| if (req.status == 200) { |
| parseMessages(req.responseXML); |
| } |
| } |
| }</pre></li> |
| |
| <li>Add <code>parseMessages()</code> to <code>javascript.js</code>. |
| |
| <pre class="examplecode"> |
| function parseMessages(responseXML) { |
| |
| // no matches returned |
| if (responseXML == null) { |
| return false; |
| } else { |
| |
| var composers = responseXML.getElementsByTagName("composers")[0]; |
| |
| if (composers.childNodes.length > 0) { |
| completeTable.setAttribute("bordercolor", "black"); |
| completeTable.setAttribute("border", "1"); |
| |
| for (loop = 0; loop < composers.childNodes.length; loop++) { |
| var composer = composers.childNodes[loop]; |
| var firstName = composer.getElementsByTagName("firstName")[0]; |
| var lastName = composer.getElementsByTagName("lastName")[0]; |
| var composerId = composer.getElementsByTagName("id")[0]; |
| appendComposer(firstName.childNodes[0].nodeValue, |
| lastName.childNodes[0].nodeValue, |
| composerId.childNodes[0].nodeValue); |
| } |
| } |
| } |
| }</pre></li> |
| </ol> |
| |
| <p>The <code>parseMessages()</code> function receives as a parameter an object representation |
| of the XML document returned by the <code>AutoComplete</code> servlet. The function programmatically |
| traverses the XML document, extracting the <code>firstName</code>, <code>lastName</code>, |
| and <code>id</code> of each entry, then passes this data to <code>appendComposer()</code>. |
| This results in a dynamic update to the contents of the <code>complete-table</code> element. |
| For example, an entry that is generated and inserted into <code>complete-table</code> |
| might look as follows: |
| |
| <div class="indent"> |
| <div class="indent"> |
| <pre class="examplecode"> |
| <tr> |
| <td class="popupCell"> |
| <a class="popupItem" href="autocomplete?action=lookup&id=12">Antonin Dvorak</a> |
| </td> |
| </tr></pre> |
| |
| </div> |
| </div> |
| |
| <p>The dynamic update to the <code>complete-table</code> element represents the final step |
| of the process flow of communication that takes place during communication using Ajax. |
| This update maps to the HTML & CSS data being sent to the presentation in the <a href="#flow-diagram">flow |
| diagram</a> above.</p> |
| |
| <h3 id="displayresults">Displaying the Results</h3> |
| <p>To display the results, you need a JSP file named <code>composers.jsp</code>. This page is called from <code>AutoCompleteServlet</code> during a lookup action. You also need an <code>error.jsp</code> file, which is called from <code>AutoCompleteServlet</code> if the composer cannot be found.</p> |
| <p><strong>To display results and errors:</strong></p> |
| <ol> |
| <li>In the Projects window, right-click the application's Web Pages folder and select New > JSP. The New JSP wizard opens.</li> |
| <li>In the File Name field, type <code>composer</code>. In the Created File field, you should see a path ending in <code>/web/composer.jsp</code>.</li> |
| <li>Click Finish. The file <code>composer.jsp</code> opens in the editor. A node for the file appears in the Projects window in the Web Pages folder. </li> |
| <li>Replace the placeholder code in <code>composer.jsp</code> with the following code: |
| <pre class="examplecode"><html> |
| <head> |
| <title>Composer Information</title> |
| |
| <link rel="stylesheet" type="text/css" href="stylesheet.css"> |
| </head> |
| <body> |
| |
| <table> |
| <tr> |
| <th colspan="2">Composer Information</th> |
| </tr> |
| <tr> |
| <td>First Name: </td> |
| <td>${requestScope.composer.firstName}</td> |
| </tr> |
| <tr> |
| <td>Last Name: </td> |
| <td>${requestScope.composer.lastName}</td> |
| </tr> |
| <tr> |
| <td>ID: </td> |
| <td>${requestScope.composer.id}</td> |
| </tr> |
| <tr> |
| <td>Category: </td> |
| <td>${requestScope.composer.category}</td> |
| </tr> |
| </table> |
| |
| <p>Go back to <a href="index.html" class="link">application home</a>.</p> |
| </body> |
| </html></pre> |
| <p class="notes"><strong>Note.</strong> You will need to change the link to return to the index page |
| if your index page is <tt>index.jsp</tt>.</p> |
| </li> |
| <li>Create another JSP file in the project's Web Pages folder. Name the file <code>error.jsp</code>.</li> |
| <li>Replace the placeholder code in <code>error.jsp</code> with the following code: |
| <pre class="examplecode"><!DOCTYPE html> |
| |
| <html> |
| <head> |
| <link rel="stylesheet" type="text/css" href="stylesheet.css"> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <title>Seach Error</title> |
| </head> |
| <body> |
| <h2>Seach Error</h2> |
| |
| <p>An error occurred while performing the search. Please try again.</p> |
| |
| <p>Go back to <a href="index.html" class="link">application home</a>.</p> |
| </body> |
| </html></pre> |
| <p class="notes"><strong>Note.</strong> You will need to change the link to return to the index page |
| if your index page is <tt>index.jsp</tt>.</p> |
| </li> |
| </ol> |
| <h3 id="stylesheet">Attaching a Stylesheet</h3> |
| |
| <p>At this stage, you have completed all the code needed for the functionality of the application. |
| To see the results of your efforts, try running the application now.</p> |
| |
| <ol> |
| <li>In the Projects window, right-click the project node and choose Run. The project |
| is recompiled and deployed to the target server. Your browser opens, and you can |
| see the index page. |
| |
| <br> |
| <img src="../../../images_www/articles/73/web/ajax-intro/no-css.png" |
| alt="Application displayed in browser without stylesheet" class="margin-around b-all" |
| title="Successful deployment without stylesheet"></li> |
| </ol> |
| |
| <p>To add a stylesheet to your application, simply create a <code>.css</code> file |
| and link to it from your presentation page(s). When you work in <code>.css</code> files, |
| the IDE provides you with code completion support, as well as the following windows |
| to help you generate and edit stylesheet rules.</p> |
| |
| <ul> |
| <li><strong>CSS Styles window.</strong> The CSS Styles window enables you to edit the declarations |
| of rules for HTML elements and selectors in a CSS file.</li> |
| <li><strong>Create CSS Rules dialog box.</strong> The Create CSS Rule dialog box enables you to |
| create new rules in a CSS style sheet. </li> |
| <li><strong>Add CSS Property dialog box.</strong>The Add CSS Property dialog box enables you to |
| add declarations to a CSS rule in a style sheet by adding properties and values. </li> |
| </ul> |
| |
| <p>To add a stylesheet to your application perform the following steps.</p> |
| |
| <ol> |
| <li>In the Projects window, right-click the Web Pages node and choose New > Cascading |
| Style Sheet (If Cascading Style Sheet is not listed, choose Other. Then choose |
| Cascading Style Sheet from the Web category in the New File wizard.)</li> |
| |
| <li>In the CSS File Name text field, type <strong><code>stylesheet</code></strong>. |
| Click Finish. |
| <p>The new file is created and opens in the editor.</p></li> |
| |
| <li>Type the following rules in <code>stylesheet.css</code> in the editor. You can make use of |
| the IDE's code completion support by pressing Ctrl-Space at points when you want |
| to call up suggestions. |
| |
| <pre class="examplecode"> |
| body { |
| font-family: Verdana, Arial, sans-serif; |
| font-size: smaller; |
| padding: 50px; |
| color: #555; |
| width: 650px; |
| } |
| |
| h1 { |
| letter-spacing: 6px; |
| font-size: 1.6em; |
| color: #be7429; |
| font-weight: bold; |
| } |
| |
| h2 { |
| text-align: left; |
| letter-spacing: 6px; |
| font-size: 1.4em; |
| color: #be7429; |
| font-weight: normal; |
| width: 450px; |
| } |
| |
| table { |
| width: 550px; |
| padding: 10px; |
| background-color: #c5e7e0; |
| } |
| |
| td { |
| padding: 10px; |
| } |
| |
| a { |
| color: #be7429; |
| text-decoration: none; |
| } |
| |
| a:hover { |
| text-decoration: underline; |
| } |
| |
| .popupBox { |
| position: absolute; |
| top: 170px; |
| left: 140px; |
| } |
| |
| .popupCell { |
| background-color: #fffafa; |
| } |
| |
| .popupCell:hover { |
| background-color: #f5ebe9; |
| } |
| |
| .popupItem { |
| color: #333; |
| text-decoration: none; |
| font-size: 1.2em; |
| }</pre> |
| |
| </li> |
| <li>Open the CSS Styles window by choosing Window > Web > CSS Styles. |
| <br> |
| <img src="../../../images_www/articles/73/web/ajax-intro/css-styles-window.png" |
| alt="CSS Styles window displaying h1 rule properties" class="margin-around b-all" |
| title="CSS Styles window displaying h1 rule properties"> |
| |
| <p>You can use the CSS Styles window to quickly view the properties and edit |
| style rules. |
| When you select a rule in the upper pane of the CSS Style window |
| you can see the properties of the rule in the lower pane. |
| You can add a CSS Rules to the stylesheet by clicking the Edit CSS Rules icon |
| (<img src="../../../images_www/articles/73/web/ajax-intro/newcssrule.png" |
| alt="New CSS Property icon" title="New CSS Property icon">) |
| in the toolbar of the upper pane. |
| You can modify rules in the lower pane by editing the property sheet and |
| add properties by clicking the Add Property icon |
| (<img src="../../../images_www/articles/73/web/ajax-intro/newcssproperty.png" |
| alt="New CSS Property icon" title="New CSS Property icon">) |
| in the toolbar of the lower pane. |
| </li> |
| |
| <li>Switch to the index page in the Source Editor, and add a reference |
| to the stylesheet between the <code><head></code> tags. |
| |
| <pre class="examplecode"> |
| <link rel="stylesheet" type="text/css" href="stylesheet.css"></pre></li> |
| |
| |
| <li>Add the <code>popupBox</code> class that is defined in the stylesheet to the |
| <code>complete-table</code> element (changes in <strong>bold</strong>). |
| |
| <pre class="examplecode"> |
| <tr> |
| <td id="auto-row" colspan="2"> |
| <table id="complete-table" <strong>class="popupBox"</strong> /> |
| </td> |
| </tr></pre> |
| <p>You can use the code completion in the editor to help you select the |
| style rule that you want to apply to the selector.</p> |
| <img src="../../../images_www/articles/73/web/ajax-intro/css-completion.png" |
| alt="CSS code completion in the editor" class="margin-around b-all" |
| title="CSS code completion in the editor"> |
| |
| <p>As indicated in <code>stylesheet.css</code>, this rule positions the <code>complete-table</code> |
| element so that it displays slightly to the right of its parent element.</p></li> |
| </ol> |
| <p>When you save the index page the application is automatically redeployed to the server. |
| If the page is still open in your browser you can reload the page to see that the |
| page is now rendered according to the rules in the CSS stylesheet. </p> |
| </div> |
| |
| |
| <br> |
| <h2 id="run">Running the Project</h2> |
| |
| <p>When you run the application again, it displays in the browser using the stylesheet |
| you just created. Each time you type in a character, an asynchronous request is sent |
| to the server, and returned with XML data that has been prepared by <code>AutoCompleteServlet</code>. |
| As you enter more characters, the number of composer names decreases to reflect the new |
| list of matches.</p> |
| |
| |
| <h3 id="httpMonitor">Using the HTTP Server Monitor</h3> |
| |
| <p>You can use the IDE's HTTP Server monitor to verify the HTTP communication that takes place |
| as requests and responses are passed between the client and server. The HTTP Server Monitor |
| displays information such as client and server headers, session properties, cookie details, |
| as well as request parameters.</p> |
| |
| <p>Before you begin using the HTTP monitor, you must first enable it on the server you |
| are using.</p> |
| |
| <ol> |
| <li>Open the Servers window by choosing Tools > Servers from the main menu.</li> |
| |
| <li>In the left pane, select the server you are using with the project. Then, |
| in the right pane, select the Enable HTTP Monitor option. |
| <p class="notes"><strong>Note:</strong> This option displays under the Common tab |
| for the GlassFish server. For Tomcat, it resides under the Connection tab.</p></li> |
| <li>Click Close.</li> |
| </ol> |
| |
| <p class="alert">If the server is already running, you need to restart it in order to |
| allow changes to take effect. You can restart the server by opening the Services |
| window (Window > Services), then right-clicking your server beneath the Servers |
| node and choosing Restart.</p> |
| |
| <p>Now, when you run the application again, the HTTP monitor opens in the lower region |
| of the IDE. You can select a record in the left pane, then click the tabs in the |
| main window to view information concerning each request that is made.</p> |
| |
| <div class="indent"> |
| <img src="../../../images_www/articles/73/web/ajax-intro/http-monitor.png" |
| class="margin-around b-all" alt="HTTP Server monitor displays in the IDE" |
| title="HTTP Server monitor displays in the IDE" style="width:688px"></div> |
| |
| <p>You can verify the XML data that is sent from the server as a result of the asynchronous |
| request made when a user enters a character in the auto-complete field.</p> |
| |
| <ol> |
| <li>In the tree view on the left side of the HTTP monitor, right-click a request |
| record and choose Replay.</li> |
| </ol> |
| |
| <p>The response is generated in your browser. In this case, because the response |
| consists of XML data, the browser displays the data in it's native XML viewer.</p> |
| |
| <div class="indent"> |
| <img src="../../../images_www/articles/73/web/ajax-intro/xml-data.png" |
| class="margin-around b-all" alt="HTTP Server monitor displays in the IDE" |
| title="HTTP Server monitor displays in the IDE" style="width:688px"></div> |
| |
| |
| <h3 id="conclusion">Conclusion</h3> |
| |
| <p>This concludes the Introduction to Ajax. Hopefully by now you realize that Ajax is simply |
| exchanging information over HTTP in the background, and updating that page dynamically based |
| on the results.</p> |
| |
| <p>You may note that the application you built has numerous shortcomings, for example nothing |
| happens when a composer name is selected from the auto-complete box! You are welcome to |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaScript%252FMyAjaxApp.zip">download |
| the solution project</a> to see how this can be implemented using JSP technology. Furthermore, |
| you might want to investigate server-side validation that prevents a user from requesting a |
| name that does not exist in the data store. You can learn more about these techniques and |
| technologies by following other tutorials on the |
| <a href="../../trails/java-ee.html">Java EE & Java Web Learning Trail</a>.</p> |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback:%20Introduction%20to%20Ajax%20(Java)">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <h2 id="seeAlso">See Also</h2> |
| |
| <p>For more information about Ajax and Java technology on <a href="https://netbeans.org/">netbeans.org</a>, |
| see the following resources:</p> |
| |
| <ul> |
| <li><a href="../../docs/web/js-toolkits-jquery.html">Using jQuery to Enhance the Appearance |
| and Usability of a Web Page</a>. Demonstrates how to integrate jQuery core and UI |
| libraries into a NetBeans project.</li> |
| |
| <li><a href="../../docs/web/js-toolkits-dojo.html">Connecting a Dojo Tree to an ArrayList |
| using JSON</a>. Based on a JavaOne Hands-On Lab, this document shows how to implement |
| a Dojo Tree widget into a web page and enable the server-side to respond to Tree |
| requests in JSON format.</li> |
| |
| <li><a href="http://www.oracle.com/pls/topic/lookup?ctx=nb8000&id=NBDAG2272">Creating JavaScript Files</a> in <i>Developing Applications with NetBeans IDE</i>.</li> |
| |
| <li><a href="quickstart-webapps-wicket.html">Introduction to the Wicket Web Framework</a>. |
| An introduction to creating reusable components and applying them to a web application |
| using the Wicket framework.</li> |
| |
| |
| |
| </ul> |
| |
| </body> |
| </html> |