5.2. Application Configuration

The heart of a Click application is the click.xml configuration file. This file specifies the application pages, headers, the format object and the applications mode.

By default the ClickServlet will attempt to load the application configuration file using the path:   /WEB-INF/click.xml

If this file is not found under the WEB-INF directory, then ClickServlet will attempt to load it from the classpath as /click.xml.

See Click DTD for the click-app XML definition.

A complete Click configuration example is available here which can be used as a quick reference when configuring Click.

A basic Click app config file is provided below:

<click-app>

  <!-- Specify the Java package where Page classes can be found -->
  <pages package="com.mycorp.page"/>

  <mode value="profile"/>

</click-app>

An advanced config file would look like this:

<click-app charset="UTF-8" locale="de">

  <!-- To aid Click's automapping, specify the Java package where Page classes can be found -->
  <pages package="com.mycorp.banking.page">
  <!-- We have to manually define the mapping between the Home page class and index.htm template
  because this page doesn't follow the automatic mapping convention of naming the page class and
  template the same-->
    <page path="index.htm" classname="com.mycorp.banking.page.Home"/>
  </pages>

  <!-- Specify a second Java package where Page classes can be found -->
  <pages package="com.mycorp.common.page"/>

  <format classname="com.mycorp.util.Format"/>

  <mode value="profile"/>

  <log-service classname="org.apache.click.extras.service.Log4JLogService"/>

</click-app>

The take away point is that there is not much to configure, even for advanced uses.

5.2.1. Click App

The root click-app element defines two application localization attributes charset and locale.

<!ELEMENT click-app (pages*, headers?, format?, mode?, controls?,
                         file-upload-service?, log-service?, messages-map-service?, resource-service?, template-service?, page-interceptor*)>
  <!ATTLIST click-app charset CDATA #IMPLIED>
  <!ATTLIST click-app locale CDATA #IMPLIED>

The charset attribute defines the character encoding set for:

  • Velocity templates

  • HttpServletRequest character encoding

  • Page Content-Type charset, see Page getContentType()

The locale attribute defines the default application Locale. If this value is defined it will override Locale returned by the request. Please see the Context getLocale() for details. For example the following configuration sets the application character set to UTF-8 and the default Locale as German (de):

<click-app charset="UTF-8" locale="de">
  ..
</click-app>

5.2.2. Pages

The first child element of the click-app is the mandatory pages element which defines the list of Click pages.

<!ELEMENT pages (page*)>
   <!ATTLIST pages package CDATA #IMPLIED>
   <!ATTLIST pages automapping (true|false) "true">
   <!ATTLIST pages autobinding (default|annotation|none) "default">

The pages element can specify a base package that Click should use for mapping page templates to page classes.

The pages element also defines the automapping and autobinding attributes which is discussed in the Page Automapping and Page Autobinding sections respectively.

5.2.2.1. Multiple Pages Packages

Click can support multiple pages elements to enable the automapping of multiple packages.

<click-app>

  <pages package="com.mycorp.banking.page"/>

  <pages package="com.mycorp.common.page"/>

</click-app>

With multiple pages elements, pages are loaded in the order of the page elements, with manual page elements being loaded before automapped pages. Once a page template has been mapped to a Page class it will not be replaced by a subsequent potential match. So pages elements at the top take priority over lower pages elements.

5.2.3. Page

The page element defines the Click application pages.

<!ELEMENT page(header*)>
   <!ATTLIST page path CDATA #REQUIRED>
   <!ATTLIST page classname CDATA #REQUIRED>

Each page path must be unique, as the Click application maps HTTP requests to the page paths.

The Click application will create a new Page instance for the given request using the configured page classname. All pages must subclass Page and provide a public no arguments constructor, so they can be instantiated.

Pages can also define header values which are discussed in the next topic.

When the Click application starts up it will check all the page definitions. If there is a critical configuration error the ClickSerlvet will log an ERROR message and throw an UnavailableException. If this occurs the click application will be permanently unavailable until the error is fixed and the web app is restarted.

5.2.3.1. Page Automapping

Page automapping will automatically configure application pages using a simple set of rules. This enables you to greatly streamline your configuration file as you only need to define pages which don't fit the automapping rules.

Automapping will attempt to associate each page template (*.htm) and JSP file in the web application (excluding those under WEB-INF) to a Page class. Automapped pages are loaded after the manually defined pages are loaded, and manually defined pages takes preference. When automapping is enabled the page mappings will be logged if Click is running in debug or trace mode.

For example, given the following page path to class mapping:

index.htm                     => com.mycorp.page.Home
search.htm                    => com.mycorp.page.Search
contacts/contacts.htm         => com.mycorp.page.contacts.Contacts
security/login.htm            => com.mycorp.page.security.Login
security/logout.htm           => com.mycorp.page.security.Logout
security/change-password.htm  => com.mycorp.page.security.ChangePassword

The above mapping could be configured manually by setting the automapping attribute to false, for example:

<click-app>
  <pages automapping="false">
    <page path="index.htm"                    classname="com.mycorp.page.Home"/>
    <page path="search.htm"                   classname="com.mycorp.page.Search"/>
    <page path="contacts/contacts.htm"        classname="com.mycorp.page.contacts.Contacts"/>
    <page path="security/login.htm"           classname="com.mycorp.page.security.Login"/>
    <page path="security/logout.htm"          classname="com.mycorp.page.security.Logout"/>
    <page path="security/change-password.htm" classname="com.mycorp.page.security.ChangePassword"/>
  </pages>
</click-app>

For an application with many pages, it is cumbersome to manually map each page template to its associated class. This is where automapping comes in.

By setting automapping to true, Click will automatically map page templates to page classes. To map a template to a page class, Click converts the template path to the Page classname. In the example above, Click will convert the template search.htm to the class Search by capitilizing the template name and removing the .htm extension. Of course this is not enough to map the template to the class. what is missing is the class package, com.mycorp.page. To help Click map the page, you can set the base package attribute as shown in the next example.

Below is the full configuration to automatically map the templates to pages (except for index.htm which doesn't automatically map to Home page and has to be mapped manually):

<click-app>
  <pages package="com.mycorp.page" automapping="true">
    <page path="index.htm" classname="com.mycorp.page.Home"/>
  </pages>
</click-app>

Note: automapping is true by default, so it could be omitted.

If a page template is placed in a sub folder of the root web folder, it's associated page class must be placed in an equivalently named sub package of the base package in order for the page to be mapped automatically. In the mapping above the page template security/change-password.htm is located in the security folder under the web root. In order for Click to correctly map the page template to it's class, the class must be located in the security package of the base package com.mycorp.page. The absolute page classname is thus: com.mycorp.page.security.ChangePassword.

The page template name to classname convention is:

change-password.htm  =>  ChangePassword
change_password.htm  =>  ChangePassword
changePassword.htm   =>  ChangePassword
ChangePassword.htm   =>  ChangePassword

During automapping, if a page class cannot be found, Click will add the 'Page' suffix to the classname (if not already present) and attempt to map the page template to this modified classname. For example:

customer.htm         =>  CustomerPage
change-password.htm  =>  ChangePasswordPage

5.2.3.2. Automapping Excludes

With Page automapping there can be resources where you don't want automapping applied. For example when using a JavaScript library with lots of .htm files, you don't want automapping to try and find Page class for each of these files. In these situations you can use the pages excludes element.

<!ELEMENT excludes (#PCDATA)>
   <!ATTLIST excludes pattern CDATA #REQUIRED>

For example if our application uses the TinyMCE JavaScript library we could configure our pages automapping to exclude all .htm files under the /tiny_mce directory.

<click-app>
  <pages package="com.mycorp.page">
    <excludes pattern="/tiny_mce/*"/>
  </pages>
</click-app>

The excludes pattern can specify multiple directories or files using a comma separated notation. For example:

<click-app>
  <pages package="com.mycorp.page">
    <excludes pattern="/dhtml/*, /tiny_mce/*, banner.htm, about.htm"/>
  </pages>
</click-app>

HTM files excluded from Page automapping are handled by an internal Page class with caching headers enabled.

5.2.3.3. Page Autobinding

Autobinding is a feature that allows certain page variables to be handled in a special way by the ClickServlet. The autobinding attribute can be configured with one of the following values:

  • default: bindable variables include both public page variables and variables annotated with the @Bindable annotation

  • annotation: bindable variables are variables annotated with the @Bindable annotation

  • none: disables the autobinding feature

By default all pages have autobinding enabled in default mode.

Please note: we recommend using autobinding only for binding request parameters, not for Controls. It generally leads to code that is difficult to maintain. In a future release we will replace autobinding with a simpler implementation.

With autobinding the ClickServlet will automatically:

  • add all bindable controls to the page, after the page constructor has been invoked

  • if a bindable control name is not defined, the control name will be set to the value of its variable name (note, if the control name is already defined its name will not be changed)

  • bind all request parameters to bindable page variables, after the page constructor has been invoked. See ClickServlet.processPageRequestParams(Page) for more details

  • add all bindable page variables to the page model (this step occurs just before the page is rendered)

For example:

public class EmployeePage extends Page {

    public String employeeDescription;

    // Form does not have a name defined
    public Form employeeForm = new Form();

    // Table defines its own name
    public Table employeeTable = new Table("table");

}

Note in the example above that the employeeDescription variable and the employeeForm and employeeTable controls are not added to the page. Also note that Form name is not defined.

When autobinding is enabled, ClickServlet will create a new Page and add the bindable variables and controls to the page. Following the example above the employeeDescription, employeeForm and employeeTable will be added to the page, which is equivalent to the following statements: addModel("employeeDescription", employeeDescription), addControl(employeeForm) and addControl(employeeTable).

Furthermore, controls that do not have a name defined will have their name set to their instance variable name. In this case the Form name will be set to employeeForm while the Table name won't be altered since it already has a name defined.

The above example is a shorthand way of writing the following:

public class EmployeePage extends Page {

    private String employeeDescription;

    private Form employeeForm = new Form();

    private Table employeeTable = new Table("table");

    public void onInit() {
        employeeForm.setName("employeeForm");
        addControl(employeeForm);

        addControl(myTable);
    }
}

Note that we did not show where employeeDescription is added to the page model. The reason for that is because autobinding handles non controls slightly differently. Non control variables are added to the model just before the page response is written. This allows the value of the variable to be set anywhere in the page. For example:

public class EmployeePage extends Page {

    private String employeeDescription;

    private Form employeeForm = new Form();

    private Table employeeTable = new Table("table");

    ...

    public boolean onSaveClick {
        if (employeeForm.isValid()) {
            // employeeDescription is added to the page model just before the
            // response is written
            employeeDescription = employee.getDescription();
        }
    }
} 

employeeDescription will be added to the page model and can be referenced in the page template as $employeeDescription.

Autobinding can be turned off by setting the autobinding attribute to none as shown below:

<click-app>
  <pages package="com.mycorp.page" autobinding="none"/>
</click-app>

5.2.3.4. Page Autobinding - Using Annotations

Click provides the Bindable annotation which enables autobinding of Page variables The Bindable annotation can bind private, protected and public Page variables.

By default, Click's autobinding feature operates on both public and @Bindable variables. To instruct Click to operate only on @Bindable annotated variables, you can set the autobinding attribute to annotation, for example:

<click-app>
  <pages package="com.mycorp.page" autobinding="annotation"/>
</click-app>

Click won't autobind public variables anymore.

Below is an example using the @Bindable annotation:

public class EmployeePage extends Page {

    @Bindable protected Form employeeForm = new Form();

    @Bindable protected Table myTable = new Table();

}

5.2.4. Headers

The optional headers element defines a list of header elements which are applied to all pages.

<!ELEMENT headers (header*)>

The header element defines header name and value pairs which are applied to the HttpServletResponse.

<!ELEMENT header (#PCDATA)>
   <!ATTLIST header name CDATA #REQUIRED>
   <!ATTLIST header value CDATA #REQUIRED>
   <!ATTLIST header type (String|Integer|Date) "String">

Page headers are set after the Page has been constructed and before onInit() is called. Pages can then modify their headers property using the setHeader() method.

5.2.4.1. Browser Caching

Headers are typically used to switch off browser caching. By default Click will use the following no caching header values if you don't define a headers element in your application:

<click-app>
  <pages>
     ..
  </pages>
  <headers>
    <header name="Pragma" value="no-cache"/>
    <header name="Cache-Control"
            value="no-store, no-cache, must-revalidate, post-check=0, pre-check=0"/>
    <header name="Expires" value="1" type="Date"/>
  </headers>
</click-app>

Alternatively you can define your headers individually in pages or for all application pages by setting header values. For example, to switch off caching in the Login page, set the following page cache control headers:

<pages package="com.mycorp.page">
  <page path="login.htm" classname="com.mycorp.page.Login">
    <header name="Pragma" value="no-cache"/>
    <header name="Expires" value="1" type="Date"/>
  </page>
</pages>

Note: the value for a Date type should be a long number value.

If you wanted to enable caching for a particular page you could set the following page cache control header. This will mark the page as cachable for a period of 1 hour after which it should be reloaded.

<pages package="com.mycorp.page">
  <page path="home.htm" classname="com.mycorp.page.Home">
    <header name="Cache-Control" value="max-age=3600, public, must-revalidate"/>
  </page>
</pages>

To apply header values globally define header values in the headers element. For example:

<click-app>
  <pages>
     ..
  </pages>
  <headers>
    <header name="Pragma" value="no-cache"/>
    <header name="Cache-Control"
               value="no-store, no-cache, must-revalidate, post-check=0, pre-check=0"/>
    <header name="Expires" value="1" type="Date"/>
  </headers>
</click-app>

5.2.5. Format

The optional format element defines the Format object classname which is applied to all pages.

<!ELEMENT format (#PCDATA)>
    <ATTLIST format classname CDATA "org.apache.click.util.Format">

By default all Click pages are configured with a org.apache.click.util.Format object. The format object is made available in the Velocity page templates using the name $format.

To specify a custom format class configure a format element in the click-app descriptor. For example:

<click-app>
  ..
  <format classname="com.mycorp.util.CustomFormat"/>
</click-app>

5.2.6. Mode

The optional mode element defines the application logging and caching mode.

<!ELEMENT mode (#PCDATA)>
    <ATTLIST mode value (production|profile|development|debug|trace) "development">

By default Click applications run in development mode, which switches off page template caching, and the logging level is set to INFO.

To change the default application mode configure a mode element in the click-app descriptor. For example to specify production mode you would add the following mode element:

<click-app>
  ..
  <mode value="production">
</click-app>

The application mode configuration can be overridden by setting the system property "click.mode". This can be use in the scenario of debugging a problem on a production system, where you change the mode to trace by setting the following system property and restarting the application.

-Dclick.mode=trace

The Click Application modes and their settings for Page auto loading, template caching and logging levels are:

Application mode

Page auto loading

Template caching

Click log level

Velocity log level

production

No

Yes

WARN

ERROR

profile

No

Yes

INFO

ERROR

development

Yes

No

INFO

ERROR

debug

Yes

No

DEBUG

ERROR

trace

Yes

No

TRACE

WARN

5.2.6.1. Page Auto Loading

When Page Auto Loading is enabled any new page templates and classes will be automatically loaded at runtime. These pages are loaded using the Page Automapping rules.

Page auto loading is a very handy feature for rapid development as you do not have to restart you application server to pick up new pages.

5.2.6.2. Click and Velocity Logging

The Click and Velocity runtimes use LogService for logging messages. The default LogService implementation is ConsoleLogService which will send messages to the console [System.out]. For example the following logging output is for a HomePage request when the application mode is trace:

[Click] [debug] GET http://localhost:8080/quickstart/home.htm
[Click] [trace]    invoked: HomePage.<<init>>
[Click] [trace]    invoked: HomePage.onSecurityCheck() : true
[Click] [trace]    invoked: HomePage.onInit()
[Click] [trace]    invoked: HomePage.onGet()
[Click] [trace]    invoked: HomePage.onRender()
[Click] [info ]    renderTemplate: /home.htm - 6 ms
[Click] [trace]    invoked: HomePage.onDestroy()
[Click] [info ] handleRequest:  /home.htm - 24 ms

Any unhandled Throwable errors are logged by the ClickServlet.

Note that Click Extras also provide log adaptors for Log4J and the JDK Logging API.

When an application is not in production mode the error page displays detailed debugging information. When the application mode is production no debug information is displayed to prevent sensitive information being revealed. This behaviour can be changed by modifying the deployed click/error.htm page template.

5.2.7. Controls

The optional controls element defines a list of control elements which will be deployed on application startup.

<!ELEMENT controls (control*)>

The control registers Control classes which will have their onDeploy() method invoked when the click application starts.

<!ELEMENT control (#PCDATA)>
   <!ATTLIST control classname CDATA #REQUIRED>

For example to have a CustomField control deploy its resources on application startup, you would add the following elements to your click.xml file:

<click-app>
   ..

   <controls>
     <control classname="com.mycorp.control.CustomField"/>
   </controls>
</click-app>