click-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sa...@apache.org
Subject svn commit: r736438 [2/2] - in /incubator/click/trunk/tools/docbook/src/docbook/click: chapter-best-practices.xml chapter-configuration.xml chapter-controls.xml chapter-pages.xml
Date Wed, 21 Jan 2009 22:10:26 GMT
Modified: incubator/click/trunk/tools/docbook/src/docbook/click/chapter-controls.xml
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/docbook/src/docbook/click/chapter-controls.xml?rev=736438&r1=736437&r2=736438&view=diff
==============================================================================
--- incubator/click/trunk/tools/docbook/src/docbook/click/chapter-controls.xml (original)
+++ incubator/click/trunk/tools/docbook/src/docbook/click/chapter-controls.xml Wed Jan 21 14:10:25 2009
@@ -1,10 +1,629 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<chapter id="chapter-controls">
+<?xml version='1.0' encoding='UTF-8'?>
+  <chapter id="chapter-controls" remap="h1">
     <title>Controls</title>
+    <para> Click provides a rich set of Controls which support client side rendering and server side processing. This section covers the following topics: </para>
+    <orderedlist>
+      <listitem>
+        <para><link linkend="anchor-control-interface">Control Interface</link>  - describes the Control interface</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="anchor-control-callback">Control Callback</link>  - control event callback pattern</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="anchor-control-class">Control Classes</link>  - control Java classes</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="anchor-message-properties">Message Properties</link>  - control message properties</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="anchor-container">Container</link>  - a Container is a Control that can contain other Controls.</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="anchor-layout">Layouts</link>  - describes layout options and how to create custom layouts.</para>
+      </listitem>
+    </orderedlist>
+    <para> </para>
+    <para> While this section provides an overview how Controls work please see the <ulink url="click-api/org/apache/click/control/package-summary.html">Javadoc</ulink>, which provides extensive information and examples. <anchor id="anchor-control-interface"/><indexterm>
+        <primary>control-interface</primary>
+      </indexterm>
+</para>
+    <sect1 id="section-control-interface" remap="h2">
+      <title>1.  Control Interface</title>
+      <para> Controls provide the server side components that process user input, and render their display to the user. Controls are equivalent to Visual Basic Controls or Delphi Components. Controls handle the processing of user input in the <ulink url="click-api/org/apache/click/Control.html#onProcess()">onProcess</ulink> method and render their HTML display using the toString() method. The execution sequence for a Control being processed and rendered is illustrated below in Figure 1. <inlinemediaobject>
+          <imageobject>
+            <imagedata fileref="images/controls/control-post-sequence-diagram.png" format="PNG"/>
+          </imageobject>
+        </inlinemediaobject>
+	  </para>
+      <para><emphasis role="bold">Figure 1.   Post Sequence Diagram</emphasis> - created with Enterprise Architect courtesy <ulink url="http://www.sparxsystems.com.au">Sparx Systems</ulink></para>
+      <para> In Click all control classes must implement the <ulink url="click-api/org/apache/click/Control.html">Control</ulink> interface. The Control interface is depicted below in Figure 2. </para>
+      <para>
+        <inlinemediaobject>
+          <imageobject>
+            <imagedata fileref="images/controls/control-class-diagram.png" format="PNG"/>
+          </imageobject>
+        </inlinemediaobject>
+      </para>
+      <para><emphasis role="bold">Figure 2.   Control Interface Diagram</emphasis> - created with Enterprise Architect courtesy <ulink url="http://www.sparxsystems.com.au">Sparx Systems</ulink></para>
+      <para> Methods on the Control interface include: </para>
+      <itemizedlist>
+        <listitem>
+          <para><ulink url="click-api/org/apache/click/Control.html#getHtmlImports()">getHtmlImports()</ulink> - defines the controls HTML header imports.</para>
+        </listitem>
+        <listitem>
+          <para><ulink url="click-api/org/apache/click/Control.html#getMessages()">getMessages()</ulink> - defines the controls localized messages map.</para>
+        </listitem>
+        <listitem>
+          <para><ulink url="click-api/org/apache/click/Control.html#getName()">getName()</ulink> / <ulink url="click-api/org/apache/click/Control.html#setName(java.lang.String)">setName()</ulink>   -   defines the controls name in the Page model or Form fields.</para>
+        </listitem>
+        <listitem>
+          <para><ulink url="click-api/org/apache/click/Control.html#getParent()">getParent()</ulink> / <ulink url="click-api/org/apache/click/Control.html#setParent(java.lang.Object)">setParent()</ulink>   -   defines the controls parent.</para>
+        </listitem>
+        <listitem>
+          <para><ulink url="click-api/org/apache/click/Control.html#onDeploy(javax.servlet.ServletContext)">onDeploy()</ulink> - deploy resources on startup.</para>
+        </listitem>
+        <listitem>
+          <para><ulink url="click-api/org/apache/click/Control.html#onInit()">onInit()</ulink> - on initialize event handler.</para>
+        </listitem>
+        <listitem>
+          <para><ulink url="click-api/org/apache/click/Control.html#onProcess()">onProcess()</ulink> - process request event handler.</para>
+        </listitem>
+        <listitem>
+          <para><ulink url="click-api/org/apache/click/Control.html#onDestroy()">onDestroy()</ulink> - on destroy event handler.</para>
+        </listitem>
+        <listitem>
+          <para><ulink url="click-api/org/apache/click/Control.html#render(org.apache.click.util.HtmlStringBuffer)">render()</ulink> - generate the control&apos;s HTML representation.</para>
+        </listitem>
+      </itemizedlist>
+      <para>
+        <anchor id="anchor-control-callback"/>
+      </para>
+      <indexterm>
+        <primary>control-callback</primary>
+      </indexterm>
+    </sect1>
+    <sect1 id="section-control-callback" remap="h2">
+      <title>2.  Control Callback</title>
+      <para> Click Controls provide an event callback mechanism similar to a java.awt.ActionListener callback. Click supports two styles of action listeners, the first is using the ActionListener interface which provides compile time safety. The second is to register the action listener via the setListener(Object, String) method where you specify the call back method via its name. This second style uses less lines of code, but has no compile time safety. Examples of these two action listener styles are provided below: <programlisting>
+public class ActionDemo extends BorderPage {
 
-    <section id="section-control-interface">
-        <title>Control Interface</title>
+    // Uses listener style 1
+    public ActionLink link = new ActionLink();
 
-    </section>
+    // Uses listener style 2
+    public ActionButton button = new ActionButton();
+
+    public ActionDemo() {
+
+        // Verbose but provides compile time safety
+        link.setActionListener(new ActionListener() {
+            public boolean onAction(Control source) {
+                return onLinkClick(source);
+            }
+        });
+
+        // Succinct but typos will cause runtime errors
+        button.setListener(this, &quot;onButtonClick&quot;);
+    }
+
+    // Event Handlers --------------------------------------------------------- 
+
+    public boolean onLinkClick(Control source) {
+        ..
+        return true;
+    }
+
+    public boolean onButtonClick() {
+        ..
+        return true;
+    }
+}
+</programlisting> All call back listener methods must return a boolean value. If they return true the further processing of other controls and page methods should continue. Otherwise if they return false, then any further processing should be aborted. By returning false you can effectively exit at this point and redirect or forward to another page. This execution logic is illustrated in the <ulink url="pages.html#activity-diagram">Page Execution Activity Diagram</ulink>. Being able to stop further processing and do something else can be very handy. For example your Pages onRender() method may perform an expensive database operation. By returning false in an event handler you can skip this step and render the template or forward to the next page. <anchor id="anchor-control-class"/><indexterm>
+          <primary>control-class</primary>
+        </indexterm>
+</para>
+    </sect1>
+    <sect1 id="section-control-classes" remap="h2">
+      <title>3.  Control Classes</title>
+      <para> Core control classes are defined in the package <ulink url="click-api/org/apache/click/control/package-summary.html">org.apache.click.control</ulink>. This package includes controls for the essential HTML elements. Extended control classes are provided in the Click Extras package <ulink url="extras-api/org/apache/click/extras/control/package-summary.html">org.apache.click.extras.control</ulink>. Click Extras classes can contain dependencies to 3rd party frameworks. A subset of these control classes are depicted below in Figure 3. <inlinemediaobject>
+          <imageobject>
+            <imagedata fileref="images/controls/control-package-class-diagram.png" format="PNG"/>
+          </imageobject>
+        </inlinemediaobject>
+ <emphasis role="bold">Figure 3.   Package Class Diagram</emphasis> - created with Enterprise Architect courtesy <ulink url="http://www.sparxsystems.com.au">Sparx Systems</ulink></para>
+      <para> The key control classes include: <itemizedlist>
+          <listitem>
+            <para><ulink url="click-api/org/apache/click/control/ActionLink.html">ActionLink</ulink>  - provides an anchor link which can invoke callback listeners.</para>
+          </listitem>
+          <listitem>
+            <para><ulink url="click-api/org/apache/click/control/Field.html">Field</ulink>  - provides the abstract form field control.</para>
+          </listitem>
+          <listitem>
+            <para><ulink url="click-api/org/apache/click/control/Form.html">Form</ulink>  - provides a form control for processing, validation and rendering.</para>
+          </listitem>
+          <listitem>
+            <para><ulink url="click-api/org/apache/click/control/Submit.html">Submit</ulink>  - provides an input type submit control which can invoke callback listeners.</para>
+          </listitem>
+          <listitem>
+            <para><ulink url="click-api/org/apache/click/control/TextField.html">TextField</ulink>  - provides an input type text control which can invoke callback listeners.</para>
+          </listitem>
+        </itemizedlist>
+ The control classes are designed to support subclassing for customized behaviour. All control fields have protected visibility and have public accessor methods. You can also aggregate controls to build more complex controls. For example the <ulink url="extras-api/org/apache/click/extras/control/CreditCardField.html">CreditCardField</ulink> uses a <ulink url="click-api/org/apache/click/control/Select.html">Select</ulink> control to render the different credit card types. <anchor id="anchor-message-properties"/><indexterm>
+          <primary>message-properties</primary>
+        </indexterm>
+</para>
+    </sect1>
+    <sect1 id="section-message-properties" remap="h2">
+      <title>4.  Message Properties</title>
+      <para> Control strings for field validation messages and HTML formatting strings are externalized in the properties file. By using these properties files you can localize a Click application for your particular language and dialect. </para>
+      <sect2 id="section-message-resolution" remap="h3">
+        <title>4.1 Message Resolution</title>
+        <para> Messages are looked up in a particular order enabling taylor specific messages, for your controls, individual pages or across your entire application. The order in which localized messages are resolved is: <variablelist>
+            <varlistentry>
+              <term>4.1.1  Page scope messages</term>
+              <listitem>
+                <para>Message lookups are first resolved to the Page classes message bundle if it exists. For example a <literal>Login</literal> page may define the message properties: <programlisting>
+ /com/mycorp/page/Login.properties
+</programlisting> If you want to tailor messages for a particular page this is where to place them.</para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>4.1.2  Global page scope messages</term>
+              <listitem>
+                <para>Next message lookups are resolved to the global pages message bundle if it exists. <programlisting>
+ /click-page.properties
+</programlisting> If you want messages to be used across your entire application this is where to place them.</para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>4.1.3  Control scope messages</term>
+              <listitem>
+                <para>Next message lookups are resolved to the Control classes message bundle if it exists. For example a <literal>CustomTextField</literal> control may define the message properties: <programlisting>
+ /com/mycorp/control/CustomTextField.properties
+</programlisting></para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>4.1.4  Global control scope messages</term>
+              <listitem>
+                <para>Finally message lookups are resolved to the global application control message bundle if the message has not already been found. The global control properties file is: <programlisting>
+ /click-control.properties
+</programlisting></para>
+              </listitem>
+            </varlistentry>
+          </variablelist>
+</para>
+      </sect2>
+      <sect2 id="section-control-properties" remap="h3">
+        <title>4.2  Control Properties</title>
+        <para> To customize the <literal>click-control.properties</literal> simply add this file to your classpath and tailor the specific values. Note when customizing the message properties you must include all the properties, not just the ones you want to override. <programlisting>
+# Click Control messages
+field-maxlength-error={0} must be no longer than {1} characers
+field-minlength-error={0} must be at least {1} characters
+field-required-error=You must enter a value for {0}
+
+file-required-error=You must enter a filename for {0}
+
+label-required-prefix=
+label-required-suffix=&lt;span class=&quot;required&quot;&gt;*&lt;/span&gt;
+label-not-required-prefix=
+label-not-required-suffix=&amp;nbsp;
+
+not-checked-error=You must select {0}
+
+number-maxvalue-error={0} must not be larger than {1}
+number-minvalue-error={0} must not be smaller than {1}
+
+select-error=You must select a value for {0}
+
+table-first-label=First
+table-first-title=Go to first page
+table-previous-label=Prev
+table-previous-title=Go to previous page
+table-next-label=Next
+table-next-title=Go to next page
+table-last-label=Last
+table-last-title=Go to last page
+table-goto-title=Go to page
+table-page-banner=&lt;span class=&quot;pagebanner&quot;&gt;{0} items found, displaying {1} to {2}.&lt;/span&gt;
+table-page-banner-nolinks=
+  &lt;span class=&quot;pagebanner-nolinks&quot;&gt;{0} items found, displaying {1} to {2}.&lt;/span&gt;
+table-page-links=&lt;span class=&quot;pagelinks&quot;&gt;[{0}/{1}] {2} [{3}/{4}]&lt;/span&gt;
+table-page-links-nobanner=&lt;span class=&quot;pagelinks-nobanner&quot;&gt;[{0}/{1}] {2} [{3}/{4}]&lt;/span&gt;
+table-no-rows-found=No records found.
+
+table-inline-first-image=/click/paging-first.gif
+table-inline-first-disabled-image=/click/paging-first-disabled.gif
+table-inline-previous-image=/click/paging-prev.gif
+table-inline-previous-disabled-image=/click/paging-prev-disabled.gif
+table-inline-next-image=/click/paging-next.gif
+table-inline-next-disabled-image=/click/paging-next-disabled.gif
+table-inline-last-image=/click/paging-last.gif
+table-inline-last-disabled-image=/click/paging-last-disabled.gif
+table-inline-page-links=Page   {0} {1} {2} {3} {4}
+
+# Message displayed when a error occurs when the application is in &quot;production&quot; mode
+production-error-message=
+  &lt;div id=&apos;errorReport&apos; class=&apos;errorReport&apos;&gt;The application encountered an unexpected error.
+  &lt;/div&gt;
+</programlisting></para>
+      </sect2>
+      <sect2 id="section-accessing-messages" remap="h3">
+        <title>4.3  Accessing Messages</title>
+        <para> Field classes support a hierarchy of resource bundles for displaying validation error messages and display messages. These localized messages can be accessed through the Field methods: <itemizedlist>
+            <listitem>
+              <para>
+                <ulink url="click-api/org/apache/click/control/AbstractControl.html#getMessage(java.lang.String)">getMessage(String)</ulink>
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <ulink url="click-api/org/apache/click/control/AbstractControl.html#getMessage(java.lang.String,%20java.lang.Object)">getMessage(String, Object)</ulink>
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <ulink url="click-api/org/apache/click/control/AbstractControl.html#getMessage(java.lang.String,%20java.lang.Object[])">getMessage(String, Object[])</ulink>
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <ulink url="click-api/org/apache/click/control/AbstractControl.html#getMessages()">getMessages()</ulink>
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <ulink url="click-api/org/apache/click/control/Field.html#setErrorMessage(java.lang.String)">setErrorMessage(String)</ulink>
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <ulink url="click-api/org/apache/click/control/Field.html#setErrorMessage(java.lang.String,%20java.lang.Object)">setErrorMessage(String, Object)</ulink>
+              </para>
+            </listitem>
+          </itemizedlist>
+ These methods use the <literal>Locale</literal> of the request to lookup the string resource bundle, and use <literal>MessageFormat</literal> for any string formatting. <anchor id="anchor-container"/><indexterm>
+            <primary>container</primary>
+          </indexterm>
+</para>
+      </sect2>
+    </sect1>
+    <sect1 id="section-container" remap="h2">
+      <title>5.  Container</title>
+      <para>
+        <ulink url="click-api/org/apache/click/control/Container.html">Container</ulink>
+      </para>
+      <para> is a Control that can contain other Controls, thus forming a hierarchy of components. Container enables components to add, remove and retrieve other controls. Listed below are example Containers: <itemizedlist>
+          <listitem>
+            <para><ulink url="click-api/org/apache/click/control/Form.html">Form</ulink>  - an HTML form which provides default layout of fields and error feedback.</para>
+          </listitem>
+          <listitem>
+            <para><ulink url="click-api/org/apache/click/control/Panel.html">Panel</ulink>  - similar to <ulink url="click-api/org/apache/click/Page.html">Page</ulink>, this Container provides its own template and model.</para>
+          </listitem>
+          <listitem>
+            <para><ulink url="click-api/org/apache/click/control/FieldSet.html">FieldSet</ulink>  - draws a legend (border) around its child Controls.</para>
+          </listitem>
+        </itemizedlist>
+</para>
+      <para> These Containers are depicted below in Figure 4. <inlinemediaobject>
+          <imageobject>
+            <imagedata fileref="./../images/container-package-class-diagram.png" format="PNG"/>
+          </imageobject>
+        </inlinemediaobject>
+ <emphasis role="bold">Figure 4.   Containers Class Diagram</emphasis></para>
+      <para> The following classes provides convenient extension points for creating custom Containers: <itemizedlist>
+          <listitem>
+            <para>
+              <ulink url="click-api/org/apache/click/control/AbstractContainer.html">AbstractContainer</ulink>
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <ulink url="click-api/org/apache/click/extras/control/AbstractContainerField.html">AbstractContainerField</ulink>
+            </para>
+          </listitem>
+        </itemizedlist>
+ Lets cover each of them here. </para>
+      <sect2 remap="h3">
+        <title>5.1  AbstractContainer</title>
+        <para> Enables easy creation of custom Containers, for example an html <emphasis>div</emphasis> or <emphasis>span</emphasis> element: <programlisting>
+public class Div extends AbstractContainer {
+    
+    public Div(String name) {
+        super(name);
+    }
+
+    public String getTag() {
+        // Return the control&apos;s HTML tag.
+        return &quot;div&quot;;
+    }
+}
+</programlisting> Lets try out the newly created Container above: (note the MockContext used in this test is described in the <ulink url="mock-api/overview-summary.html">Mock Test Support</ulink> documentation) <programlisting>
+public class Test {
+    public static void main (String args[]) {
+        // Create mock context in which to test the container.
+        MockContext.initContext();
+
+        // Create a div instance called &quot;mydiv&quot;
+        String containerName = &quot;mydiv&quot;;
+        Div mydiv = new Div(containerName);
+        
+        // Add a control to the container
+        mydiv.add(new TextField(&quot;myfield&quot;));
+
+        System.out.println(mydiv);
+    }
+}
+</programlisting> Executing the above example results in the following output: <programlisting>
+&lt;div name=&quot;mydiv&quot; id=&quot;mydiv&quot;&gt;
+    &lt;input type=&quot;text&quot; name=&quot;myfield&quot; id=&quot;myfield&quot; value=&quot;&quot; size=&quot;20&quot; /&gt;
+&lt;/div&gt;
+</programlisting></para>
+      </sect2>
+      <sect2 id="section-abstractcontainerfield" remap="h3">
+        <title>5.2  AbstractContainerField</title>
+        <para> AbstractContainerField extends Field and implements the Container interface. This provides a convenient base class in case you run into a situation where you need both a Field and Container. Below is an example of how AbstractContainerField might be used: <programlisting>
+public class FieldAndContainer extends AbstractContainerField {
+
+    public FieldAndContainer(String name) {
+        super(name);
+    }
+
+    // Return the html tag to render
+    public String getTag() {
+        return &quot;div&quot;;
+    }
+}
+</programlisting> To test the new class we use the following snippet: <programlisting>
+public class Test {
+    public static void main (String args[]) {
+        // Create mock context in which to test the container.
+        MockContext.initContext();
+
+        // Create a FieldContainer instance called &quot;field_container&quot;
+        String containerName = &quot;field_container&quot;;
+        FieldAndContainer fieldAndContainer = new FieldAndContainer(containerName);
+        
+        // Add a couple of fields to the container
+        fieldAndContainer.add(new TextField(&quot;myfield&quot;));
+        fieldAndContainer.add(new TextArea(&quot;myarea&quot;));
+
+        System.out.println(fieldAndContainer);
+    }
+}
+</programlisting> Executing the snippet produces the output: <programlisting>
+&lt;div name=&quot;field_container&quot; id=&quot;field_container&quot;&gt;
+    &lt;input type=&quot;text&quot; name=&quot;myfield&quot; id=&quot;myfield&quot; value=&quot;&quot; size=&quot;20&quot;/&gt;
+    &lt;textarea name=&quot;myarea&quot; id=&quot;myarea&quot; rows=&quot;3&quot; cols=&quot;20&quot;&gt;&lt;/textarea&gt;
+&lt;/div&gt;
+</programlisting><anchor id="anchor-layout"/><indexterm>
+            <primary>layout</primary>
+          </indexterm>
+</para>
+      </sect2>
+    </sect1>
+    <sect1 id="section-layouts" remap="h2">
+      <title>6.  Layouts</title>
+      <para> Controls such as <ulink url="click-api/org/apache/click/control/Form.html">Form</ulink> takes care of layout and error reporting automatically, and for many use cases auto-layout is good enough. However for custom or complex layouts, Form is not always the best choice. There are two approaches for creating custom layouts. <itemizedlist>
+          <listitem>
+            <para> Template approach - use a template engine such as Velocity, Freemarker or JSP to declare the layout as HTML markup.</para>
+          </listitem>
+          <listitem>
+            <para> Programmatic approach - build custom layout components using Java. This option is very similar to building components using Swing.</para>
+          </listitem>
+        </itemizedlist>
+<anchor id="anchor-template-layout"/><indexterm>
+          <primary>template-layout</primary>
+        </indexterm>
+</para>
+      <sect2 remap="h3">
+        <title>6.1  Template layout</title>
+        <para> Taking the <ulink url="click-api/org/apache/click/control/Form.html#manual-layout">Template</ulink> approach works well and it separates the Page and layout logic. For example: <programlisting>
+// EmployeePage.java
+public EmployeePage extends Page {
+
+    private Form form;
+    
+    public void onInit() {
+        // Create form
+        Form form = new Form(&quot;form&quot;);
+        
+        // Add a couple of fields to the form
+        form.add(new TextField(&quot;firstname&quot;));
+        form.add(new TextField(&quot;lastname&quot;));
+        form.add(new IntegerField(&quot;age&quot;));
+        form.add(new DoubleField(&quot;salary&quot;));
+
+        // Add a submit button to form
+        form.add(new Submit(&quot;submit&quot;, &quot;Add Employee&quot;));
+
+        // Add form the page
+        addControl(form);
+    }
+}
+</programlisting> Lets imagine we want to create a layout using Div &lt;div&gt; and HTML List &lt;ol&gt; tags. We could provide the markup for the employee.htm template as shown below, using a template engine such as Velocity: <programlisting>
+&lt;!-- employee.htm --&gt;
+${form.startTag()}
+    &lt;div style=&quot;margin: 1em;&quot;&gt;
+        &lt;ol&gt;
+            &lt;li&gt;
+                &lt;label for=&quot;firstname&quot;&gt;Firstname:&lt;/label&gt;
+                ${form.fields.firstname}
+            &lt;/li&gt;
+            &lt;li&gt;
+                &lt;label for=&quot;lastname&quot;&gt;Lastname:&lt;/label&gt;
+                ${form.fields.lastname}
+            &lt;/li&gt;
+            &lt;li&gt;
+                &lt;label for=&quot;age&quot;&gt;Age:&lt;/label&gt;
+                ${form.fields.age}
+            &lt;/li&gt;
+            &lt;li&gt;
+                &lt;label for=&quot;salary&quot;&gt;Salary:&lt;/label&gt;
+                ${form.fields.salary}
+            &lt;/li&gt;
+        &lt;/ol&gt;
+    &lt;/div&gt;
+    ${form.fields.submit}
+${form.endTag()}
+</programlisting> Using a CSS stylesheet, the markup above can be styled and transformed into a fancy looking form. There are pros and cons to using the template approach. One of the advantages of the Template approach, is that the layout is explicit and one can easily tweak it if needed. For example instead of using divs and ordered lists, one can change the template to leverage a table layout. A disadvantage of the Template approach, is added redundancy. In the example above we created the fields in Java, and laid them out using markup in the template. If the requirements should change to add a new field for example, one will have to add the field in the Page as well as the template.  It is also possible to &quot;generify&quot; the layout using template engines. <ulink url="click-api/org/apache/click/control/Form.html#velocity-macros">Macro.vm</ulink> is an example of a generic form layout using Velocity.</para>
+        <para>
+          <anchor id="anchor-programmatic-layout"/>
+        </para>
+        <indexterm>
+          <primary>programmatic-layout</primary>
+        </indexterm>
+      </sect2>
+      <sect2 id="section-programmatic-layout" remap="h3">
+        <title>6.2  Programmatic layout</title>
+        <para> To combat the redundancy introduced by the Template approach, you can take a programmatic approach and use normal Java and some Click classes to build custom layouts. Click extras provides two useful classes in this situation namely, <ulink url="click-api/org/apache/click/extras/control/HtmlForm.html">HtmlForm</ulink> and <ulink url="click-api/org/apache/click/extras/control/HtmlFieldSet.html">HtmlFieldSet</ulink>. Unlike Form and FieldSet which renders its controls using a Table layout, HtmlForm and HtmlFieldSet renders its controls in the order they were added and does not add any extra markup. HtmlForm will be shown in the example below. When creating custom layouts, the HTML construct List &lt;ul&gt; is pretty useful. Since Click does not provide this component, lets create it as shown here: <programlisting>
+// HtmlList.java
+// Create a list &lt;ol&gt; html element, that accepts &lt;li&gt; elements as children
+public class HtmlList extends AbstractContainer {
+
+    public String getTag() {
+        return &quot;ol&quot;;
+    }
+
+    // Can only add ListItems: &lt;li&gt; tags
+    public Control add(Control control) {
+        if (!(control instanceof ListItem)) {
+            throw new IllegalArgumentException(&quot;Only list items can be added.&quot;);
+        }
+        return super.add(control);
+    }
+}
+</programlisting><programlisting>
+// ListItem.java
+// Create a listItem &lt;li&gt; element
+public class ListItem extends AbstractContainer {
+
+    public String getTag() {
+        return &quot;li&quot;;
+    }
+}
+</programlisting> Another component that will be used in the example below is a FieldLabel which renders an HTML label element for a specified Field. <programlisting>
+// FieldLabel.java
+// Create an html &lt;label&gt; element for a specified Field
+public class FieldLabel extends AbstractControl {
+
+    private Field target;
+
+    private String label;
+
+    public FieldLabel(Field target, String label) {
+        this.target = target;
+        this.label = label;
+    }
+
+    public String getTag() {
+        return &quot;label&quot;;
+    }
+
+    // Override render to produce an html label which produces:
+    // 
+Firstname:
+    public void render(HtmlStringBuffer buffer) {
+        // Open tag: &lt;label
+        buffer.elementStart(getTag());
+
+        // Set attribute to target field&apos;s id
+        setAttribute(&quot;for&quot;, target.getId());
+
+        // Render the labels attributes
+        appendAttributes(buffer);
+
+        // Close tag: &lt;label for=&quot;firstname&quot;&gt;
+        buffer.closeTag();
+
+        // Add label text: &lt;label for=&quot;firstname&quot;&gt;Firstname:
+        buffer.append(label);
+
+        // Close tag: &lt;label for=&quot;firstname&quot;&gt;Firstname:&lt;/label&gt;
+        buffer.elementEnd(getTag());
+    }
+
+}
+</programlisting> Now the form can be assembled. Continuing with the employee example from the <link linkend="anchor-template-layout">template approach</link>, we again create an EmployeePage, but this time an HtmlForm and HtmlList is used to create a custom layout: <programlisting>
+// EmployeePage.java
+public class EmployeePage extends Page {
+    // A form instance variable
+    private HtmlForm form;
+
+    // Build the form when the page is initialized
+    public void onInit() {
+        // Create an HtmlForm which is ideal for composing manual layouts
+        form = new HtmlForm(&quot;form&quot;);
+        
+        // Create a list and add it to the form. 
+        HtmlList list = new HtmlList();
+        form.add(list);
+        
+        // Add firstname field and pass in its name, label and the list to add the field to
+        addTextField(&quot;firstname&quot;, &quot;Firstname:&quot;, list);
+        addTextField(&quot;lastname&quot;, &quot;Lastname:&quot;, list);
+        addTextField(&quot;age&quot;, &quot;Age:&quot;, list);
+        addTextField(&quot;salary&quot;, &quot;Salary:&quot;, list);
+        
+        // Add a submit button to form
+        form.add(new Submit(&quot;submit&quot;, &quot;Add Employee&quot;));
+
+        // Add the form to the page
+        addControl(form);
+    }
     
+    // Provide a helper method to add fields to the form
+    private void addTextField(String nameStr, String labelStr, List list) {
+        // Create a new ListItem &lt;li&gt; and add it to the List
+        ListItem item = new ListItem();
+        list.add(item);
+
+        // Create a textfield with the specified name
+        Field field = new TextField(nameStr);
+        
+        // Create a field label, which associates the label with the field id.
+        // label.toString would output: &lt;label for=&quot;firstname&quot;&gt;Firstname:&lt;/name&gt;
+        FieldLabel label = new FieldLabel(field, labelStr);
+
+        // Next add the label and field to the list item.
+        // item.toString would then produce:
+        // &lt;li&gt;
+        //   &lt;label for=&quot;firstname&quot;&gt;Firstname:&lt;/name&gt;
+        //   &lt;input type=&quot;text&quot; name=&quot;firstname&quot; id=&quot;form_firstname&quot; value=&quot;&quot; size=&quot;20&quot;/&gt;
+        // &lt;/li&gt;
+        //
+        item.add(label);
+        item.add(field);
+    }
+}
+</programlisting> Now the employee.htm template would only need to specify the name of the top level component, in this case <emphasis>form</emphasis>. <programlisting>
+&lt;!--employee.htm--&gt;
+${form}
+</programlisting> which produces the following markup: <programlisting>
+&lt;!-- employee.htm --&gt;
+&lt;form method=&quot;post&quot; id=&quot;form&quot; action=&quot;/myapp/employee.htm&quot;&gt;
+&lt;input type=&quot;hidden&quot; name=&quot;form_name&quot; id=&quot;form_form_name&quot; value=&quot;form&quot;/&gt;
+    &lt;ol&gt;
+        &lt;li&gt;
+            &lt;label for=&quot;firstname&quot;&gt;Firstname:&lt;/label&gt;
+            &lt;input type=&quot;text&quot; name=&quot;firstname&quot; id=&quot;form_firstname&quot; value=&quot;&quot; size=&quot;20&quot;/&gt;
+        &lt;/li&gt;
+        &lt;li&gt;
+            &lt;label for=&quot;lastname&quot;&gt;Lastname:&lt;/label&gt;
+            &lt;input type=&quot;text&quot; name=&quot;lastname&quot; id=&quot;form_lastname&quot; value=&quot;&quot; size=&quot;20&quot;/&gt;
+        &lt;/li&gt;
+        &lt;li&gt;
+            &lt;label for=&quot;age&quot;&gt;Age:&lt;/label&gt;
+            &lt;input type=&quot;text&quot; name=&quot;age&quot; id=&quot;form_age&quot; value=&quot;&quot; size=&quot;20&quot;/&gt;
+        &lt;/li&gt;
+        &lt;li&gt;
+            &lt;label for=&quot;salary&quot;&gt;Salary:&lt;/label&gt;
+            &lt;input type=&quot;text&quot; name=&quot;salary&quot; id=&quot;form_salary&quot; value=&quot;&quot; size=&quot;20&quot;/&gt;
+        &lt;/li&gt;
+    &lt;/ol&gt;
+    &lt;input type=&quot;submit&quot; name=&quot;submit&quot; id=&quot;form_submit&quot; value=&quot;Add Employee&quot;/&gt;
+&lt;/form&gt;
+</programlisting> Again using a CSS stylesheet, the markup above can be styled and transformed into a fancy looking form. There is a <ulink url="http://www.avoka.com/click-examples/form/contact-details.htm">live demo</ulink> showing the programmatic approach. The advantage of the programmatic approach is that there is no redundancy. Each Field is created and added using normal Java. There is no need to specify where the Field must reside in the markup. If new requirements arrive and more fields added, only the Page has to be updated. No need to change the template as the layout is taken care of by the CSS and markup produced by the components. A disadvantage is that it is harder to <emphasis>visualize</emphasis> what output would be rendered by the containers. Whether you use the <link linkend="anchor-template-layout">template</link> or <link linkend="anchor-programmatic-layout">programmatic</link> layout approach, is up to you. Both work well and have advantages and disadva
 ntages over the other. </para>
+      </sect2>
+    </sect1>
 </chapter>
\ No newline at end of file

Modified: incubator/click/trunk/tools/docbook/src/docbook/click/chapter-pages.xml
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/docbook/src/docbook/click/chapter-pages.xml?rev=736438&r1=736437&r2=736438&view=diff
==============================================================================
--- incubator/click/trunk/tools/docbook/src/docbook/click/chapter-pages.xml (original)
+++ incubator/click/trunk/tools/docbook/src/docbook/click/chapter-pages.xml Wed Jan 21 14:10:25 2009
@@ -1,10 +1,885 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<chapter id="chapter-pages">
-    <title>Pages</title>
-
-    <section id="section-classes">
-        <title>Classes</title>
-
-    </section>
-
-</chapter>
\ No newline at end of file
+<?xml version='1.0' encoding='UTF-8'?>
+  <chapter remap="h1">
+    <title>Pages</title>
+    <para> Pages are the heart of web applications. In Click, Pages encapsulate the processing of HTML requests and the rendering of HTML responses. The section discusses Click pages and covers to following topics: </para>
+    <orderedlist>
+      <listitem>
+        <para><link linkend="pages.html-page-class">Classes</link>  - page Java classes</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="pages.html-page-execution">Execution</link>  - page execution sequence</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="pages.html-page-param-auto-binding">Request Param Auto Binding</link>  - request parameter to page field auto binding</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="pages.html-page-security">Security</link>  - page security model</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="pages.html-page-navigation">Navigation</link>  - navigation between pages</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="pages.html-page-templating">Page Templating</link>  - templating common page content</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="pages.html-page-direct-rendering">Direct Rendering</link>  - page direct rendering</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="pages.html-page-stateful">Stateful</link>  - stateful pages</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="pages.html-page-error-handling">Error Handling</link>  - page error handling</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="pages.html-page-not-found">Page Not Found</link>  - page not found handling</para>
+      </listitem>
+      <listitem>
+        <para><link linkend="pages.html-page-messages">Message Properties</link>  - pages message properties</para>
+      </listitem>
+    </orderedlist>
+    <para> </para>
+    <para> In Click, a logical page is composed of a Java class and a Velocity template, with these components being defined in page elements of the <ulink url="configuration.html#application-configuration">click.xml</ulink> file. </para>
+    <screen>
+&lt;page path=&quot;
+search.htm&quot; classname=&quot;
+com.mycorp.page.Search&quot;/&gt; 
+</screen>
+    <para> The path attribute specifies the location of the page Velocity template, and the classname attribute specifies the page Java class name. If you use an alternative template engine such as Freemarker, the setup above is the same. Alternatively you can also configure Click to use JSP pages for rendering. <screen>
+&lt;page path=&quot;
+search.jsp&quot; classname=&quot;
+com.mycorp.page.Search&quot;/&gt; 
+</screen><anchor id="pages.html-page-class"/><indexterm>
+        <primary>page-class</primary>
+      </indexterm>
+</para>
+    <sect1 remap="h2">
+      <title>1.  Classes</title>
+      <para> All custom Click pages must subclass the <ulink url="click-api/org/apache/click/Page.html">Page</ulink> base class. The Page class and its associated companion classes, Context and Control, are depicted below in Figure 1. <inlinemediaobject>
+          <imageobject>
+            <imagedata fileref="./../images/click-class-diagram.png" format="PNG"/>
+          </imageobject>
+        </inlinemediaobject>
+ <emphasis role="bold">Figure 1.   Page Class Diagram</emphasis> - created with Enterprise Architect courtesy <ulink url="http://www.sparxsystems.com.au">Sparx Systems</ulink></para>
+      <para> The Page class provides a <ulink url="click-api/org/apache/click/Page.html#model">model</ulink> attribute which is used to hold all the objects that are rendered in the page&apos;s Velocity template. The model may also contain <ulink url="click-api/org/apache/click/Control.html">Control</ulink> objects, which provide user interface controls on the Page. Pages also have an associated <ulink url="click-api/org/apache/click/Context.html">Context</ulink> object which references all the javax.servlet objects associated with the request. When programming in Click you use the Context object to access HttpServletRequest attributes, parameters and the HttpSession object. <anchor id="pages.html-page-execution"/><indexterm>
+          <primary>page-execution</primary>
+        </indexterm>
+</para>
+    </sect1>
+    <sect1 remap="h2">
+      <title>2.  Execution</title>
+      <para> The Page class provide a number of empty handler methods which subclasses can override to provide functionality: <itemizedlist>
+          <listitem>
+            <para>
+              <ulink url="click-api/org/apache/click/Page.html#onSecurityCheck()">onSecurityCheck()</ulink>
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <ulink url="click-api/org/apache/click/Page.html#onInit()">onInit()</ulink>
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <ulink url="click-api/org/apache/click/Page.html#onGet()">onGet()</ulink>
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <ulink url="click-api/org/apache/click/Page.html#onPost()">onPost()</ulink>
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <ulink url="click-api/org/apache/click/Page.html#onRender()">onRender()</ulink>
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <ulink url="click-api/org/apache/click/Page.html#onDestroy()">onDestroy()</ulink>
+            </para>
+          </listitem>
+        </itemizedlist>
+ The ClickServlet relies on instantiating Pages using a public no arguments constructor, so when you create Page subclasses you must ensure you don&apos;t add an incompatible constructor. The GET request execution sequence for Pages is summarized below in the Figure 2. <inlinemediaobject>
+          <imageobject>
+            <imagedata fileref="./../images/get-sequence-diagram.png" format="PNG"/>
+          </imageobject>
+        </inlinemediaobject>
+ <emphasis role="bold">Figure 2.   GET Request Sequence Diagram</emphasis> - created with Enterprise Architect courtesy <ulink url="http://www.sparxsystems.com.au">Sparx Systems</ulink></para>
+      <para> Stepping through this GET request sequence, a new Page instance is created and the attributes for the Page are set (context, format, headers, path). Next, request parameter values are bound to any matching public Page fields. Then the <literal>onSecurityCheck()</literal> handler is executed. This method can be used to ensure the user is authorized to access the page, and if necessary abort any further processing. The next method invoked is <literal>onInit()</literal>, this is where you place any post constructor initialization code. <literal>onInit()</literal> is the ideal place to create controls such as Forms, Fields and Tables. As illustrated by the diagram, after a Page&apos;s <literal>onInit()</literal> is called, each Control, available at that stage, will have their <literal>onInit()</literal> method called. The next step is the processing of the Page&apos;s <ulink url="click-api/org/apache/click/Page.html#controls">controls</ulink>. The ClickSerlvet gets
  the list of Controls from the page and then iterates through the list calling <literal>onProcess()</literal>. If any of the Control&apos;s <literal>onProcess()</literal> methods return false, processing of subsequent controls and the Page&apos;s <literal>onGet()</literal> method is aborted. If everything is executing normally the Page&apos;s <literal>onGet()</literal> method is now called. The next step is rendering the page template to generate the displayed HTML. The ClickServlet gets the model (<literal>Map</literal>) from the Page then adds the following objects to the model: <itemizedlist>
+          <listitem>
+            <para> any public Page fields using the fields name</para>
+          </listitem>
+          <listitem>
+            <para> context   -   the Servlet context path, e.g. /mycorp</para>
+          </listitem>
+          <listitem>
+            <para> cssImports   -   the CSS imports and style blocks to include in the pages header. Please see <ulink url="../click-api/org/apache/click/util/PageImports.html">PageImports</ulink> for more details.</para>
+          </listitem>
+          <listitem>
+            <para> format   -   the <ulink url="../click-api/org/apache/click/util/Format.html">Format</ulink> object for formatting the display of objects.</para>
+          </listitem>
+          <listitem>
+            <para> imports   -   the CSS and JavaScript imports to include in the pages header. Please see <ulink url="../click-api/org/apache/click/util/PageImports.html">PageImports</ulink> for more details.</para>
+          </listitem>
+          <listitem>
+            <para> jsImports   -   the JavaScript imports and script blocks to include in the pages footer. Please see <ulink url="../click-api/org/apache/click/util/PageImports.html">PageImports</ulink> for more details.</para>
+          </listitem>
+          <listitem>
+            <para> messages   -   the <ulink url="click-api/org/apache/click/util/MessagesMap.html">MessagesMap</ulink> adaptor for the Page <ulink url="click-api/org/apache/click/Page.html#getMessage(java.lang.String)">getMessage()</ulink> method</para>
+          </listitem>
+          <listitem>
+            <para> path   -   the <ulink url="click-api/org/apache/click/Page.html#path">path</ulink> of the page template to render</para>
+          </listitem>
+          <listitem>
+            <para> request   -   the pages <ulink url="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/http/HttpServletRequest.html">HttpServletRequest</ulink> object</para>
+          </listitem>
+          <listitem>
+            <para> response   -   the pages <ulink url="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/http/HttpServletResponse.html">HttpServletResponse</ulink> object</para>
+          </listitem>
+          <listitem>
+            <para> session   -   the <ulink url="click-api/org/apache/click/util/SessionMap.html">SessionMap</ulink> adaptor for the users <ulink url="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/http/HttpSession.html">HttpSession</ulink></para>
+          </listitem>
+        </itemizedlist>
+ It then merges the template with the page model and writes out results to the HttpServletResponse. When the model is being merged with the template, any Controls in the model may be rendered using their <literal>toString()</literal> method. The final step in this sequence is invoking each control&apos;s <literal>onDestroy()</literal> method and lastly invoke the Page&apos;s <literal>onDestroy()</literal> method. This method can be used to clean up resource associated with the Control or Page before it is garbage collected. The <literal>onDestroy()</literal> method is guaranteed to be called even if an exception occurs in the previous steps. The execution sequence for POST requests is almost identical, except the <literal>onPost()</literal> method is invoked instead on <literal>onGet()</literal>. See the <ulink url="../images/post-sequence-diagram.png">POST Request Sequence Diagram</ulink>. Another view on the execution flow of Pages is illustrated in the Activity diagram be
 low. <anchor id="pages.html-activity-diagram"/><inlinemediaobject>
+          <imageobject>
+            <imagedata fileref="./../images/activity-diagram-small.png" format="PNG"/>
+          </imageobject>
+        </inlinemediaobject>
+<indexterm>
+          <primary>activity-diagram</primary>
+        </indexterm>
+ <emphasis role="bold">Figure 3.   Page Execution Activity Diagram</emphasis> - created with Enterprise Architect courtesy <ulink url="http://www.sparxsystems.com.au">Sparx Systems</ulink></para>
+      <para>
+        <anchor id="pages.html-page-param-auto-binding"/>
+      </para>
+      <indexterm>
+        <primary>page-param-auto-binding</primary>
+      </indexterm>
+    </sect1>
+    <sect1 remap="h2">
+      <title>3.  Request Param Auto Binding</title>
+      <para> Click will automatically bind any request parameter values to public Page fields with the same name. When binding these values it will also attempt to convert them to the correct type. The best way to understand this is to walk through an example. Our application recieves a GET request: <screen>
+http://localhost:8080/mycorp/customer-details.htm?
+customerId=
+7203
+</screen> This request is automatically handled by our <literal>CustomerDetails</literal> page: <screen>
+
+package com.mycorp.page;
+
+
+public class CustomerDetails 
+extends Page {
+
+    
+public Integer 
+customerId;
+
+}
+</screen> After the CustomerDetails page has been created the &quot;customerId&quot; request parameter value &quot;7023&quot; will be converted into an Integer and assigned to the public page field <literal>customerId</literal>. Another feature of Click is that any public Page fields are automatically added to the page&apos;s model before it is rendered. This will make these values available in the page template for display. In our example the public <literal>customerId</literal> field will be added to the Page model and will be available for rendering in the page template: Our customer-details.htm page template contains: <screen>
+&lt;html&gt;
+&lt;body&gt;
+ 
+  Customer ID: 
+$
+customerId
+ 
+&lt;/body&gt;
+&lt;/html&gt;
+</screen> After processing the request our page would be rendered as: <informaltable frame="none">
+          <tgroup cols="1">
+            <colspec colname="c1" colwidth="100*"/>
+            <tbody>
+              <row>
+                <entry>
+                  <para>Customer ID: 7203</para>
+                </entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+</para>
+      <sect2 remap="h3">
+        <title>3.1  Customizing Auto Binding</title>
+        <para> Auto binding supports the conversion of request string parameters into the Java classes: Integer, Double, Boolean, Byte, Character, Short, Long, Float, BigInteger, BigDecimal, String and the various Date classes. By default type conversion is performed by the <ulink url="click-api/org/apache/click/util/RequestTypeConverter.html">RequestTypeConverter</ulink> class which is used by the ClickServlet method <ulink url="click-api/org/apache/click/ClickServlet.html#getTypeConverter()">getTypeConverter()</ulink>. If you need to add support for additional types, you would write your own type converter class and subclass the ClickSerlvet to use your custom converter. For example if we wanted to automatically load a <literal>Customer</literal> object from the database when a customer id request parameter is specified, you could write your own type converter: <screen>
+
+public class CustomTypeConverter 
+extends RequestTypeConverter {
+
+    
+private CustomerService customerService = 
+new CustomerService();
+
+    
+/**
+     * @see RequestTypeConverter#convertValue(Object, Class)
+     */
+    
+protected Object convertValue(Object value, Class toType) {
+        
+if (toType == Customer.
+class) {
+            
+return customerService.getCustomerForId(value);
+            
+        } 
+else {
+            
+return super.convertValue(value, toType);
+        }
+    }
+}
+</screen> This type converter would handle the following request: <screen>
+ http://localhost:8080/mycorp/customer-details.htm?
+customer=
+7203
+</screen> This request will load the customer object from the database using &quot;7203&quot; as the customer id value. The ClickServlet would then assign this customer object to the matching page field: <screen>
+
+package com.mycorp.page;
+
+
+public class CustomerDetails 
+extends Page {
+
+    
+public Customer 
+customer;
+
+}
+</screen> To make your custom type converter available you will need to subclass ClickServlet and override the <literal>getTypeConverter()</literal> method. For example: <screen>
+
+public class CustomClickServlet 
+extends ClickServlet {
+
+    
+/**
+     * @see ClickServlet#getTypeConverter()
+     */
+    
+protected TypeConverter getTypeConverter() {
+        
+if (typeConverter == 
+null) {
+            typeConverter = 
+new CustomTypeConverter();
+        }
+        
+return typeConverter;
+    }
+}
+</screen><anchor id="pages.html-page-security"/><indexterm>
+            <primary>page-security</primary>
+          </indexterm>
+</para>
+      </sect2>
+    </sect1>
+    <sect1 remap="h2">
+      <title>4.  Security</title>
+      <para> Pages provide an <ulink url="click-api/org/apache/click/Page.html#onSecurityCheck()">onSecurityCheck</ulink> event handler which application pages can override to implement a programmatic security model. Please note you generally don&apos;t need to use this capability, and where possible you should use the declarative JEE security model. See the Best Practices <ulink url="best-practices.html#security">Security</ulink> topic for more details. </para>
+      <sect2 remap="h3">
+        <title>4.1  Application Authentication</title>
+        <para> Applications can use the <literal>onSecurityCheck()</literal> method to implement their own security model. The example class below provides a base Secure page class which other pages can extend to ensure the user is logged in. In this example the login page creates a session when a user successfully authenticates. This Secure page then checks to make sure the user has a session, otherwise the request is redirected to the login page. <screen>
+
+public class Secure 
+extends Page {
+
+    
+/**
+     * @see Page#onSecurityCheck()
+     */
+    
+public boolean onSecurityCheck() {
+    
+        
+if (getContext().hasSession()) {
+            
+return true;
+            
+        } 
+else {
+            setRedirect(LoginPage.
+class);
+            
+return false;
+        }
+    }
+} 
+</screen></para>
+      </sect2>
+      <sect2 remap="h3">
+        <title>4.2  Container Authentication</title>
+        <para> Alternatively you can also use the security services provided by the JEE Servlet Container. For instance to ensure users have been authenticated by the Serlvet Container you could use a Secure page of: <screen>
+
+public class Secure 
+extends Page {
+
+    
+/**
+     * @see Page#onSecurityCheck()
+     */
+    
+public boolean onSecurityCheck() {
+    
+        
+if (getContext().getRequest().<ulink url="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/http/HttpServletRequest.html#getRemoteUser()"> getRemoteUser</ulink>() != 
+null) {
+            
+return true;
+            
+        } 
+else {
+            setRedirect(LoginPage.
+class);
+            
+return false;
+        }
+    }
+}
+</screen></para>
+      </sect2>
+      <sect2 remap="h3">
+        <title>4.3  Container Access Control</title>
+        <para> The Servlet Container also provides facilities to enforce role based access control (authorization). The example below is a base page to ensure only users in the &quot;admin&quot; role can access the page, otherwise users are redirected to the login page. Application Admin pages would extend this secure page to provide their functionality. <screen>
+
+public class AdminPage 
+extends Page {
+
+    
+/**
+     * @see Page#onSecurityCheck()
+     */
+    
+public boolean onSecurityCheck() {
+    
+        
+if (getContext().getRequest().<ulink url="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/http/HttpServletRequest.html#isUserInRole(java.lang.String)"> isUserInRole</ulink>(
+&quot;admin&quot;)) {
+            
+return true;
+
+        } 
+else {
+            setRedirect(LoginPage.
+class);
+            
+return false;
+        }
+    }
+}
+</screen></para>
+      </sect2>
+      <sect2 remap="h3">
+        <title>4.4  Logging Out</title>
+        <para> To logout using the application or container based security models you would simply invalidate the session. <screen>
+
+public class Logout 
+extends Page {
+
+    
+/**
+     * @see Page#onInit()
+     */
+    
+public void onInit() {
+        getContext().getSession().<ulink url="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/http/HttpSession.html#invalidate()"> invalidate</ulink>();
+    }
+} 
+</screen><anchor id="pages.html-page-navigation"/><indexterm>
+            <primary>page-navigation</primary>
+          </indexterm>
+</para>
+      </sect2>
+    </sect1>
+    <sect1 remap="h2">
+      <title>5.  Navigation</title>
+      <para> Navigation between pages is achieved by using forwards, redirects and by setting the page template path. <anchor id="pages.html-page-foward"/><indexterm>
+          <primary>page-foward</primary>
+        </indexterm>
+</para>
+      <sect2 remap="h3">
+        <title>5.1  Forward</title>
+        <para> To forward to another page using the servlet <ulink url="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/RequestDispatcher.html">RequestDispatcher</ulink>, set the Page&apos;s forward property. For example to forward to a page with a path index.htm: <screen>
+
+/**
+ * @see Page#onPost()
+ */
+
+public void onPost() {
+   
+// Process form post
+   ..
+   
+   setForward(
+&quot;index.htm&quot;);
+} 
+</screen> This will invoke a new Page class instance mapped to the path index.htm. <emphasis role="bold">Please note</emphasis> when a request is forwarded to another Page, the controls on the second page will not be processed. This prevents confusion and bugs, like a form on the second page trying to process a POST request from the first page. </para>
+        <sect3 remap="h4">
+          <title>5.1.1  Forward Parameter Passing</title>
+          <para> When you forward to another page the request parameters are maintained. This is a handy way of passing through state information with the request. For example you could add a customer object as a request parameter which is displayed in the template of the forwarded page. <screen>
+
+public boolean onViewClick() {
+   Long id = viewLink.getValueLong();
+   Customer customer = CustomerDAO.findByPK(id); 
+   
+   
+// Set the customer object as a request parameter
+   getContext().setRequestAttribute(
+&quot;customer&quot;, customer);
+   setForward(
+&quot;view-customer.htm&quot;);
+   
+   
+return false;
+} 
+</screen> The snippet above forwards to the page template view-customer.htm: <screen>
+&lt;html&gt;
+ &lt;head&gt;
+   &lt;title&gt;Customer Details&lt;/title&gt;
+ &lt;/head&gt;
+ &lt;body&gt;
+   &lt;h1&gt;Customer Details&lt;/h1&gt;
+   &lt;pre&gt;
+     Full Name: 
+$customer.fullName
+     Email:     
+$customer.email
+     Telephone: 
+$customer.telephone
+    &lt;/pre&gt;
+  &lt;/body&gt;
+&lt;/html&gt; 
+</screen> Request attributes are automatically added to the Velocity Context object so are available in the page template. <anchor id="pages.html-page-forwarding"/><indexterm>
+              <primary>page-forwarding</primary>
+            </indexterm>
+</para>
+        </sect3>
+        <sect3 remap="h4">
+          <title>5.1.2  Page Forwarding</title>
+          <para> Page forwarding is another way of passing information between pages. In this case you create the page to be forwarded to using the Context <ulink url="click-api/org/apache/click/Context.html#createPage(java.lang.String)">createPage()</ulink> method and then set properties directly on the Page. Finally set this page as the page to forward the request to. For example: <screen>
+
+public boolean onEditClick() {
+   Long id = viewLink.getValueLong();
+   Customer customer = CustomerDAO.findByPK(id); 
+   
+   
+// Create a new EditPage instance based on the specified path
+   EditPage editPage = (EditPage) getContext().createPage(
+&quot;/edit-customer.htm&quot;);
+   editPage.setCustomer(customer);
+   setForward(editPage);
+   
+   
+return false;
+} 
+</screen> When creating a page with the <literal>createPage()</literal> method ensure you prefix the page path with the <literal>&quot;/&quot;</literal> character. You can also specify the target page using its class as long as the Page has a unique path. (Although uncommon it is possible to map more than one path to the same class. In these cases invoking Context.createPage will throw an exception, because Click will not be able to determine which path to use). Using this technique the above code becomes: <screen>
+
+public boolean onEditClick() {
+   Long id = viewLink.getValueLong();
+   Customer customer = CustomerDAO.findByPK(id); 
+   
+   
+// Create a new EditPage instance based on its class
+   EditPage editPage = (EditPage) getContext().createPage(EditPage.
+class);
+   editPage.setCustomer(customer);
+   setForward(editPage);
+   
+   
+return false;
+}
+</screen> This Page forwarding technique is best practice as it provides you with compile time safety and alleviates you from having to specify page paths in your code. Please always use the Context <literal>createPage()</literal> methods to allow Click to inject Page dependencies. <anchor id="pages.html-page-template-path"/><indexterm>
+              <primary>page-template-path</primary>
+            </indexterm>
+</para>
+        </sect3>
+      </sect2>
+      <sect2 remap="h3">
+        <title>5.2  Template Path</title>
+        <para> An alternative method of forwarding to a new page is to simply set the current Page&apos;s path to the new page template to render. With this approach the page template being rendered must have everything it needs without having its associated Page object created. Our modified example would be: <screen>
+
+public boolean onViewClick() {
+   Long id = viewLink.getValueLong();
+   Customer customer = CustomerDAO.findByPK(id); 
+    
+   addModel(
+&quot;customer&quot;, customer);
+   
+   
+// Set the Page&apos;s path to a new value
+   setPath(
+&quot;view-customer.htm&quot;);
+   
+   
+return false;
+} 
+</screen> Note how the <emphasis condition="red" role="color">customer</emphasis> object is passed through to the template in the Page model. This approach of using the Page model is not available when you forward to another Page, as the first Page object is &quot;<ulink url="click-api/org/apache/click/Page.html#onDestroy()">destroyed</ulink>&quot; before the second Page object is created and any model values would be lost. <anchor id="pages.html-page-redirect"/><indexterm>
+            <primary>page-redirect</primary>
+          </indexterm>
+</para>
+      </sect2>
+      <sect2 remap="h3">
+        <title>5.3  Redirect</title>
+        <para> Redirects are another very useful way to navigate between pages. See HttpServletResponse.<ulink url="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/http/HttpServletResponse.html#sendRedirect(java.lang.String)">sendRedirect</ulink>(location) for details. The great thing about redirects are that they provide a clean URL in the users browser which matches the page that they are viewing. This is important for when users want to bookmark a page. The downside of redirects are that they involve a communications round trip with the users browser which requests the new page. Not only does this take time, it also means that all the page and request information is lost. An example of a redirect to a logout.htm page is provided below: <screen>
+
+public boolean onLogoutClick() {
+   setRedirect(
+&quot;/logout.htm&quot;);
+   
+return false;
+} 
+</screen> If the redirect location begins with a &quot;/&quot; character the redirect location will be prefixed with the web applications context path. For example if an application is deployed to the context &quot;mycorp&quot; calling <literal>setRedirect(&quot;/customer/details.htm&quot;)</literal> will redirect the request to: &quot;/mycorp/customer/details.htm&quot; You can also obtain the redirect path via the target Page&apos;s class. For example: <screen>
+
+public boolean onLogoutClick() {
+   String path = getContext().getPagePath(Logout.
+class);
+   setRedirect(path);
+   
+return false;
+} 
+</screen> Note when using this redirect method, the target Page class must have a unique path. A short hand way of redirecting is to simply specify the target Page class in the redirect method. For example: <screen>
+
+public boolean onLogoutClick() {
+   setRedirect(Logout.
+class);
+   
+return false;
+} 
+</screen></para>
+        <sect3 remap="h4">
+          <title>5.3.1  Redirect Parameter Passing</title>
+          <para> You can pass information between redirected pages using URL request parameters. The ClickServlet will encode the URL for you using HttpServletResponse.<ulink url="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/http/HttpServletResponse.html#encodeRedirectURL(java.lang.String)">encodeRedirectURL</ulink>(url). In the example below a user will click on an OK button to confirm a payment. The <literal>onOkClick()</literal> button handler processes the payment, gets the payment transaction id, and then redirects to the trans-complete.htm page with the transaction id encoded in the URL. <screen>
+
+public class Payment 
+extends Page {
+   ..
+   
+   
+public boolean onOkClick() {
+      
+if (form.isValid()) {
+         
+// Process payment
+         ..
+         
+         
+// Get transaction id
+         Long transId = OrderDAO.purchase(order);
+   
+         setRedirect(
+&quot;trans-complete.htm?transId=&quot; + transId);
+      
+         
+return false; 
+      } 
+  
+      
+return true;
+   }
+} 
+</screen> The Page class for the trans-complete.htm page can then get the transaction id through the request parameter <literal>&quot;transId&quot;</literal>: <screen>
+
+public class TransComplete 
+extends Page {
+   
+   
+/**
+    * @see Page#onInit()
+    */
+   
+public void onInit() {
+      String transId = getContext().getRequest().getParameter(
+&quot;transId&quot;);
+   
+      
+if (transId != 
+null) {
+      
+         
+// Get order details
+         Order order = OrderDAO.findOrderByPK(
+new Long(transId));
+         
+if (order != 
+null) {
+            addModel(
+&quot;order&quot;, order);
+         }
+      }
+   }
+} 
+</screen></para>
+        </sect3>
+        <sect3 remap="h4">
+          <title>5.3.2  Post Redirect</title>
+          <para> The parameter passing example above is also an example of a Post Redirect. The Post Redirect technique is a very useful method of preventing users from submitting a form twice by hitting the refresh button. <anchor id="pages.html-page-templating"/><indexterm>
+              <primary>page-templating</primary>
+            </indexterm>
+</para>
+        </sect3>
+      </sect2>
+    </sect1>
+    <sect1 remap="h2">
+      <title>6.  Page Templating</title>
+      <para> Click supports page templating (a.k.a. <emphasis>Tiles</emphasis> in Struts) enabling you to create a standardized look and feel for your web application and greatly reducing the amount of HTML you need to maintain. To implement templating define a border template base Page which content Pages should extend. The template base Page class overrides the Page <ulink url="click-api/org/apache/click/Page.html#getTemplate()">getTemplate()</ulink> method, returning the path of the border template to render. For example: <screen>
+
+public class BorderedPage 
+extends Page {
+
+    
+/**
+     * @see Page#getTemplate()
+     */
+    
+public String getTemplate() {
+        
+return 
+&quot;/border.htm&quot;;  
+    }
+}
+</screen> The BorderedPage template border.htm: <screen>
+ &lt;html&gt;
+   &lt;head&gt;
+     &lt;title&gt;
+$title&lt;/title&gt;
+     &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;style.css&quot; title=&quot;Style&quot;/&gt;
+   &lt;/head&gt;
+   &lt;body&gt;
+ 
+     &lt;h2 class=&quot;title&quot;&gt;
+$title&lt;/h2&gt;
+ 
+     
+#parse(
+$path)
+ 
+   &lt;/body&gt;
+ &lt;/html&gt;
+</screen> Other pages insert their content into this template using the Velocity <ulink url="velocity/vtl-reference-guide.html#parse">#parse</ulink> directive, passing it their contents pages <ulink url="click-api/org/apache/click/Page.html#path">path</ulink>. The $path value is automatically added to the VelocityContext by the ClickServlet. An example bordered Home page is provided below: <screen>
+&lt;page path=&quot;
+home.htm&quot; classname=&quot;Home&quot;/&gt; 
+</screen><screen>
+
+public class Home 
+extends BorderedPage {
+   
+     
+public String title = 
+&quot;Home&quot;;
+
+}
+</screen> The Home page&apos;s content home.htm: <screen>
+&lt;b&gt;Welcome&lt;/b&gt; to Home page your starting point for the application.
+</screen> When a request is made for the Home page (home.htm) Velocity will merge the border.htm page and home.htm page together returning: <screen>
+ &lt;html&gt;
+   &lt;head&gt;
+     &lt;title&gt;Home&lt;/title&gt;
+     &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;style.css&quot; title=&quot;Style&quot;/&gt;
+   &lt;/head&gt;
+   &lt;body&gt;
+ 
+     &lt;h2 class=&quot;title&quot;&gt;Home&lt;/h2&gt;
+ 
+     &lt;b&gt;Welcome&lt;/b&gt; to Home page your application starting point.
+ 
+   &lt;/body&gt;
+ &lt;/html&gt;
+</screen> Which may be rendered as: <informaltable frame="none">
+          <tgroup cols="1">
+            <colspec colname="c1" colwidth="100*"/>
+            <tbody>
+              <row>
+                <entry>
+                  <para>
+                    <emphasis remap="h2" role="bold">Home</emphasis>
+                  </para>
+                  <para><emphasis role="bold">Welcome</emphasis> to Home page your application starting point. </para>
+                </entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+ Note how the Home page class defines a title model value which is referenced in the border.htm template as $title. Each bordered page can define their own title which is rendered in this template. Templating with JSP pages is also supported using the same pattern. Please see the Click Examples application for a demonstration. <anchor id="pages.html-page-direct-rendering"/><indexterm>
+          <primary>page-direct-rendering</primary>
+        </indexterm>
+</para>
+    </sect1>
+    <sect1 remap="h2">
+      <title>7.  Direct Rendering</title>
+      <para> Pages support a direct rendering mode where you can render directly to the servlet response and bypass the page template rendering. This is useful for scenarios where you want to render non HTML content to the response, such as a PDF or Excel document. To do this: <itemizedlist>
+          <listitem>
+            <para> get the servlet response object</para>
+          </listitem>
+          <listitem>
+            <para> set the content type on the response</para>
+          </listitem>
+          <listitem>
+            <para> get the response output stream</para>
+          </listitem>
+          <listitem>
+            <para> write to the output stream</para>
+          </listitem>
+          <listitem>
+            <para> close the output stream</para>
+          </listitem>
+          <listitem>
+            <para> set the page path to null to inform the ClickServlet that rendering has been completed</para>
+          </listitem>
+        </itemizedlist>
+ A direct rendering example is provided below. <screen>
+    
+    
+/**
+     * Render the Java source file as &quot;text/plain&quot;.
+     *
+     * @see Page#onGet()
+     */
+    
+public void onGet() {
+        String filename = ..
+
+        HttpServletResponse response = getContext().getResponse();
+
+        response.setContentType(
+&quot;text/plain&quot;);
+        response.setHeader(
+&quot;Pragma&quot;, 
+&quot;no-cache&quot;);
+
+        ServletContext context = getContext().getServletContext();
+
+        InputStream inputStream = 
+null;
+        
+try {
+            inputStream = context.getResourceAsStream(filename);
+
+            PrintWriter writer = response.getWriter();
+
+            BufferedReader reader =
+                
+new BufferedReader(new InputStreamReader(inputStream));
+
+            String line = reader.readLine();
+
+            
+while (line != 
+null) {
+                writer.println(line);
+                line = reader.readLine();
+            }
+            
+            setPath(
+null);
+
+        } 
+catch (IOException ioe) {
+            ioe.printStackTrace();
+
+        } 
+finally {
+            ClickUtils.close(inputStream);
+        }
+    }
+</screen><anchor id="pages.html-page-stateful"/><indexterm>
+          <primary>page-stateful</primary>
+        </indexterm>
+</para>
+    </sect1>
+    <sect1 remap="h2">
+      <title>8.  Stateful Pages</title>
+      <para> Click supports stateful pages where the state of the page is saved between the users requests. Stateful pages are useful in a number of scenarios including: <itemizedlist>
+          <listitem>
+            <para> Search page and edit page interactions. In this scenario you navigage from a stateful search page which may have filter criteria applied to an object edit page. Once object update has been completed on the edit page, the user is redirected to the search page and the stateful filter criteria still applies.</para>
+          </listitem>
+          <listitem>
+            <para> Complex pages with multiple forms and or tables which need to maintain their state between interactions.</para>
+          </listitem>
+        </itemizedlist>
+ To make a page stateful you simply need to set the page <ulink url="click-api/org/apache/click/Page.html#stateful">stateful</ulink> property to true, have the page implement the <literal>Serializable</literal> interface and set the <literal>serialVersionUID</literal> indicator. For example: <screen>
+
+package com.mycorp.page;
+
+
+import java.io.Serializable;
+
+
+import org.apache.click.Page;
+ 
+
+public class SearchPage 
+extends Page 
+implements Serializable {
+
+    
+private static final long serialVersionUID = 1L;
+
+    
+public SearchPage() {
+        setStateful(
+true);
+        ..
+    }
+} 
+</screen> Stateful page instances are stored in the user&apos;s <ulink url="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/http/HttpSession.html">HttpSession</ulink> using the pages class name as the key. In the example above the page would be stored in the users session using the class name: <literal>com.mycorp.page.SearchPage</literal></para>
+      <sect2 remap="h3">
+        <title>8.1  Page Creation</title>
+        <para> With stateful pages they are only created once, after which they are retrieved from the session. However page event handlers are invoked for each request, including the <literal>onInit()</literal> method. When you are creating stateful pages you typically place all your control creation code in the Pages constructor so it is invoked only once. It is important not to place control creation code in the <literal>onInit()</literal> method which will be invoked with each request. If you have dynamic control creation code you would typically place this in the <literal>onInit()</literal> method, but you will need to take care that controls and or models are not already present in the page. </para>
+      </sect2>
+      <sect2 remap="h3">
+        <title>8.2  Page Execution</title>
+        <para> The default Click page execution model is thread safe as a new Page instance is created for each request and thread. With stateful pages a user will have a single page instance which is reused in multiple requests and threads. To ensure page execution is thread safe, users page instances are synchronized so only one request thread can execute a page instance at any one time. </para>
+      </sect2>
+      <sect2 remap="h3">
+        <title>8.3  Page Destruction</title>
+        <para> After normal page instances have been executed, they are de-referenced and garbage collected by the JVM. However with stateful pages they are stored in the users <literal>HttpSession</literal> so care needs to be take not to store too many objects in stateful page instances which may cause memory and performance issues. When pages have completed their execution, all the Page&apos;s controls <literal>onDestroy()</literal> methods are invoked, and then the Page&apos;s <literal>onDestroy()</literal> method is invoked. This is your opportunity to de-reference any large sets or graphs. For example the Table control by default de-references its rowList in its <ulink url="click-api/org/apache/click/control/Table.html#onDestroy()">onDestory()</ulink> method. <anchor id="pages.html-page-error-handling"/><indexterm>
+            <primary>page-error-handling</primary>
+          </indexterm>
+</para>
+      </sect2>
+    </sect1>
+    <sect1 remap="h2">
+      <title>9.  Error Handling</title>
+      <para> If an Exception occurs processing a Page object or rendering a template the error is delegated to the registered handler. The default Click error handler is the <ulink url="click-api/org/apache/click/util/ErrorPage.html">ErrorPage</ulink>, which is automatically configured as: <screen>
+&lt;page path=&quot;
+click/error.htm&quot; classname=&quot;
+org.apache.click.util.ErrorPage&quot;/&gt; 
+</screen> To register an alternative error handler you must subclass ErrorPage and define your page using the path &quot;click/error.htm&quot;. For example: <screen>
+&lt;page path=&quot;
+click/error.htm&quot; classname=&quot;
+com.mycorp.page.ErrorPage&quot;/&gt; 
+</screen> When the ClickSevlet starts up it checks to see whether the error.htm template exists in the click web sub directory. If it cannot find the page the ClickServlet will automatically deploy one. You can tailor the click/error.htm template to suite you own tastes, and the ClickServlet will not overwrite it. The default error template will display extensive debug information when the application is in <literal>development</literal> or <literal>debug</literal> mode. Example error page displays include: <itemizedlist>
+          <listitem>
+            <para><ulink url="error-npe.html">NullPointerException</ulink>  - in a page method</para>
+          </listitem>
+          <listitem>
+            <para><ulink url="error-parsing.html">ParseErrorException</ulink>  - in a page template</para>
+          </listitem>
+        </itemizedlist>
+ When the application is in <literal>production</literal> mode only a simple error message is displayed. See <ulink url="configuration.html#application-mode">Configuration</ulink> for details on how to set the application mode. Please also see the <ulink url="examples.html">Examples</ulink> web app Exception Demo for demonstrations of Clicks error handling. <anchor id="pages.html-page-not-found"/><indexterm>
+          <primary>page-not-found</primary>
+        </indexterm>
+</para>
+    </sect1>
+    <sect1 remap="h2">
+      <title>10.  Page Not Found</title>
+      <para> If the ClickServlet cannot find a requested page in the <literal>click.xml</literal> config file it will use the registered <ulink url="not-found.html">not-found.htm</ulink> page. The Click not found page is automatically configured as: <screen>
+&lt;page path=&quot;
+click/not-found.htm&quot; classname=&quot;
+org.apache.click.Page&quot;/&gt; 
+</screen> You can override the default configuration and specify your own class, but you cannot change the path. When the ClickSevlet starts up it checks to see whether the not-found.htm template exists in the click web sub directory. If it cannot find the page the ClickServlet will automatically deploy one. You can tailor the click/not-found.htm template to suite you own needs. This page template has access to the usual Click objects. <anchor id="pages.html-page-messages"/><indexterm>
+          <primary>page-messages</primary>
+        </indexterm>
+</para>
+    </sect1>
+    <sect1 remap="h2">
+      <title>11.  Message Properties</title>
+      <para> The Page class provides a <ulink url="click-api/org/apache/click/Page.html#messages">messages</ulink> property which is a <ulink url="click-api/org/apache/click/util/MessagesMap.html">MessagesMap</ulink> of localized messages for the page. These messages are made available in the VelocityContext when the page is rendered under the key <literal>messages</literal>. So for example if you had a page title message you would access it in your page template as: <screen>
+    &lt;h1&gt; 
+$
+messages.title &lt;/h1&gt;
+</screen> This messages map is loaded from the page class property bundle. For example if you had a page class <literal>com.mycorp.page.CustomerList</literal> you could have an associated property file containing the pages localized messages: <screen>
+/com/mycorp/page/CustomerList.properties
+</screen> You can also defined a application global page messages properties file: <screen>
+/click-page.properties
+</screen> Messages defined in this file will be available to all pages throughout your application. Note messages defined in your page class properties file will override any messages defined in the application global page properties file. Page messages can also be used to override Control messages, see the Controls <ulink url="controls.html#message-properties">Message Properties</ulink> topic for more details. </para>
+    </sect1>
+  </chapter>



Mime
View raw message