Ajax|web
Page overloading presents one of the biggest usability hurdles in Web application development and is a major challenge for Java development. In this series, the author Philip McCarthy introduces the experience of creating dynamic Web applications through a background channel approach.
Ajax (asynchronous JavaScript and XML) is a combination of Java technology, XML, and JavaScript programming techniques that allow you to build Java-based Web applications and break the practice of using page overloading.
Ajax, asynchronous JavaScript and XML, is a Web application development method that uses client script to exchange data with a Web server. This way, Web pages can be updated dynamically without interrupting the interactive process. With Ajax, you can create a direct, highly available, richer, more dynamic Web user interface that is close to local desktop applications.
Ajax is not a technology, it's more like a pattern-a way of labeling and describing useful design techniques. It's a new sensation for many developers who just got to know it, but all the components that implement Ajax have existed for many years.
The current buzz is due to the fact that there were some very dynamic WebUI based on Ajax in the 2004 and 2005, especially Google's Gmail and maps apps, and Flickr, a photo-sharing site. These UIs fully use the backend channels, also known as "Web 2.0" by some developers, and have led to a spike in interest in AJAX applications.
In this series, I'll give you all the tools you need to develop your own AJAX applications. In this first article, I'll explain the concept behind Ajax, demonstrating the basic steps of creating an Ajax interface for web-based application systems. I'll use the sample code to demonstrate the server-side Java code and client JavaScript script that implements the Ajax dynamic interface. Finally, I'll point out some of the errors that are easy to make in Ajax methods and the wide range of usability and accessibility issues you should consider when creating AJAX applications.
a better shopping cart
You can use Ajax to enhance your traditional Web applications by eliminating page loads to make your interactions smoother. In order to demonstrate it, I will use a simple, dynamically updated item to add to the shopping cart. Combined with an online store, this method allows us to continue browsing and picking items into our shopping cart without waiting for the page overload to be clicked.
Although the code in this article is for shopping cart examples, the techniques shown here can be used in other AJAX applications. The HTML code used by the shopping cart sample is shown in Listing 1. In the entire article, I will refer to these HTML code.
AJAX Processing Process
An AJAX interaction begins with a JavaScript object called XMLHttpRequest. As the name implies, it allows a client script to execute the HTTP request and will parse an XML-formatted server response. The first step in the AJAX process is to create a XMLHttpRequest instance. Use the HTTP method (get or post) to process the request and set the target URL to the XMLHttpRequest object.
Now, remember how Ajax is first in the asynchronous processing state? When you send an HTTP request, you do not want the browser to hang up and wait for the server to respond, instead, you want to continue to interact with the user's interface through the page and process them after the server response has actually arrived.
To do this, you can register a callback function with XMLHttpRequest and distribute XMLHttpRequest requests asynchronously. Control is immediately returned to the browser, and the callback function is invoked when the server response arrives.
On a Java Web server, the request to arrive is the same as any other httpservletrequest. After parsing the request parameter, the servlet executes the required application logic, serializes the response into the XML, and writes it back to HttpServletResponse.
Back to the client, the callback function registered on the XMLHttpRequest is now invoked to process the XML document returned by the server. Finally, by updating the user interface to respond to server data transfer, use JavaScript to manipulate the HTML DOM of the page. Figure 1 is a sequential diagram of the AJAX processing process.
Figure 1:ajax Processing Process
Now, you should have a high-level view of the AJAX process. I'll go into every step of the way to look at the more detailed content. If you can't find your location, look back at Figure 1, plus-because of the asynchronous nature of the Ajax method, the timeline diagram is not straight forward.
sends a xmlhttprequest
I'll start at the beginning of the Ajax timeline: Create and send a XMLHttpRequest from the browser. Unfortunately, the method of creating XMLHttpRequest in different browsers is not the same. The JavaScript functions of the example in Listing 2 eliminate these browser-related problems, properly detect the methods associated with the current browser, and return a xmlhttprequest that can be used. It's best to look at it as a fallback code and simply copy it to your JavaScript library and use it when you need a xmlhttprequest.
List 2: Create a XMLHttpRequest across browsers
/** returns a new XMLHttpRequest object. If not supported by the browser * / function newxmlhttprequest() {var xmlreq = false; if (window. XMLHttpRequest) {/ / creates XMLHttpRequest object xmlreq = new xmlhttprequest();} else if (window. Activexobject) {/ / creates XMLHttpRequest try through MS ActiveX{ //Try to create xmlreq = new activexobject ("msxml2. Xmlhttp");} catch (E1) {/ / failed to create the requested ActiveX object try {/ / try to create xmlreq = new activexobject ("Microsoft. Xmlhttp") according to the old Internet Explorer method; }Catch (E2) {/ / XMLHttpRequest}}} return xmlreq;} cannot be created through ActiveX
Later, I'll discuss some tips on how to treat browsers that don't support xmlhttpreauest. Now, the example function shown in Listing 2 will always return a xmlhttpreauest instance.
Back in the shopping cart example scenario, I would invoke an AJAX interaction whenever the user clicked the Add to Cart button for a directory entry. The onclick function named AddToCart () is responsible for updating the status of the shopping cart through an Ajax call, as shown in Listing 1.
in Listing 3, the first thing that AddToCart () does is to get an instance of a XMLHttpRequest by calling the Newxmlhttpreauest function (shown in Listing 2). and register a callback function to accept the server response (which I will explain later in detail, see Listing 6).
Because, this request will modify the server state, and I will use an HTTP post to handle it. It takes three steps to deliver data via post: First, I need to open a post connection to the server resource for the communication--in the case of a server-side servlet with a URL mapped to cart.do.
Next, set the header information for the XMLHttpRequest to flag the requested content as form-encoded. Finally, the form-encoded data is used as the body of the request and the request is sent. These steps are shown centrally in Listing 3.
List 3: Send a add to cart XMLHttpRequest
/** add an entry * itemcode - the product code of the entry to be added * / function addtocart (itemcode) {/ / get an XMLHttpRequest instance var req = newxmlhttprequest(); / / set the handle function var handlerfunction = getreadystatehandler (req, updatecart); req.onrea to receive callback notifications from the request object Dystatechange = handlerfunction; / / open an HTTP post connection to the shopping cart servlet / / the third parameter indicates that the request is asynchronous req.open ("post", "cart. Do", true); / / indicates that the request body contains the form data req.setrequestheader ("content type", "application / x-www-form-urlencoded"); / / the sending flag needs to be added to the form encd of the item in the shopping cart Ed data req.send ("action = add & item =" + itemcode);}
With the above, you can learn the first part of the AJAX process-creating and sending HTTP requests on the client side. The next step is the Java servlet code that is used to process the request.
servlet Request processing
handling XMLHttpRequest with a servlet is essentially similar to processing an ordinary HTTP request from a browser. You can obtain the form-encoded data that is passed by the POST request body by calling Httpservletrequest.getparameter (). The
Ajax request is also part of the same httpsession session process as the ordinary Web request sample. This is 肜 for the shopping cart example, because we can save the state of multiple requests through a session to the same JavaBean shopping cart object and serialize it.
Listing 4 is a snippet of code that handles AJAX requests and updates a simple servlet for a shopping cart. Retrieves a cart Bean from a user session and updates it with the requested parameters. The cart bean is serialized to XML after
and is written back to Servletrespone. Note that you must set the type of the response content to Application/xml, otherwise XMLHttpRequest will not be able to resolve the response content to an XML DOM.
Listing 4: servlet code to handle AJAX requests
Public void dopost (HttpServletRequest req, httpservletresponse) throws java.io.ioexception {cart cart = getcartfromsession (req); string action = req.getparameter ("action"); string item = req.getparameter ("item"); if ((action! = null) & (item! = null)) {/ / add or remove an entry if ("add". Equals (action)) {cart. Addite M (item);} else if ("remove". Equals (action)) {cart. Removeitems (item);} / / serialize the shopping cart status to XML string cartxml = cart. Toxml(); / / write the XML to response. Res.setcontenttype ("application / XML"); res.getwriter(). Write (cartxml);}
Listing 5 shows the XML generated by the Cart.toxml () method. Notice the property of the generated cart element, which is a timestamp generated by System.currenttimemillis ().
List 5:cart The XML that the object serializes
<?xml version="1.0"?><cart generated="1123969988414" total="$171.95"> <item code="hat001"> <name>Hat</name> <quantity>2</quantity> </item> <item code="cha001"> <name>Chair</name> <quantity>1</quantity> </item> <item code="dog001"> <name>Dog</name> <quantity>1</quantity> </item></cart>
If you look at the Cart.java in the sample application source provided by the download site, you will see that it generates XML by simply appending strings. For this example, it's enough, and I'll introduce some better methods in the next installment of this system article.
Now you know how Cartservlet responds to a xmlhttprequest. The next step is to return to the client and update the page status with the server response.
the ReadyState property of a server response
XMLHttpRequest through JavaScript is a numeric value that gives the state of the request lifecycle. It changes from 0 that represents "uninitialized" to 4 that represents "completed." Each time the readystate changes, a ReadyStateChange event is raised, and the callback handler function is invoked through the onReadyStateChange property.
in Listing 3, you have seen a handler function created by calling the function Getreadystatehandler () and configured to the onReadyStateChange property. Getreadystatehandler () uses the fact that a function is the primary object in JavaScript.
This means that a function can be passed as a parameter to another function, and other functions can be created and returned. Getreadystatehandler () to do is to return a function to check whether Xmlhttprequet has finished processing and to pass the XML server to respond to the handler function specified by the caller. Listing 6 is the code for Getreadystatehandler ().
List 6: function Getreadystatehandler ()
/** returns a function that waits for the specified XMLHttpRequest * to complete, then passes its XML response to the given handler function. * req - the XMLHttpRequest whose state is changing * responsexmlhandler - function to pass the XML response to * / function getreadystatehandler (req, responsexmlhandler) {/ / returns a listener xmlhttprequests T instance's anonymous function return function() {/ / if the request status is "complete" (req. ReadyState = = 4) {/ / check whether the server response if (req. Status = = 200) has been received successfully {/ / pass the XML containing the response information to the processing function responsexmlhandler (req. Responsexml);} else {/ / there is an HTTP problem Generate alert ("HTTP error:" + req. Status);}}}}}}
HTTP status Code
In Listing 6, the Status property of the XMLHttpRequest is tested to determine whether the request completed successfully. When dealing with a simple get and post request, you can assume that an error is indicated as long as it is not a state of (OK). If the server sends a redirect response (for example, 301 or 302), the browser transparently completes the redirection and obtains the appropriate resource from the new location; XMLHttpRequest will not see the redirect status code.
At the same time, the browser automatically adds a cache control: Use the No-cache header for all XMLHttpRequest so that the client code does not have to process the 304 (not-modified) response.
about Getreadystatehandler ()
Getreadystatehandler () is a relatively complex piece of code, especially if you are not familiar with reading JavaScript. The compromise is to include this function in your JavaScript library, and you can simply handle the AJAX server response without paying attention to the internal details of the XMLHttpRequest. It is important for you to understand how to use Getreadystatehandler () in your code.
In Listing 3, you see that Getreadystatehandler () is called:
Handlerfunction=getreadystatehandler (Req,updatecart) |
The
function returned by it will check whether the XMLHttpRequest in the REQ variable has completed and invoke the callback method specified by Updatecart to handle the response XML. The code in Updatecart () is shown in
extract Shopping cart data
Listing 7. This function uses the DOM to parse the shopping cart XML document and updates the Web page (see Listing 1) to reflect the new shopping cart content. Note the call to the XML DOM used to extract the data. The property that is generated on the
cart element, the timestamp generated when serialized, and is detected to ensure that no old data is overwritten with the new cart data. Ajax requests are inherently asynchronous, and this detection can effectively avoid interference with server responses that arrive outside the process.
Listing 7: Updating the page to reflect the contents of the shopping cart XML document
Function updatecart (cartxml) {/ / get the root element "cart" var cart = cartxml. GetElementsByTagName ("cart") [0]; / / ensure that this document is the latest var generated = cart. Getattribute ("generated"); if (generated > lastartupdate) {lastartupdate = generated; / / clear the HTML list to display the shopping cart content var contents = document. GetElement Ntbyid ("cart contents"); contents. InnerHTML = ""; / / cycle through items in the cart var items = cart.getelementsbytagname ("item"); for (VaR I = 0; I < items. Length; I + +) {var item = items [i]; / / extract text nodes var name = item.getelementsbytagname ("name") [0]. Firstchild. NodeValue; VAR Quan Tity = item. GetElementsByTagName ("quantity") [0]. Firstchild. NodeValue; / / create and add an entry to the HTML list var Li = document. CreateElement ("Li"); Li. AppendChild (document. CreateTextNode (name + "X" + quantity)); contents. AppendChild (Li);}} / / update the cumulative amount of the cart document. Getelementbyid ("total"). InnerHTML = cart getAttribute("total");}
By now, the tutorial on the AJAX process is over, and perhaps you want to run the application and see how it actually works. This example is very simple and has a lot of room for improvement. For example, I included code to remove entries from the shopping cart in the server-side code, but there was no way to access it from the client UI. As an exercise, try to actually do this function on the basis of existing JavaScript.
The challenge of using Ajax
As with any technology, using AJAX can be a mistake in quite a number of ways. The issues I am discussing here are currently lacking solutions and will be resolved or improved as Ajax matures. With the development of AJAX application experience, the developer community will have the best practice experience and guidelines.
Effectiveness of XMLHttpRequest
One of the biggest problems that Ajax developers face is how to react when XMLHttpRequest is unavailable. Although most modern browsers support XMLHttpRequest, there are a small number of users whose browsers do not support it, or prevent the use of XMLHttpRequest because of browser security settings.
If your Web application is posted on an intranet within your company, you will probably be able to specify which browsers to support and make sure that XMLHttpRequest is available. If you publish on the public Web, you have to realize that by assuming that XMLHttpRequest is available, it prevents users from using your system, such as old browsers, handheld browsers, and so on.
However, you should make every effort to ensure that the application system is "degraded properly" and that the system retains functionality for browsers that do not support XMLHttpRequest. In the shopping cart example, the best way to do this is to have an add to cart button that allows for regular submission and refreshes the page to reflect changes in the status of the cart.
Ajax XMLHttpRequest can be added to the page by JavaScript when the page is loaded, with the JavaScript handler function for each add to cart button only if it is available. Another approach is to detect xmlhttprequest when a user logs on, and then decide whether to provide an AJAX version or a regular form-submitted version.
Usability Considerations
Most of the problems surrounding AJAX applications are common problems. For example, it is important for users to know that their input has been registered and processed, because the usual funnel-rotation cursors are not available during XMLHttpRequest processing. One way is to replace the text on the "Confirm" button with the "in update ..." To prevent users from clicking the button more than once while waiting for a response.
Another problem is that users may not notice that the page they are viewing has been updated. You can use a variety of visual techniques to draw the user's vision to the updated area of the page. Another problem is that the AJAX update page interrupts the browser "back to Front" button, the URL in the address bar does not reflect the full state of the page, and cannot use the bookmark function. See the articles on the Web site addresses listed in the resource section to learn more about usability issues with AJAX applications.
Server Load
Using an Ajax interface instead of a traditional form-based interface can dramatically increase the number of requests delivered to the server. For example, a common Google search causes a hit to the server and occurs when the user confirms the search form. However, Google suggest will try to automatically complete your search terms and send multiple requests to the server when the user is typing.
When developing an AJAX application, be aware of how many requests you will send to the client side, and the server's load metrics. You can mitigate load pressure by caching requests appropriately on the client and responding to the server. You should also try to process more logic on the client when designing AJAX applications, rather than communicating with the server side.
Processing Asynchronous
It's important to remember that nothing can guarantee that XMLHttpRequest will end up in the order in which they are sent. In fact, when you're designing a system, you should always assume that they don't end in the same order. In the shopping cart example, a last-updated timestamp is used to ensure that the latest data is not overwritten.
This very basic approach can work in a shopping cart scenario, but may not work in other situations. At design time consider how you should handle asynchronous server responses.
Conclusions
You should now have a good understanding of the fundamentals of Ajax and, in addition, you should understand some of the more advanced design issues that come with Ajax methods. Creating a successful AJAX application requires a range of approaches-from JavaScript UI design to server-side architecture-but you should now have the AJAX core knowledge you need to use.