You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2010/09/02 14:37:24 UTC

svn commit: r991917 - in /click/trunk/click/documentation/xdocs/src: docbook/click/chapter-ajax.xml docbook/click/click-book.xml images/ajax/ images/ajax/ajax-class-diagram.png images/ajax/ajax-request-sequence-diagram.png

Author: sabob
Date: Thu Sep  2 12:37:24 2010
New Revision: 991917

URL: http://svn.apache.org/viewvc?rev=991917&view=rev
Log:
added Ajax chapter

Added:
    click/trunk/click/documentation/xdocs/src/docbook/click/chapter-ajax.xml
    click/trunk/click/documentation/xdocs/src/images/ajax/
    click/trunk/click/documentation/xdocs/src/images/ajax/ajax-class-diagram.png   (with props)
    click/trunk/click/documentation/xdocs/src/images/ajax/ajax-request-sequence-diagram.png   (with props)
Modified:
    click/trunk/click/documentation/xdocs/src/docbook/click/click-book.xml

Added: click/trunk/click/documentation/xdocs/src/docbook/click/chapter-ajax.xml
URL: http://svn.apache.org/viewvc/click/trunk/click/documentation/xdocs/src/docbook/click/chapter-ajax.xml?rev=991917&view=auto
==============================================================================
--- click/trunk/click/documentation/xdocs/src/docbook/click/chapter-ajax.xml (added)
+++ click/trunk/click/documentation/xdocs/src/docbook/click/chapter-ajax.xml Thu Sep  2 12:37:24 2010
@@ -0,0 +1,821 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<chapter id="chapter-ajax" remap="h1">
+  <title>Ajax</title>
+
+  <sect1 id="ajax-overview" remap="h2">
+    <title>Ajax Overview</title>
+
+  <para>Ajax is a method of using JavaScript to perform a GET or POST request
+and return a result without reloading the whole page.
+  </para>
+
+  <para>For an introduction on Ajax please see the following articles:</para>
+
+  <itemizedlist>
+    <listitem>
+      <para><ulink url="http://www.w3schools.com/Ajax/default.asp">http://www.w3schools.com/Ajax/default.asp</ulink></para>
+    </listitem>
+
+    <listitem>
+      <para><ulink url="http://en.wikipedia.org/wiki/AJAX">http://en.wikipedia.org/wiki/AJAX</ulink></para>
+    </listitem>
+  </itemizedlist>
+
+  <para>Ajax is a client-side technology for creating interactive web applications.
+  The JavaScript <literal>XMLHttpRequest</literal> object is used to perform GET
+  and POST requests and the server can send back a response that can be processed
+  in the browser.
+  </para>
+
+  <para>Click on the other hand is a server-side technology that can handle and
+  process incoming Ajax requests and send a response back to the browser.
+  </para>
+
+  <para><emphasis role="bold">Please note:</emphasis> Click is responsible
+  for handling server-side requests. It is up to you to develop the client-side
+  logic necessary to make the Ajax request, process the server response
+  and handle errors. Fortunately this step is quite easy since Click is a
+  stateless framework and Page URLs are obvious and transparent.
+  </para>
+
+  <para>It is also possible to write custom Behaviors (covered later) that renders
+  the client-side code necessary to initiate Ajax requests and handle Ajax responses
+  and errors. In fact once you become familiar Click's Ajax handling, you will
+  likely create custom Behaviors to streamline and encapsulate your client-side
+  code.
+  </para>
+
+  <para><emphasis role="bold">Also note:</emphasis> Click doesn't care what
+  client-side technology you use. You can use pure JavaScript or one of the
+  popular JavaScript libraries such as:
+  <ulink url="http://www.jquery.com">jQuery</ulink>,
+  <ulink url="http://www.prototypejs.org/">Prototype</ulink>,
+  <ulink url="http://mootools.net/">MooTools</ulink> to name a few.
+  </para>
+
+  <para>In this chapter we'll look at the Ajax support provided by Click. There
+  are two basic ways to handle and process Ajax requests:
+  </para>
+
+  <itemizedlist>
+    <listitem>
+      <para><link linkend="ajax-behaviors">Ajax Behaviors</link> - a Behavior
+      can change how a Control behave at runtime, allowing the Control to handle
+      and process Ajax requests. Behaviors are added to Controls through
+      <ulink url="../../click-api/org/apache/click/control/AbstractControl.html#addBehavior(org.apache.click.Behavior)">AbstractControl.addBehavior()</ulink>
+      </para>
+    </listitem>
+
+    <listitem>
+      <para><link linkend="ajax-page-action">Page Actions</link> - Page Actions
+      was covered <link linkend="page-actions">earlier</link> and provides a
+      popular way to handle and process Ajax requests
+      </para>
+    </listitem>
+  </itemizedlist>
+
+  </sect1>
+
+  <sect1 id="ajax-behaviors" remap="h2">
+    <title>Ajax Behaviors</title>
+
+    <para><ulink url="../../click-api/org/apache/click/Behavior.html">Behaviors</ulink>
+    can change how Controls behave at runtime. The default Behavior implementation,
+    <ulink url="../../click-api/org/apache/click/ajax/AjaxBehavior.html">AjaxBehavior</ulink>,
+    can be added to a Control, enabling that control to handle, process and respond
+    to Ajax requests.
+    </para>
+
+    <para>
+    Behaviors are added to controls through
+    <ulink url="../../click-api/org/apache/click/control/AbstractControl.html#addBehavior(org.apache.click.Behavior)">AbstractControl.addBehavior()</ulink>
+    and the same Behavior can be shared by multiple Controls.
+    </para>
+
+    <para>Behaviors provides an
+    <ulink url="../../click-api/org/apache/click/Behavior.html#onAction(org.apache.click.Control)">onAction</ulink>
+    method (similar to <classname>ActionListener</classname>) that is invoked to
+    handle and process the Ajax request. The <methodname>onAction</methodname>
+    method returns an <ulink url="../../click-api/org/apache/click/ActionResult.html">ActionResult</ulink>
+    containing the data rendered to the browser. In addition Behaviors provides
+    <literal>interceptor</literal> methods to decorate and enhance the Control.
+    </para>
+
+    <para>The <classname>Control</classname>,
+    <classname>Behavior</classname> and <classname>ActionResult</classname>
+    class is depicted in the figure below.
+    </para>
+
+    <figure id="ajax-behavior-class-diagram">
+      <title>Ajax Behavior Class Diagram</title>
+      <inlinemediaobject>
+        <imageobject>
+          <imagedata fileref="images/ajax/ajax-class-diagram.png" format="PNG" scale="65"/>
+        </imageobject>
+      </inlinemediaobject>
+    </figure>
+
+    <para>The Control contains a <classname>Set</classname> that holds the
+    <classname>Behaviors</classname> added to the <classname>Control</classname>.
+    The Control interface exposes the following methods for handling Ajax requests:
+    </para>
+
+    <itemizedlist>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/Control.html#getBehaviors()">getBehaviors()</ulink>
+          - returns the Control's Set of Behaviors
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/Control.html#hasBehaviors()">hasBehaviors()</ulink>
+          - returns true if the Control has any Behaviors.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/Control.html#isAjaxTarget(org.apache.click.Context)">isAjaxTarget()</ulink>
+          - Returns true if the control is the Ajax request <literal>target</literal>,
+          false otherwise. The <literal>Ajax target control</literal> is the Control
+          which <methodname>onProcess</methodname> method will be invoked. The most
+          common way to target a specific server side control is to give it an
+          <ulink url="../../click-api/org/apache/click/control/AbstractControl.html#setId(java.lang.String)">HTML ID</ulink>
+          attribute, that is then passed as an Ajax request parameter to the server.
+          More on this later.
+        </para>
+      </listitem>
+    </itemizedlist>
+
+    <para>The Behavior interface is covered next:
+    </para>
+
+    <itemizedlist>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/Behavior.html#onAction(org.apache.click.Control)">onAction()</ulink>
+          - the Behavior action method for handling Ajax requests.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/Behavior.html#isRequestTarget(org.apache.click.Context)">isRequestTarget()</ulink>
+          - determines whether the behavior is the request target or not. Click
+          will only invoke <methodname>onAction</methodname> if
+          <methodname>isRequestTarget()</methodname> returns true. This method
+          allows for fine grained control over the exection of the <methodname>onAction</methodname>
+          method.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/Behavior.html#preResponse(org.apache.click.Control)">preResponse()</ulink>
+          - defines an interceptor method that is invoked before the response is written.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/Behavior.html#preGetHeadElements(org.apache.click.Control)">preGetHeadElements()</ulink>
+          - defines an interceptor method that is invoked after <methodname>preResponse()</methodname>
+          but before the <classname>Control</classname> <methodname>getHeadElements()</methodname>
+          is called.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/Behavior.html#preDestroy(org.apache.click.Control)">preDestroy()</ulink>
+          - defines an interceptor method that is invoked before the
+          <classname>Control</classname> <methodname>onDestroy()</methodname>
+          event handler. This interceptor method allows the behavior to cleanup
+          any resources.
+        </para>
+      </listitem>
+    </itemizedlist>
+
+    <para>The <classname>Behavior</classname> provides an <methodname>onAction</methodname>
+    method for handling Ajax requests. The <methodname>onAction</methodname>
+    method returns an <classname>ActionResult</classname> containing the data that
+    is rendered to the browser.
+    </para>
+
+    <para>The <methodname>isRequestTarget</methodname> method controls whether or
+    not the <methodname>onAction</methodname> method should be invoked.
+    <methodname>isRequestTarget()</methodname> is typically used to target the
+    Behavior for specific JavaScript events. For example a Behavior might only
+    handle <literal>onclick</literal> or <literal>onblur</literal> JavaScript events.
+    For this to work the client-side code initiating the Ajax request should pass
+    the JavaScript event to the server.
+    </para>
+
+    <para>The <classname>Behavior</classname> also provides a number of interceptor
+    methods for specific <classname>Control</classname> life cycle events. These
+    interceptor methods can be implemented to process and decorate the control or
+    its children.
+    </para>
+
+    <para>Lastly the <classname>ActionResult</classname> methods are shown below:
+    </para>
+
+    <itemizedlist>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/ActionResult.html#setContent(java.lang.String)">setContent(String)</ulink>
+          - set the String content to render to the browser
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/ActionResult.html#setBytes(byte[])">setBytes(byte[])</ulink>
+          - set the byte array to render to the browser
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/ActionResult.html#setBytes(byte[])">setTemplate(String)</ulink>
+          - set the name of the Velocity (or Freemarker) template to render to
+          the browser
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/ActionResult.html#setModel(java.util.Map)">setModel(Map)</ulink>
+          - set the Velocity (or Freemarker) template model
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <ulink url="../../click-api/org/apache/click/ActionResult.html#setModel(java.util.Map)">setModel(Map)</ulink>
+          - set the ActionResult content type, for example: <literal>text/html</literal>,
+          <literal>text/xml</literal>, <literal>application/json</literal> etc.
+        </para>
+      </listitem>
+    </itemizedlist>
+
+    <para>An ActionResult is returned by the Behavior <methodname>onAction</methodname>
+    method and contains the data to render to the browser. ActionResult can return
+    any response to the browser: String, byte array or a template.
+    </para>
+
+  </sect1>
+
+  <sect1 id="ajax-behavior-execution" remap="h2">
+    <title>Ajax Behavior Execution</title>
+
+    <para>The execution sequence for an <classname>Ajax Behavior</classname>
+    being processed and rendered is illustrated in the figure below. You'll note
+    that it is similar to a normal HTTP request flow. The main differences are that
+    Ajax requests do not have an onGet or onRender event. Another difference
+    is that only the <literal>Ajax target Control</literal> is processed.
+    </para>
+
+    <figure id="ajax-behavior-sequence-diagram">
+      <title>Ajax Behavior Sequence Diagram</title>
+      <inlinemediaobject>
+        <imageobject>
+          <imagedata fileref="images/ajax/ajax-request-sequence-diagram.png" format="PNG" scale="58"/>
+        </imageobject>
+      </inlinemediaobject>
+    </figure>
+
+    <para>Stepping through this Ajax GET request sequence, first a new Page
+    instance is created.
+    </para>
+
+    <para>Then the <methodname>onSecurityCheck()</methodname> handler is executed
+    to authorize access to the page, and if necessary abort further processing.
+    If the request is aborted for an Ajax request, no response is rendered to
+    the browser. If you want to render a response you need to write to the
+    <classname>HttpServletResponse</classname> directly or create and
+    render an <classname>ActionResult</classname> yourself.
+    </para>
+
+    <para>The next method invoked is <methodname>onInit()</methodname> to initialize,
+    create and setup controls and <classname>Behaviors</classname>.
+    <methodname>onInit</methodname> is an ideal place to add <classname>Behaviors</classname>
+    to <classname>Controls</classname>. When a Behavior is added to a Control that
+    Control is automatically registered with the ClickServlet as a potential
+    <literal>Ajax target control</literal>.
+    </para>
+
+    <para>The next step is to find and process the <literal>Ajax target control</literal>.
+    First the ClickServlet needs to determine which Control is the Ajax target.
+    To resolve the target Control the ClickServlet iterates over all the registered
+    Controls and invokes each Control's method: <methodname>isAjaxTarget()</methodname>.
+    The first control which isAjaxTarget() returns true will be resolved as the
+    Ajax target. The most common way for a Control to be resolved as the Ajax
+    target is to check if its ID attribute is passed as a request parameter. It
+    is then up the client-side JavaScript code that initiated the Ajax request
+    to ensure the Control ID is sent as part of the Ajax request. Note, if the
+    ClickServlet cannot find a target control, no response is rendered.
+    </para>
+
+    <para>If an Ajax target control is found, the ClickServlet will invoke
+    that control's <methodname>onProcess</methodname> method. Other controls are not
+    processed. It is important to note that processing a control for an Ajax request
+    has the same requirements as processing a control for a non-Ajax request.
+    In other words, in addition to the Control ID (or other identifier), the Ajax
+    request must send all the parameters normally expected by the target Control
+    and its children. For example, a Field expects it's <literal>name/value</literal>
+    parameter while an ActionLink expects its <literal>actionLink/name</literal>
+    parameter.
+    </para>
+
+    <para>Next, the target control <classname>Behaviors</classname> are fired.
+    The ClickServlet iterates over the control Behaviors and for each
+    Behavior invoke the method: <methodname>isRequestTarget()</methodname>. Each
+    Behavior which <methodname>isRequestTarget</methodname> method returns true
+    will have their <methodname>onAction</methodname> method invoked to handle
+    the Ajax request. The Behavior <methodname>onAction</methodname> method
+    returns an <classname>ActionResult</classname> that is rendered to the browser.
+    </para>
+
+    <para>Please note: multiple Behaviors can handle the Ajax request, however
+    only the first ActionResult returned will be rendered to the browser. If an
+    onAction method returns null, the ActionResult from the next Behavior onAction
+    method will be used. If all onAction methods returns null, no response is
+    rendered.
+    </para>
+
+    <para>Next the ActionResult is rendered to the browser.</para>
+
+    <para>The final step in this sequence is invoking each control's onDestroy()
+    method and lastly invoke the Page's onDestroy() method.</para>
+  </sect1>
+
+  <sect1 id="first-ajax-example" remap="h2">
+    <title>First Ajax Example</title>
+
+    <para>In this first example we demonstrate how to handle Ajax requests with an
+    <symbol>AjaxBehavior</symbol>. AjaxBehavior is the default implementation of
+    the <classname>Behavior</classname> interface. Below we show the Page class,
+    <classname>AjaxBehaviorPage.java</classname>, and how an
+    <symbol>AjaxBehavior</symbol> is added to an ActionLink called link with an
+    HTML ID <varname>link-id</varname>. The AjaxBehavior <varname>onAction</varname>
+    method will be invoked to handle the Ajax request. The <varname>onAction</varname>
+    method returns an <token>ActionResult</token> that is rendered to the browser.
+    </para>
+
+    <programlisting language="java">public class AjaxBehaviorPage extends BorderPage {
+
+    private static final long serialVersionUID = 1L;
+
+    private ActionLink link = new ActionLink("link", "here");
+
+    public AjaxBehaviorPage() {
+        link.setId("link-id"); <co id="co-link-id" linkends="ca-link-id"/>
+
+        addControl(link);
+
+        // Add an Ajax behavior to the link. The behavior will be invoked when the
+        // link is clicked.
+        link.addBehavior(new <symbol>AjaxBehavior()</symbol> { <co id="co-ajax-behavior" linkends="ca-ajax-behavior"/>
+
+            @Override
+            public <token>ActionResult</token> <varname>onAction</varname>(Control source) { <co id="co-ajax-behavior-method" linkends="ca-ajax-behavior-method"/>
+
+                // Formatted date instance that will be added to the
+                String now = format.currentDate("MMM, yyyy dd HH:MM:ss");
+
+                String msg = "AjaxBehavior &lt;tt&gt;onAction()&lt;/tt&gt; method invoked at: " + now;
+
+                // Return an action result containing the message
+                return new <token>ActionResult</token>(msg, ActionResult.HTML); <co id="co-ajax-action-result" linkends="ca-ajax-action-result"/>
+            }
+        });
+    }
+} </programlisting>
+
+    <calloutlist>
+      <callout arearefs="co-link-id" id="ca-link-id">
+        <para>We assign to the ActionLink the HTML ID: <varname>link-id</varname>.
+        The ID will be used to identify the ActionLink as the
+        <literal>Ajax target control</literal>. The client-side JavaScript code
+        is expected to send this ID as an Ajax request parameter.
+        </para>
+      </callout>
+      <callout arearefs="co-ajax-behavior" id="ca-ajax-behavior">
+        <para>Next we add an <symbol>AjaxBehavior</symbol> to the ActionLink.
+        Adding a Behavior to a control will also register that control as a
+        potential <literal>Ajax target control</literal>.
+        </para>
+      </callout>
+      <callout arearefs="co-ajax-behavior-method" id="ca-ajax-behavior-method">
+        <para>We also implement the Behavior <varname>onAction</varname> method
+        in order to handle the Ajax request.
+        </para>
+      </callout>
+      <callout arearefs="co-ajax-action-result" id="ca-ajax-action-result">
+        <para>Lastly we return an <token>ActionResult</token> containing HTML
+        content that is rendered to the browser.
+        </para>
+      </callout>
+    </calloutlist>
+
+    <para>Next we show the Page template <literal>ajax-behavior.htm</literal>,
+    containing the client-side JavaScript code that will initiate an Ajax request.
+    </para>
+
+    <para><emphasis role="bold">Please note:</emphasis> we assume you are familiar
+    with basic JavaScript skills. In this example we use the <ulink url="http://www.jquery.com">jQuery</ulink>
+    JavaScript library, but any other library can be used, even raw JavaScript.
+    Also see the online Click examples for more Ajax examples.
+    </para>
+
+    <programlisting language="javascript">&lt;!-- // $link is a Velocity reference that will render an ActionLink at runtime. --&gt;
+Click $link to call the server using Ajax.
+
+&lt;div id="result"&gt;
+    &lt;!-- // Ajax response will be set here --&gt;
+&lt;/div&gt;
+
+&lt;!-- // JavaScript code below --&gt;
+
+&lt;!-- // Import the jQuery library --&gt;
+&lt;script type="text/javascript" src="$context/js/jquery.js"&gt;&lt;/script&gt;
+
+&lt;!-- // The client-side JavaScript for initiating an Ajax request --&gt;
+&lt;script type="text/javascript"&gt;
+    // This example uses jQuery for making Ajax requests:
+
+    // Register a function that is invoked as soon as the entire DOM has been loaded
+    jQuery(document).ready(function() { <co id="co-ajax-jq-function" linkends="ca-ajax-jq-function"/>
+
+        // Register a 'click' handler that makes an Ajax request
+        jQuery("#link-id").click(function(event){
+            // Make ajax request
+            makeRequest();
+
+            // Prevent the default browser behavior of navigating to the link
+            return false;
+        })
+    })
+
+    function makeRequest() {
+        // Get a reference to the link
+        var link = jQuery('#link-id');
+
+        // In order for Click to identify the Ajax target, we pass the link ID
+        // attribute as request parameters
+        var extraData = link.attr('id') + '=1'; <co id="co-ajax-link-id" linkends="ca-ajax-link-id"/>
+
+        // The Ajax URL is set to the link 'href' URL which contains all the link default parameters, including it's name/value pair: 'actionLink=link'
+        var url = link.attr('href'); <co id="co-ajax-jq-href" linkends="ca-ajax-jq-href"/>
+
+        jQuery.get(url, extraData, function(data) {
+            // 'data' is the response returned from the server
+
+            // We update the div with the ID 'result' and set its content to the server response
+            jQuery("#result").html("&lt;p&gt;" + data + "&lt;/p&gt;"); <co id="co-ajax-jq-response" linkends="ca-ajax-jq-response"/>
+        });
+    }
+&lt;/script&gt; </programlisting>
+
+    <calloutlist>
+        <callout arearefs="co-ajax-jq-function" id="ca-ajax-jq-function">
+        <para>We start off with a jQuery <ulink url="http://api.jquery.com/ready/">ready</ulink>
+        function that is executed as soon as the browser DOM has been loaded.
+        This ensures that the function body is executed <literal>before</literal>
+        the page images are downloaded, which leads to a more responsive GUI.
+        </para>
+      </callout>
+      <callout arearefs="co-ajax-link-id" id="ca-ajax-link-id">
+        <para>Next is an important step. We need to pass the link <varname>HTML ID</varname>
+        attribute as request parameters in order for the server to identify <literal>which</literal>
+        server-side control is the <literal>Ajax target</literal>. We use the jQuery
+        <literal>attr</literal> function to lookup the link's <varname>HTML ID</varname>
+        attribute. Click does not care about <literal>value</literal> of the
+        parameter, so we pass in a value of <varname>1</varname>, but any other
+        value could be used.
+        </para>
+      </callout>
+      <callout arearefs="co-ajax-jq-href" id="ca-ajax-jq-href">
+        <para>Next step is also important. We can't just pass in the Control HTML ID.
+        Although the HTML ID identifies which Control is the target control, that
+        only instructs Click to process the control. The Control <methodname>onProcess</methodname>
+        method is where the Control values are bound, validated and action event
+        is fired. So what is needed is to pass all the parameters normally expected
+        by the ActionLink <methodname>onProcess</methodname> method. In the case
+        of ActionLink, that means the Ajax request must include it's <varname>href</varname>
+        parameters. The easiest way to do this is to use jQuery to set the Ajax
+        <literal>URL</literal> to the ActionLink <varname>href</varname> value.
+        </para>
+      </callout>
+      <callout arearefs="co-ajax-jq-response" id="ca-ajax-jq-response">
+        <para>Lastly TODO
+        </para>
+      </callout>
+    </calloutlist>
+
+    <sect2 id="ajax-trace-log" remap="h3">
+      <title>Ajax Trace Log</title>
+
+      <para>Looking at the output log we see the following trace:
+      </para>
+
+      <literallayout>[Click] [debug] GET http://localhost:8080/mycorp/ajax/ajax-behavior.htm
+[Click] [trace]    <symbol>is Ajax request</symbol>: <varname>true</varname>
+[Click] [trace]    request param: <varname>actionLink=link</varname>
+[Click] [trace]    request param: <varname>link-id=1</varname>
+[Click] [trace]    invoked: AjaxBehaviorPage.&lt;&lt;init&gt;&gt;
+[Click] [trace]    invoked: AjaxBehaviorPage.onSecurityCheck() : true
+[Click] [trace]    invoked: AjaxBehaviorPage.onInit()
+[Click] [trace]    invoked: 'link' ActionLink.onInit()
+[Click] [trace]    <token>the following controls have been registered as potential Ajax targets:</token>
+[Click] [trace]       ActionLink: name='link'
+[Click] [trace]    invoked: 'link' ActionLink.<symbol>isAjaxTarget()</symbol> : <varname>true</varname> (target Ajax control found)
+[Click] [trace]    invoked: 'link' ActionLink.<symbol>onProcess()</symbol> : <varname>true</varname>
+[Click] [trace]    <token>processing Behaviors for control: 'link' ActionLink</token>
+[Click] [trace]       invoked: AjaxBehaviorPage.1.<symbol>isRequestTarget()</symbol> : <varname>true</varname>
+[Click] [trace]       invoked: AjaxBehaviorPage.1.<symbol>onAction()</symbol> : <varname>ActionResult</varname> (ActionResult will be rendered)
+[Click] [info ]    <token>renderActionResult</token> (text/html) - 0 ms
+[Click] [trace]    invoked: 'link' ActionLink.onDestroy()
+[Click] [trace]    invoked: AjaxBehaviorPage.onDestroy()
+[Click] [info ] handleRequest:  /ajax/ajax-behavior.htm - 68 ms</literallayout>
+
+      <para>First thing we notice is that the request is recognized as an
+      <symbol>Ajax request</symbol>.
+      </para>
+
+      <para>We can also see from the log that the Ajax request sent the parameters,
+      <varname>link-id=1</varname> and <varname>actionLink=link</varname> to the server.
+      <varname>link-id</varname> is the ActionLink HTML ID attribute that will be used
+      to identify the Control as the <literal>Ajax request target</literal>.
+      </para>
+
+      <para>Next the log prints which controls have been registered as <literal>potential
+      Ajax targets</literal>. In our example we added a Behavior to the ActionLink
+      so the ActionLink is registered as an Ajax target.
+      </para>
+
+      <para>Next the ActionLink#<symbol>isAjaxTarget</symbol> was invoked and because
+      it returned <varname>true</varname>, ActionLink will be set as the
+      <literal>Ajax target control.</literal>
+      </para>
+
+      <para>Having found the <literal>Ajax target</literal>, the ActionLink
+      <symbol>onProcess</symbol> is called.
+      </para>
+
+      <para>Next, the log shows it found the <literal>target Behavior</literal>.
+      by invoking Behavior#<symbol>isRequestTarget</symbol> method, which
+      also returned <varname>true</varname>.
+      </para>
+
+      <para>The Behavior#<symbol>onAction</symbol> is invoked which returns an
+      <varname>ActionResult</varname>.
+      </para>
+
+      <para>Finally the <varname>ActionResult</varname> is rendered to the browser.
+      </para>
+    </sect2>
+
+    <sect2 id="ajax-trace-log-no-target-control" remap="h3">
+      <title>Ajax Trace Log - No Ajax Target Control Found</title>
+
+      <para>Below we show a log trace where no <literal>Ajax target control</literal>
+      is found. The most common reason that can happen is if the JavaScript code
+      that initiates the Ajax request does not send the necessary request parameters
+      to identify the <literal>Ajax target control</literal>. Another common reason
+      is if no Behavior was added to a Control.
+      </para>
+
+      <literallayout>[Click] [debug] GET http://localhost:8080/mycorp/ajax/ajax-behavior.htm
+[Click] [trace]    <symbol>is Ajax request</symbol>: <varname>true</varname>
+[Click] [trace]    request param: <varname>actionLink=link</varname>
+[Click] [trace]    invoked: AjaxBehaviorPage.&lt;&lt;init&gt;&gt;
+[Click] [trace]    invoked: AjaxBehaviorPage.onSecurityCheck() : true
+[Click] [trace]    invoked: AjaxBehaviorPage.onInit()
+[Click] [trace]    invoked: 'link' ActionLink.onInit()
+[Click] [trace]    <token>the following controls have been registered as potential Ajax targets:</token>
+[Click] [trace]       ActionLink: name='link'
+[Click] [trace]    <symbol>*no*</symbol> target control was found for the Ajax request
+[Click] [trace]    invoked: 'link' ActionLink.onDestroy()
+[Click] [trace]    invoked: AjaxBehaviorPage.onDestroy()
+[Click] [info ] handleRequest:  /ajax/ajax-behavior.htm - 87 ms</literallayout>
+
+      <para>Notice from the log that the only Ajax request parameters sent was
+      <varname>actionLink=link</varname>.
+      </para>
+
+      <para>Next the log prints which controls have been registered as <literal>potential
+      Ajax targets</literal>. In our example we added a Behavior to the ActionLink
+      so the ActionLink is registered as an Ajax target.
+      </para>
+
+      <para>Next we see that <symbol>*no*</symbol> Ajax target control was found.
+      The reason is because the ActionLink ID attribute, <literal>link-id</literal>,
+      does not match the incoming request parameter, <literal>actionLink=link</literal>,
+      hence the ActionLink was not identified as the <literal>Ajax request target</literal>
+      and no response is rendered.
+      </para>
+    </sect2>
+
+    <sect2 id="ajax-trace-log-no-target-behavior" remap="h3">
+      <title>Ajax Trace Log - No Target Behavior Found</title>
+
+      <para>Below we show a log trace where a no <literal>target behavior</literal>
+      is found. The reason this can happen is if the <symbol>isRequestTarget</symbol>
+      of the <classname>Behaviors</classname> added to the Control returns false.
+      </para>
+
+      <literallayout>[Click] [debug] GET http://localhost:9999/mycorp/ajax/ajax-behavior.htm
+[Click] [trace]    <symbol>is Ajax request</symbol>: <varname>true</varname>
+[Click] [trace]    request param: <varname>actionLink=link</varname>
+[Click] [trace]    request param: <varname>link-id=1</varname>
+[Click] [trace]    invoked: AjaxBehaviorPage.&lt;&lt;init&gt;&gt;
+[Click] [trace]    invoked: AjaxBehaviorPage.onSecurityCheck() : true
+[Click] [trace]    invoked: AjaxBehaviorPage.onInit()
+[Click] [trace]    invoked: 'link' ActionLink.onInit()
+[Click] [trace]    the following controls have been registered as potential Ajax targets:
+[Click] [trace]       ActionLink: name='link'
+[Click] [trace]    invoked: 'link' ActionLink.isAjaxTarget() : true (target Ajax control found)
+[Click] [trace]    invoked: 'link' ActionLink.onProcess() : true
+[Click] [trace]    <token>processing Behaviors for control: 'link' ActionLink</token>
+[Click] [trace]       invoked: AjaxBehaviorPage.1.<symbol>isRequestTarget()</symbol> : <varname>false</varname>
+[Click] [trace]    <symbol>*no*</symbol> target behavior found for <varname>'link' ActionLink</varname> - invoking Behavior.isRequestTarget() returned false for all behaviors
+[Click] [trace]    invoked: 'link' ActionLink.onDestroy()
+[Click] [trace]    invoked: AjaxBehaviorPage.onDestroy()
+[Click] [info ] handleRequest:  /ajax/ajax-behavior.htm - 80 ms
+      </literallayout>
+
+      <para>We can see from the log that the Ajax request sent the parameters,
+      <varname>link-id=1</varname> and <varname>actionLink=link</varname> to the server.
+      </para>
+
+      <para>Next we notice that the Behavior <symbol>isRequestTarget()</symbol>
+      returned <varname>false</varname>.
+      </para>
+
+      <para>Finally we see that <symbol>*no*</symbol> target behavior was found
+      for the <literal>Ajax target control</literal> <varname>'link' ActionLink</varname>.
+      </para>
+    </sect2>
+
+  </sect1>
+
+  <sect1 id="ajax-page-action" remap="h2">
+    <title>Ajax Page Action</title>
+
+    <para>Page Actions are page methods that can be invoked directly from the
+    browser. So instead of handling the Ajax request with a Control, the request
+    is handled with a page method. Like Behaviors, page methods returns an
+    ActionResult containing the Ajax data rendered to the browser.
+    </para>
+
+    <para>Page Actions have already been covered earlier. Please click
+    <link linkend="page-actions">here</link> for a detailed discussion.
+    </para>
+
+    <para>Using a Page Action for handling an Ajax request is no different from
+    a normal HTTP request. To invoke a Page Action, specify the parameter
+    <varname>"pageAction"</varname> and the name of the page method eg:
+    <symbol>"onLinkClicked"</symbol>.
+    </para>
+
+    <para>Here is an example using the
+    <ulink url="http://www.jquery.com">jQuery</ulink> JavaScript library to make
+    an Ajax request to a Page Action:
+    </para>
+
+<programlisting language="javascript">jQuery('#some-link-id').click(function() {
+
+  // The page url
+  var url = '$context/view-customers.htm';
+
+  // Specify the pageAction parameter and page method to invoke: 'onLinkClicked'
+  var extraData = 'pageAction=<symbol>onLinkClicked</symbol>';
+
+  // Perform the Ajax request
+  jQuery.get(url, extraData, function(response) {
+
+    // Update the target element with the server response
+    jQuery("#target").html("&lt;p&gt;" + response + "&lt;/p&gt;");
+  });
+
+}); </programlisting>
+
+  <para>The JavaScript snippet above will send a request to the
+  <classname>ViewCustomerPage</classname> method <symbol>"onLinkClicked"</symbol>,
+  which returns an <token>ActionResult</token> instance:
+  </para>
+
+  <programlisting language="java">public class ViewCustomerPage extends Page {
+
+    ...
+
+    public <token>ActionResult</token> <symbol>onLinkClicked()</symbol> {
+        // Formatted date instance that will be returned to the browser
+        String now = format.currentDate("MMM, yyyy dd HH:MM:ss");
+
+        String msg = "PageAction method &lt;tt&gt;onLinkClicked()&lt;/tt&gt; invoked at: " + now;
+
+        // Return an action result containing the message
+        return new <token>ActionResult</token>(msg, ActionResult.HTML);
+    }
+} </programlisting>
+
+    <para>The <token>ActionResult</token> contains the data that is rendered to the
+    client browser. In the example above, the action result is an HTML snippet with
+    today's date.
+    </para>
+
+  </sect1>
+
+  <sect1 id="ajax-response-types" remap="h2">
+    <title>Ajax Response Types</title>
+
+    <para>The most common server response types are:
+    </para>
+
+    <itemizedlist>
+      <listitem>
+        <para>HTML</para>
+      </listitem>
+      <listitem>
+        <para>XML</para>
+      </listitem>
+      <listitem>
+        <para>JSON</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>Click Controls render themselves as XHTML markup so can be used in
+    either XML or HTML responses.
+    </para>
+
+    <para>Here is an example showing how to return different types of responses:</para>
+
+    <programlisting language="java">public class ViewCustomerPage extends Page {
+
+    ...
+
+    public void onInit() {
+        Behavior htmlBehavior = new AjaxBehavior() {
+            public ActionResult onAction() {
+                String html = "&lt;h1&gt;Hello world&lt;/h1&gt;";
+
+                // Return an HTML snippet
+                return new ActionResult(html, ActionResult.HTML);
+            }
+        };
+        htmlLink.addBehavior(htmlBehavior);
+
+        ...
+
+        Behavior xmlBehavior = new AjaxBehavior() {
+            public ActionResult onAction() {
+                String xml = "&lt;payload&gt;Hello world&lt;/payload&gt;";
+
+                // Return an XML snippet
+                return new ActionResult(xml, ActionResult.XML);
+            }
+        };
+        xmlLink.addBehavior(xmlBehavior);
+
+        ...
+
+        Behavior jsonBehavior = new AjaxBehavior() {
+            public ActionResult onAction() {
+                String json = "{\"value\": \"Hello world\"}";
+
+                // Return an JSON snippet
+                return new ActionResult(json, ActionResult.JSON);
+            }
+        };
+        jsonLink.addBehavior(jsonBehavior);
+    }
+} </programlisting>
+
+  </sect1>
+
+  <sect1 id="ajax-error-handling" remap="h2">
+    <title>Ajax Error Handling</title>
+
+    <para>If an exception occurs while processing an Ajax request and the application
+    is in <literal>development</literal> mode, the exception
+    <literal>stackTrace</literal> is returned to the browser.
+    </para>
+    <para>If an exception occurs while processing an Ajax request and the application
+    is in <literal>production</literal> mode, a simple error message is returned.
+    </para>
+
+  </sect1>
+</chapter>

Modified: click/trunk/click/documentation/xdocs/src/docbook/click/click-book.xml
URL: http://svn.apache.org/viewvc/click/trunk/click/documentation/xdocs/src/docbook/click/click-book.xml?rev=991917&r1=991916&r2=991917&view=diff
==============================================================================
--- click/trunk/click/documentation/xdocs/src/docbook/click/click-book.xml (original)
+++ click/trunk/click/documentation/xdocs/src/docbook/click/click-book.xml Thu Sep  2 12:37:24 2010
@@ -4,6 +4,7 @@
     <!ENTITY chapter-introduction SYSTEM "chapter-introduction.xml" >
     <!ENTITY chapter-pages SYSTEM "chapter-pages.xml" >
     <!ENTITY chapter-controls SYSTEM "chapter-controls.xml" >
+    <!ENTITY chapter-ajax SYSTEM "chapter-ajax.xml" >
     <!ENTITY chapter-configuration SYSTEM "chapter-configuration.xml" >
     <!ENTITY chapter-best-practices SYSTEM "chapter-best-practices.xml" >
     ]>
@@ -55,6 +56,7 @@
   &chapter-introduction;
   &chapter-pages;
   &chapter-controls;
+  &chapter-ajax;
   &chapter-configuration;
   &chapter-best-practices;
 

Added: click/trunk/click/documentation/xdocs/src/images/ajax/ajax-class-diagram.png
URL: http://svn.apache.org/viewvc/click/trunk/click/documentation/xdocs/src/images/ajax/ajax-class-diagram.png?rev=991917&view=auto
==============================================================================
Binary file - no diff available.

Propchange: click/trunk/click/documentation/xdocs/src/images/ajax/ajax-class-diagram.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: click/trunk/click/documentation/xdocs/src/images/ajax/ajax-request-sequence-diagram.png
URL: http://svn.apache.org/viewvc/click/trunk/click/documentation/xdocs/src/images/ajax/ajax-request-sequence-diagram.png?rev=991917&view=auto
==============================================================================
Binary file - no diff available.

Propchange: click/trunk/click/documentation/xdocs/src/images/ajax/ajax-request-sequence-diagram.png
------------------------------------------------------------------------------
    svn:mime-type = image/png