net.sf.click
Class Page

java.lang.Object
  extended bynet.sf.click.Page
Direct Known Subclasses:
ErrorPage, XmlConfigService.ExcludePage

public class Page
extends Object

Provides the Page request event handler class.

The Page class plays a central role in Click applications defining how the application's pages are processed and rendered. All application pages must extend the base Page class, and provide a no arguments constructor.

Page Execution Sequence

The default Page execution path for a GET request is:
  1. no-args constructor invoked to create a new Page instance. At this point no dependencies have been injected into the Page, and any request information is not available. You should put any "static" page initialization code, which doesn't depend upon request information, in the constructor. This will enable subclasses to have this code automatically initialized when they are created.
  2. format property is set
  3. headers property is set
  4. path property is set
  5. onSecurityCheck() method called to check whether the page should be processed. This method should return true if the Page should continue to be processed, or false otherwise.
  6. onInit() method called to complete the initialization of the page after all the dependencies have been set. This is where you should put any "dynamic" page initialization code which depends upon the request or any other dependencies.

    Form and field controls must be fully initialized by the time this method has completed.

  7. ClickServlet processes all the page controls calling their Control.onProcess() method. If any of these controls return false, continued control and page processing will be aborted.
  8. onGet() method called for any additional GET related processing.

    Form and field controls should NOT be created or initialized at this point as the control processing stage has already been completed.

  9. onRender() method called for any pre-render processing. This method is often use to perform database queries to load information for rendering tables.

    Form and field controls should NOT be created or initialized at this point as the control processing stage has already been completed.

  10. ClickServlet renders the page merging the model with the Velocity template defined by the getTemplate() property.
  11. onDestroy() method called to clean up any resources. This method is guaranteed to be called, even if an exception occurs. You can use this method to close resources like database connections or Hibernate sessions.
For POST requests the default execution path is identical, except the onPost() method is called instead of onGet(). The POST request page execution sequence is illustrated below:

A good way to see the page event execution order is to view the log when the application mode is set to 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  

Rendering Pages

When a Velocity template is rendered the ClickServlet uses Pages: These Page properties are also used when rendering JSP pages.

Author:
Malcolm Edgar

Field Summary
protected  List controls
          The list of page controls.
protected  Format format
          The Velocity template formatter object.
protected  String forward
          The forward path.
protected  Map headers
          The HTTP response headers.
protected  boolean headersEdited
          The headers have been edited flag, to support copy on write.
protected  MessagesMap messages
          The map of localized page resource messages.
protected  Map model
          The page model.
static String PAGE_MESSAGES
          The global page messages bundle name:   click-page.
protected  PageImports pageImports
          The Page header imports.
protected  String path
          The path of the page template to render.
protected  String redirect
          The redirect path.
protected  boolean stateful
          The page is stateful and should be save to the users HttpSession between requests.
protected  String template
          The path of the page border template to render.
 
Constructor Summary
Page()
           
 
Method Summary
 void addControl(Control control)
          Add the control to the page.
 void addModel(String name, Object value)
          Add the named object value to the Pages model map.
 String getContentType()
          Return the HTTP response content type.
 Context getContext()
          Return the request context of the page.
 List getControls()
          Return the list of page Controls.
 Format getFormat()
          Return the Velocity template formatter object.
 String getForward()
          Return the path to forward the request to.
 Map getHeaders()
          Return the map of HTTP header to be set in the HttpServletResponse.
 String getHtmlImports()
          Return the HTML import string to include in the page, by default this method returns null.
 String getMessage(String key)
          Return the localized Page resource message for the given resource property key.
 String getMessage(String name, Object arg)
          Return the formatted page message for the given resource name and message format argument and for the context request locale.
 String getMessage(String name, Object[] args)
          Return the formatted page message for the given resource name and message format arguments and for the context request locale.
 Map getMessages()
          Return a Map of localized messages for the Page.
 Map getModel()
          Return the Page's model map.
 PageImports getPageImports()
          Return the Page header imports.
 String getPath()
          Return the path of the Template or JSP to render.
 String getRedirect()
          Return the path to redirect the request to.
 String getTemplate()
          Return the path of the page border template to render, by default this method returns getPath().
 boolean hasControls()
          Return true if the page has any controls defined.
 boolean isStateful()
          Return true if the page is stateful and should be saved in the users HttpSession between requests.
 void onDestroy()
          The on Destroy request event handler.
 void onGet()
          The on Get request event handler.
 void onInit()
          The on Initialization event handler.
 void onPost()
          The on Post request event handler.
 void onRender()
          The on render event handler.
 boolean onSecurityCheck()
          The on Security Check event handler.
 void removeControl(Control control)
          Remove the control from the page.
 void setFormat(Format value)
          Set the Velocity template formatter object.
 void setForward(Class pageClass)
          Set the request to forward to the given page class.
 void setForward(Page page)
          The Page instance to forward the request to.
 void setForward(String value)
          Set the path to forward the request to.
 void setHeader(String name, Object value)
          Set the named header with the given value.
 void setHeaders(Map value)
          Set the map of HTTP header to be set in the HttpServletResponse.
 void setPageImports(PageImports pageImports)
          Set the Page header imports.
 void setPath(String value)
          Set the path of the Template or JSP to render.
 void setRedirect(Class pageClass)
          Set the request to redirect to the give page class.
 void setRedirect(String location)
          Set the location to redirect the request to.
 void setStateful(boolean stateful)
          Set whether the page is stateful and should be saved in the users HttpSession between requests.
 void setTemplate(String template)
          Set the page border template path.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

PAGE_MESSAGES

public static final String PAGE_MESSAGES
The global page messages bundle name:   click-page.

See Also:
Constant Field Values

controls

protected List controls
The list of page controls.


format

protected Format format
The Velocity template formatter object.


forward

protected String forward
The forward path.


headers

protected Map headers
The HTTP response headers.


headersEdited

protected boolean headersEdited
The headers have been edited flag, to support copy on write.


messages

protected transient MessagesMap messages
The map of localized page resource messages.


model

protected Map model
The page model. For Velocity templates the model is used to populate the Velocity context. For JSP pages the model values are set as named request attributes.


pageImports

protected transient PageImports pageImports
The Page header imports.


path

protected String path
The path of the page template to render.


redirect

protected String redirect
The redirect path.


stateful

protected boolean stateful
The page is stateful and should be save to the users HttpSession between requests.


template

protected String template
The path of the page border template to render.

Constructor Detail

Page

public Page()
Method Detail

onSecurityCheck

public boolean onSecurityCheck()
The on Security Check event handler. This event handler is invoked after the pages constructor has been called and all the page properties have been set.

Security check provides the Page an opportunity to check the users security credentials before processing the Page.

If security check returns true the Page is processed as normal. If the method returns then no other event handlers are invoked (except onDestroy() and no page controls are processed.

If the method returns false, the forward or redirect property should be set to send the request to another Page.

By default this method returns true, subclass may override this method to provide their security authorization/authentication mechanism.

Returns:
true by default, subclasses may override this method

onInit

public void onInit()
The on Initialization event handler. This event handler is invoked after the onInit() method has been called.

Subclasses should place any initialization code which has dependencies on the context or other properties in this method. Generally light weight initialization code should be placed in the Pages constructor.

Time consuming operations such as fetching the results of a database query should not be placed in this method. These operations should be performed in the onRender(), onGet() or onPost() methods so that other event handlers may take alternative execution paths without performing these expensive operations.

Please Note however the qualifier for the previous statement is that all form and field controls must be fully initialized before they are processed, which is after the onInit() method has completed. After this point their onProcess() methods will be invoked by the ClickServlet.

Select controls in particular must have their option list values populated before the form is processed otherwise field validations cannot be performed.

For initializing page controls the best practice is to place all the control creation code in the pages constructor, and only place any initialization code in the onInit() method which has an external dependency to the context or some other object. By following this practice it is easy to see what code is "design time" initialization code and what is "runtime initialization code".

When subclassing pages which also use the onInit() method is is critical you call the super.onInit() method first, for example:

 public void onInit() {
     super.onInit();

     // Initialization code
     ..
 } 


onGet

public void onGet()
The on Get request event handler. This event handler is invoked if the HTTP request method is "GET".

The event handler is invoked after onSecurityCheck() has been called and all the Page controls have been processed. If either the security check or one of the controls cancels continued event processing the onGet() method will not be invoked.

Important Note

Form and field controls should NOT be created or initialized at this point as the control processing stage has already been completed. Select option list values should also be populated before the control processing stage is performed so that they can validate the submitted values.


onPost

public void onPost()
The on Post request event handler. This event handler is invoked if the HTTP request method is "POST".

The event handler is invoked after onSecurityCheck() has been called and all the Page controls have been processed. If either the security check or one of the controls cancels continued event processing the onPost() method will not be invoked.

Important Note

Form and field controls should NOT be created or initialized at this point as the control processing stage has already been completed. Select option list values should also be populated before the control processing stage is performed so that they can validate the submitted values.


onRender

public void onRender()
The on render event handler. This event handler is invoked prior to the page being rendered.

This method will not be invoked if either the security check or one of the controls cancels continued event processing.

The on render method is typically used to populate tables performing some database intensive operation. By putting the intensive operations in the on render method they will not be performed if the user navigates away to a different page.

If you have code which you are using in both the onGet() and onPost() methods, use the onRender() method instead.

Important Note

Form and field controls should NOT be created or initialized at this point as the control processing stage has already been completed. Select option list values should also be populated before the control processing stage is performed so that they can validate the submitted values.


onDestroy

public void onDestroy()
The on Destroy request event handler. Subclasses may override this method to add any resource clean up code.

This method is guaranteed to be called before the Page object reference goes out of scope and is available for garbage collection.

Stateful pages will have this method invoked before they are saved to the session.


addControl

public void addControl(Control control)
Add the control to the page. The control will be added to the pages model using the controls name as the key. The Controls parent property will also be set to the page instance.

Parameters:
control - the control to add
Throws:
IllegalArgumentException - if the control is null, or if the name of the control is not defined

removeControl

public void removeControl(Control control)
Remove the control from the page. The control will be removed from the pages model and the control parent property will be set to null.

Parameters:
control - the control to remove
Throws:
IllegalArgumentException - if the control is null, or if the name of the control is not defined

getControls

public List getControls()
Return the list of page Controls.

Returns:
the list of page Controls

hasControls

public boolean hasControls()
Return true if the page has any controls defined.

Returns:
true if the page has any controls defined

getContext

public Context getContext()
Return the request context of the page.

Returns:
the request context of the page

getContentType

public String getContentType()
Return the HTTP response content type. By default this method returns "text/html".

If the request specifies a character encoding via If ServletRequest.getCharacterEncoding() then this method will return "text/html; charset=encoding".

The ClickServlet uses the pages content type for setting the HttpServletResponse content type.

Returns:
the HTTP response content type

getFormat

public Format getFormat()
Return the Velocity template formatter object.

The ClickServlet adds the format object to the Velocity context using the key "format" so that it can be used in the page template.

Returns:
the Velocity template formatter object

setFormat

public void setFormat(Format value)
Set the Velocity template formatter object.

Parameters:
value - the Velocity template formatter object.

getForward

public String getForward()
Return the path to forward the request to.

If the forward property is not null it will be used to forward the request to in preference to rendering the template defined by the path property. The request is forwarded using the RequestDispatcher.

See also getPath(), getRedirect()

Returns:
the path to forward the request to

setForward

public void setForward(String value)
Set the path to forward the request to.

If the forward property is not null it will be used to forward the request to in preference to rendering the template defined by the path property. The request is forwarded using the Servlet RequestDispatcher.

If forward paths start with a "/" character the forward path is relative to web applications root context, otherwise the path is relative to the requests current location.

For example given a web application deployed to context mycorp with the pages:

  /index.htm
  /customer/search.htm
  /customer/details.htm
  /customer/management/add-customer.htm 
To forward to the customer search.htm page from the web app root you could set forward as setFoward("/customer/search.htm") or setFoward("customer/search.htm").

If a user was currently viewing the add-customer.htm to forward to customer details.htm you could set forward as setFoward("/customer/details.htm") or setFoward("../details.htm").

See also setPath(String), setRedirect(String)

Parameters:
value - the path to forward the request to

setForward

public void setForward(Page page)
The Page instance to forward the request to. The given Page object must have a valid path defined, as the path specifies the location to forward to.

Parameters:
page - the Page object to forward the request to.
See Also:
setForward(java.lang.String)

setForward

public void setForward(Class pageClass)
Set the request to forward to the given page class.

Parameters:
pageClass - the class of the Page to forward the request to
Throws:
IllegalArgumentException - if the Page Class is not configured with a unique path
See Also:
setForward(java.lang.String)

getHeaders

public Map getHeaders()
Return the map of HTTP header to be set in the HttpServletResponse. Note to edit header values use setHeader(String, Object) as headers Map is initially unmodifiable.

Returns:
the map of HTTP header to be set in the HttpServletResponse

setHeader

public void setHeader(String name,
                      Object value)
Set the named header with the given value. This method uses copy on write to the headers Map, as the initial loaded headers Map is unmodifiable.

Parameters:
name - the name of the header
value - the value of the header

setHeaders

public void setHeaders(Map value)
Set the map of HTTP header to be set in the HttpServletResponse.

Parameters:
value - the map of HTTP header to be set in the HttpServletResponse

getHtmlImports

public String getHtmlImports()
Return the HTML import string to include in the page, by default this method returns null.

Override this method to specify JavaScript and CSS includes for the page. For example:

 public MyPage extends Page {

     // Define a constant for the Page Javascript import.
     protected static final String JAVASCRIPT_IMPORT =
         "<script type='text/javascript' src='{0}/click/my-page.js'></script>\n";

     // Define a constant for the Page CSS import
     protected static final String CSS_IMPORT =
         "<link type='text/css' rel='stylesheet' href='text/css' src='{0}/click/my-page.css'/>\n";

     ...

     // Override getHtmlImports and return the Javascript and CSS imports.
     public String getHtmlImports() {
         Context context = getContext();

         // Concatenate Javascript and CSS imports
         return ClickUtils.createHtmlImport(MyPage.JAVASCRIPT_IMPORT, ClickUtils.getResourceVersionIndicator(), context)
         + ClickUtils.createHtmlImport(MyPage.CSS_IMPORT, ClickUtils.getResourceVersionIndicator(), context);
     }
 } 
Note multiple import lines should be separated by a '\n' char, as the PageImports will parse multiple import lines on the '\n' char and ensure that imports are not included twice.

The order in which JS and CSS files are include will be preserved in the page.

If you need to customize the HTML imports included in your page override the method getPageImports().

Returns:
the HTML includes statements for the control stylesheet and JavaScript files, by default this method returns null

getMessage

public String getMessage(String key)
Return the localized Page resource message for the given resource property key. The resource message returned will use the Locale obtained from the Context.

Pages can define text properties files to store localized messages. These properties files must be stored on the Page class path with a name matching the class name. For example:

The page class:

  package com.mycorp.pages;

  public class Login extends Page {
     .. 
The page class property filenames and their path:
  /com/mycorp/pages/Login.properties
  /com/mycorp/pages/Login_en.properties
  /com/mycorp/pages/Login_fr.properties 
Page messages can also be defined in the optional global messages bundle:
  /click-page.properties 
To define global page messages simply add click-page.properties file to your application's class path. Message defined in this properties file will be available to all of your application pages.

Note messages in your page class properties file will override any messages in the global click-page.properties file.

Page messages can be accessed directly in the page template using the $messages reference. For examples:

 $messages.title 
Please see the MessagesMap adaptor for more details.

Parameters:
key - the message property key name
Returns:
the Page message for the given message property key

getMessage

public String getMessage(String name,
                         Object arg)
Return the formatted page message for the given resource name and message format argument and for the context request locale.

Parameters:
name - resource name of the message
arg - the message argument to format
Returns:
the named localized message for the page

getMessage

public String getMessage(String name,
                         Object[] args)
Return the formatted page message for the given resource name and message format arguments and for the context request locale.

Parameters:
name - resource name of the message
args - the message arguments to format
Returns:
the named localized message for the page

getMessages

public Map getMessages()
Return a Map of localized messages for the Page.

Returns:
a Map of localized messages for the Page
Throws:
IllegalStateException - if the context for the Page has not be set
See Also:
getMessage(String)

addModel

public void addModel(String name,
                     Object value)
Add the named object value to the Pages model map.

Parameters:
name - the key name of the object to add
value - the object to add
Throws:
IllegalArgumentException - if the name or value parameters are null, or if there is already a named value in the model

getModel

public Map getModel()
Return the Page's model map. The model is used populate the Velocity Context with is merged with the page template before rendering.

Returns:
the Page's model map

getPageImports

public PageImports getPageImports()
Return the Page header imports.

PageImports are used define the CSS and JavaScript imports and blocks to be included in the page template.

The PageImports object will be included in the Page template when the following methods are invoked:

If you need to tailor the page imports rendered, override this method and modify the PageImports object returned.

If you need to create a custom PageImports, override the method ClickServlet.createPageImports(net.sf.click.Page)

Returns:
the Page header imports

setPageImports

public void setPageImports(PageImports pageImports)
Set the Page header imports.

PageImports are used define the CSS and JavaScript imports and blocks to be included in the page template.

The PageImports references will be included in the Page model when the following methods are invoked:

If you need to tailor the page imports rendered, override the getPageImports() method and modify the PageImports object returned.

If you need to create a custom PageImports, override the method ClickServlet.createPageImports(net.sf.click.Page)

Parameters:
pageImports - the new pageImports instance to set

getPath

public String getPath()
Return the path of the Template or JSP to render.

If this method returns null, Click will not perform any rendering. This is useful when you want to stream or write directly to the HttpServletResponse.

See also getForward(), getRedirect()

Returns:
the path of the Template or JSP to render

setPath

public void setPath(String value)
Set the path of the Template or JSP to render.

By default Click will set the path to the requested page url. Meaning if the url /edit-customer.htm is requested, path will be set to /edit-customer.htm.

Here is an example if you want to change the path to a different Template:

 public void onGet() {
     setPath("/some-other-template.htm");
 }
And here is an example if you want to change the path to a different JSP.
 public void onGet() {
     setPath("/some-other-jsp.jsp");
 }

If path is set to null, Click will not perform any rendering. This is useful when you want to stream or write directly to the HttpServletResponse.

See also setForward(String), setRedirect(String)

Parameters:
value - the path of the Template or JSP to render

getRedirect

public String getRedirect()
Return the path to redirect the request to.

If the redirect property is not null it will be used to redirect the request in preference to forward or path properties. The request is redirected to using the HttpServletResponse.setRedirect() method.

See also getForward(), getPath()

Returns:
the path to redirect the request to

isStateful

public boolean isStateful()
Return true if the page is stateful and should be saved in the users HttpSession between requests.

Returns:
true if the page is stateful and should be save in the users session

setStateful

public void setStateful(boolean stateful)
Set whether the page is stateful and should be saved in the users HttpSession between requests.

Click will synchronize on the page instance. This ensures that if multiple requests arrive from the same user for the page, only one request can access the page at a time.

Stateful pages are stored in the HttpSession using the key page.getClass().getName().

It is worth noting that Click checks a Page's stateful property after each request. Thus it becomes possible to enable a stateful Page for a number of request and then setting it to false again. Click will remove the Page from the HttpSession, freeing up memory for the server.

Parameters:
stateful - the flag indicating whether the page should be saved between user requests

setRedirect

public void setRedirect(String location)
Set the location to redirect the request to.

If the redirect property is not null it will be used to redirect the request in preference to forward or path properties. The request is redirected to using the HttpServletResponse.setRedirect() method.

If the redirect location begins with a "/" character the redirect location will be prefixed with the web applications context path.

For example if an application is deployed to the context "mycorp" calling setRedirect("/customer/details.htm") will redirect the request to: "/mycorp/customer/details.htm"

If the redirect location does not begin with a "/" character the redirect location will be used as specified. Thus if the location is http://somehost.com/myapp/customer.jsp, Click will redirect to that location.

JSP note: when redirecting to a JSP template keep in mind that the JSP template won't be processed by Click, as ClickServlet is mapped to *.htm. Instead JSP templates are processed by the Servlet container JSP engine.

So if you have a situation where a Page Class (Customer.class) is mapped to the JSP ("/customer.jsp") and you want to redirect to Customer.class, you could either redirect to ("/customer.htm") or use the alternative redirect utility setRedirect(java.lang.Class).

Please note that Click will url encode the location by invoking response.encodeRedirectURL(location) before redirecting.

See also setForward(String), setPath(String)

Parameters:
location - the path to redirect the request to

setRedirect

public void setRedirect(Class pageClass)
Set the request to redirect to the give page class.

Parameters:
pageClass - the class of the Page to redirect the request to
Throws:
IllegalArgumentException - if the Page Class is not configured with a unique path
See Also:
setRedirect(java.lang.String)

getTemplate

public String getTemplate()
Return the path of the page border template to render, by default this method returns getPath().

Pages can override this method to return an alternative border page template. This is very useful when implementing an standardized look and feel for a web site. The example below provides a BorderedPage base Page which other site templated Pages should extend.

 public class BorderedPage extends Page {
     public String getTemplate() {
         return "border.htm";
     }
 } 
The BorderedPage returns the page border template "border.htm":
 <html>
   <head>
     <title> $title </title>
     <link rel="stylesheet" type="text/css" href="style.css" title="Style"/>
   </head>
   <body>

     <h1> $title </h1>
     <hr/>

     #parse( $path )

   </body>
 </html> 
Other pages insert their content into this template, via their path property using the Velocity #parse directive. Note the $path value is automatically added to the VelocityContext by the ClickServlet.

Returns:
the path of the page template to render, by default returns getPath()

setTemplate

public void setTemplate(String template)
Set the page border template path.

Note: if this value is not set, getTemplate() will default to getPath().

Parameters:
template - the border template path