Base UI Modules

The Toolkit provides a set of base UI modules and helper classes that encapsulate event handling and presentation. They form the foundation for custom application development. For example, the UI in the FileNet P8 Workplace application is built on the base UI modules in the Toolkit. The following screenshot shows the collective output of multiple Workplace-specific subclasses, which derive from base Toolkit UI modules indicated in bold. (The Workplace classes shown do not directly extend the base modules.)

output of multiple UI modules

The Toolkit base UI modules:

See Also
Containment
Toolkit Implementation of MVC

Class Hierarchy

As shown in the class diagram below, all UI modules derive from WcmUiModule, which defines base UI behavior. It, in turn, derives from GlobalEventModule, which subscribes to and receives global events, that is, an event that the framework dispatches to multiple UI modules. All UI modules inherit the ability to subscribe to and receive global events. The classes that derive from GlobalEventModule are packaged in com.filenet.wcm.toolkit.server.ui.

The classes in blue (top right) have default implementations that you can use out of the box:

The classes in green (bottom) are defined to be subclassed, providing behavior but no presentation:

Note that GlobalEventModule, WcmModule, and WcmController derive from WcmDpContainer, which are in the same base package, com.filenet.wcm.toolkit.server.base. WcmDpContainer offers data provider binding functionality to all classes that derive from it. The addDataProvider(...) and queryDataProvider(...) methods are implemented in this base class.

The base controller module, WcmController, derives from WcmDpContainer as a convenience for indirect binding to a data provider. That is, if every module on a page requires the same data provider, you need only bind the data provider to the controller, and the other modules on the page can access the data provider as well.

class diagram

See Also
Toolkit Packages

Containment

The Toolkit provides a mechanism for organizing UI modules into a containment hierarchy, with one UI module encapsulating one or more child UI modules. The illustration below illustrates a containment relationship in the FileNet P8 Workplace application. Using the addChild(...) method, WcmPathNavigation contains UI modules that render the path and toolbar. A member of WcmModule module, the addChild(...) method adds the specified module as a child to the calling module, and registers the specified module with the controller.

containment relationship

See Also
Containment: Routing an Event to the Parent

Anchor List Modules

The Toolkit includes base UI modules for adding non-hierarchical lists of HTML anchors (hypertext links), as shown in the following graphic.

The key class is WcmAnchorList, a base UI module that contains WcmAnchor objects (addAnchor( )), and provides callbacks for Java-based rendering. A WcmAnchor object represents an HTML text link anchor tag, and provides methods for constructing links. A WcmAnchor object can be constructed by specifying the URL as a String or as a WcmURL object.

A subclass of WcmAnchorList is WcmSelectableAnchorList. This subclass provides a selection property to track the currently selected option in a list of anchors. WcmAnchorList and WcmSelectableAnchorList provide a callback framework that can be used for Java-based rendering. Both WcmAnchorList and WcmSelectableAnchorList are declared as abstract.

Anchor Tree Modules

The Toolkit includes base UI modules for creating cascading menus and trees of anchors (HTML hypertext links). The following graphic shows a tree of anchors built from Toolkit modules.

tree of links

Most of this work is done by WcmAnchorTree, which includes methods for adding and removing WcmTreeNode objects, and provides callbacks for Java-based rendering. WcmAnchorTree can contain WcmTreeNode objects as root nodes (addRootNode( )) or as child nodes (addChildNode( )). WcmAnchorTree is declared as abstract.

WcmTreeNode is the building block for an anchor tree. It contains a single WcmAnchor representing the link associated with it, and a list of 0..n child tree nodes representing the continuation of the hierarchy.

Page Layout Modules

The Toolkit provides base UI modules for organizing page layouts into user-definable regions. The graphic below is a page from the FileNet P8 Workplace application. Note that you can add one or more UI modules to regions in the layout

page layout

The Toolkit includes two classes for laying out and rendering pages into regions:

Multi-Panel Modules

The Toolkit includes multi-panel modules, base classes that provide containment and paging of two or more contained UI modules. They can be used for sequential paging UIs such as wizards, or non-sequential, multi-page property sheets. The screenshots below from the FileNet P8 Workplace application show a UI with two non-sequential panels: System Properties and Root Folder Security.

multi-panel UI

The primary multi-panel module is WcmMultiPanelModule, an abstract class that must be subclassed. WcmMultiPanelModule can contain one or more UI modules (addPanel(...)), persists a current panel value in the session, and retrieves the page to return to in the onExit(...) method. For onExit(...) to have a return URL, the page must be initiated passing a "returnUrl" (WcmParameter.RETURN_URL) request parameter that specifies the page to return to, if defined.

WcmMultiPanelModule is subclassed by the following classes:

WcmMultiPanelViewModule and WcmMultiPanelSequenceModule are abstract and must be subclassed.

XSLT-Based Rendering

The Toolkit includes a base class for XSLT rendering. As the simplified diagram below shows, XML data is passed to a WcmXSLModule subclass, which uses an XSLT stylesheet to output HTML. The WcmXSLModule class includes properties and accessor methods for setting the XML to be rendered (setXML(...)) and the XSL stylesheet to be used (setXSL(...)).

Note that all of the WcmXSLModule methods call into the helper class WcmXSLUtil (not shown). WcmXSLUtil does the actual work, calling into the XSL processor to perform the transformations. By leveraging this helper class, you can provide XSL transformation behavior in any UI module.

XSLT rendering diagram

JSP-Based Rendering

UI modules can delegate rendering to JSP pages. As the diagram below shows, the UI module is a subclass of WcmUiModule, which includes the setJSP(...) method. In its initialize() method, the UI module calls setJSP(...) to specify the JSP page that will render the output of the UI module. The rendering JSP is referred to as the UI module JSP.

At the rendering phase, the UI module JSP calls the static method WcmJSPModule .getCurrentModule(...), which returns an instance of the UI module subclass. WcmJSPModule is also a subclass of WcmUiModule. The XML data passed to the UI module is rendered by the UI module JSP.

JSP-based rendering diagram

See Also
XSLT-Based Rendering

Creating a UI Module

This section takes you through the general steps of creating a high-level UI module and deploying it in a framework JSP page. For details on a particular step, click the applicable link.

  1. Subclass a UI module.
  2. Override Methods.
  3. Add Event Handlers.
  4. Deploy on Framework Pages.

Subclass a UI Module

The base behavior for all UI modules is implemented in WcmUiModule, which implements WcmUiModuleInterface. A UI module by definition is an object that is an instance of WcmUiModule. Any UI module can be subclassed to create a new UI module.

public class MyUIModule extends WcmUiModule
{
   ...
}

The object lifespan of a UI module is the duration of the request, but the lifespan of a UI module's stateful data is for the duration of the user JSP session. A UI module object contains these features:

Override Methods

Override applicable methods to code the specific functionality not found in the superclass, and implement interface methods, if any. Note that the methods listed below must be included in or inherited by your subclass. For details on a method, click the applicable link.

initialize method

package mypackage;
public class MyUIModule extends WcmUiModule
{
  public void initialize() throws Exception
  {
    super.initialize(); // Never forget this!
    // initialize from stateful data.
  }
}


onStartPage method

package mypackage;
public class MyUIModule extends WcmUiModule
{
  ...
  public void onStartPage(HttpServletRequest request,
      HttpServletResponse response) throws Exception
    {
      super.onStartPage(request, response);
      // prepare for rendering (queries)
    }
}


render method
package mypackage;
public class MyUIModule extends WcmUiModule
{
   ...
   public void render(Writer w) throws Exception
   {
      w.write("<br><center>Hello World.</center><br>");
   }
}

See Also
Event URLs
XSLT-Based Rendering
JSP-Based Rendering

Add Event Handler

The framework supports targeted and global event URLs. A targeted event URL is addressed to a specific, single UI module on a page, whereas a global event URL is routed to multiple UI modules that have subscribed to the same event. Also, in a containment relationship, the framework provides methods for a UI module to route an event to its parent to handle.

This section provides code examples for handling a targeted event, a global event, and an event routed from a child UI module to its parent.

Event Targeted to Single UI Module

The code example below shows three methods that work in conjunction to generate event URLs and to process a click event targeted to a UI module called MyUIModule. The initialize( ) method calls the getModuleProperty( ) method. Inherited from WcmModule, this method returns the text stored in the data store identified by the "valueKey" key. If there is not already an existing value, a default string ("Hello World") is set. When the user requests the framework event JSP page for the first time, "Hello World" will be rendered.

The onClick( ) event handler gets a value passed to it in an HTTP request and assigns the value to a variable. The method then calls setModuleProperty( ), also inherited from WcmModule. The setModuleProperty( ) method passes the variable value to the data store, which associates the value with the "valueKey" key. One of two values can be assigned to the "valueKey" key at any one time: either "Value One" or "Value Two", depending on which event URL is passed in the HTTP request.

The render( ) method writes out the value selected by the end user ("Value One" or "Value Two"), along with the two event URLs that present the user with a click event. Note that a getEventURL( ) method assembles the URL based on the event name and the value to be passed in the HTTP request. Implemented in WcmUiModule, several getEventUrl( ) methods are available. Use these methods; never hardcode event URLs.

package mypackage;
public class MyUIModule extends WcmUiModule
{
   private String value;
   public void initialize() throws Exception
   {
      value = getModuleProperty("valueKey", "Hello world.");
      super.initialize(); // Never forget this!
      // initialize from stateful data.
   }

   ...
   public void onClick(HttpServletRequest request, HttpServletResponse response) throws Exception
   {
      String tmp = request.getParameter("value");
      if ( tmp != null )
      {
         value = tmp;
         setModuleProperty("valueKey", value);
      }
   }

   ...
   public void render(Writer w) throws Exception
   {
      String eventURL1 = getEventUrl("Click", "value=Value%20One");
      String eventURL2= getEventUrl("Click", "value=Value%20Two");
      w.write("<br>" + value + "<br><br>");
      w.write("<a href='" + eventURL1 + "'>Value One</a><br>");
      w.write("<a href='" + eventURL2 + "'>Value Two</a><br>");
   }
}
Global Event

The next code example illustrates a global event, where two UI modules handle the same event. In its initialize() method, each module subscribes to the "Click" global event, calling the subscribeGlobalEvent(...) method inherited from the GlobalEventModule base class. Each event handler is passed an GlobalEvent object, which references the request and response objects. In the example, each handler gets the value of a request parameter, assigns the value to a variable, and calls setModuleProperty( ) to save the value in the data store.

UI Module 1 UI Module 2
package mypackage;
public class MyUIModule1 extends WcmUiModule
{
private String value1;
public void initialize() throws Exception
{
   subscribeGlobalEvent("Click");
   value1 = getModuleProperty("value1Key",
      "Hello Earth");
   super.initialize();
   // initialize from stateful data.
}

...
public void onClick(GlobalEvent evt)
{
   String tmp = evt.request.getParameter("value1");
   if ( tmp != null )
   {
      value1 = tmp;
      setModuleProperty("value1Key", value1);
   }
}

   ...
public void render(Writer w) throws Exception
{
   String eventURL = getEventUrl("Click",
      "value1=Value1%20One");
   w.write("<br>" + value1 + "<br><br>");
   w.write("<a href='" + eventURL + "'>
      Value One</a><br>");
}
package mypackage;
public class MyUIModule2 extends WcmUiModule
{
private String value2;
public void initialize() throws Exception
{
   subscribeGlobalEvent("Click");
   value2 = getModuleProperty("value2Key",       "Hello Mars");
   super.initialize();
   // initialize from stateful data.
}

...
public void onClick(GlobalEvent evt)
{
   String tmp = evt.request.getParameter("value2");
   if ( tmp != null )
   {
      value2 = tmp;
      setModuleProperty("value2Key", value2);
   }
}

   ...
public void render(Writer w) throws Exception
{
   String eventURL2= getEventUrl("Click",
      "value2=Value2%20Two");
   w.write("<br>" + value2 + "<br><br>");
   w.write("<a href='" + eventURL + "'>
      Value Two</a><br>");
}

See Also
Global Event sample in Basic Toolkit Samples. See Sample Applications for downloading instructions.

Containment: Routing an Event to the Parent

In a child UI module, you can route an event to the parent module with the following WcmUiModule methods: getUiParent() and routeEvent(...). For example:

public void onAddSelection(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
   WcmUiModuleInterface parent = getUiParent();
   if ( parent != null )
      parent.routeEvent("AddSelection", request, response);
}

Deploy on Framework Page

Deploy the UI module(s) on a framework page, consisting of an event JSP page and a UI JSP page. The following code examples show an event JSP and UI JSP, in which two UI modules are declared, registered, and rendered.

<%@ page errorPage="/WcmError.jsp" autoFlush="false" %>

<jsp:useBean
   id="myModule1"
   class="mypackage.MyUIModule1"
   scope="request"/>
   <jsp:setProperty name="myModule1" property="name" value="myModule1"/>
<jsp:useBean/>

<jsp:useBean
   id="myModule2"
   class="mypackage.MyUIModule2"
   scope="request"/>
   <jsp:setProperty name="myModule2" property="name" value="myModule2"/>
<jsp:useBean/>

<jsp:useBean
   id="controller"
   class="mypackage.MyController"
   scope="request"/>
<jsp:useBean/>

<%
   controller.configurePage(application, request);
   controller.getHeaderModule().setTitle("Hello World Page");
   controller.registerModule(myModule1);
   controller.registerModule(myModule2);
   controller.handleEvent(application, request, response, true);
%>

In the following UI JSP listing, two UI modules are rendered in successive order.

<%@ page errorPage="/WcmError.jsp" autoFlush="true"
    contentType="text/html; charset=UTF-8"
    import="com.filenet.wcm.toolkit.server.util.*"
%>

<html>
   <head>
      <% WcmUI.renderHeaders(request, out);%>
   </head>

   <body class="wcmBody" bgcolor="white">
      <% WcmUi.render(request, "myModule1", out);%>
      <% WcmUi.render(request, "myModule2", out);%>
   </body>
</html>

Leveraging Workplace Presentation Behavior

In Workplace, the modules that define presentation behavior are abstracted from the Workplace modules that render HTML. Depending on your UI requirements, it may be more efficient to leverage the FileNet P8 Workplace presentation behavior rather than directly subclass the base UI modules and define custom presentation behavior.

The Workplace modules defining presentation behavior are packaged in com.filenet.wcm.apps.server.presentation.ui and com.filenet.wcm.apps.server.presentation.util. They are distributed in p8workplacePresentation.jar, located in the Workplace/WEB-INF/lib directory.

The following Workplace screenshot points out many of the modules that are distributed in p8workplacePresentation.jar. Note that these modules do not render the graphical elements in the UI, but rather define the Workplace presentation behavior. They extend the Toolkit's base UI modules. For example, BannerBar, PathView, TabBar, and ToolBar extend WcmAnchorList (see Anchor List Modules). TreeView extends WcmAnchorTree (see Anchor Tree Modules). ItemsListView extends WcmXSLModule (see XSLT-Based Rendering). ContextMenu, Footer, and FooterLinksBar extend WcmUiModule (see Class Hierarchy). HeaderModule extends WcmHeaderModule (see HTML Headers -- Using Default Implementation), and is used to set data and time information in the header tag that is rendered in the banner.

NOTE   HeaderModule and other presentation components provide additional functions, including a JavaScript control for entering date and time from the browser. See Date/Time API.

Not shown in the screenshot is WorkplaceLayout, which defines a set of layout regions (TOP_REGION, MIDDLE_REGION, BOTTOM_REGION, and so on) for rendering Workplace pages. WorkplaceLayout extends WcmLayout, the base implementation of a UI layout (see Page Layout Modules).

presentation behavior modules

Date/Time API

As mentioned in Leveraging Workplace Presentation Behavior, the p8workplacePresentation.jar includes API components that perform date and time display, input, and processing. Most notable of these features is the date/time control, a JavaScript-rendered calendar configured by the date/time API components. As shown in the following screenshot, the calendar control is invoked by a browser user to enter time and date settings.

calendar control

You access the date/time API from UI modules. This section covers the following topics:

Date/Time Components

Using the Date/Time API

To use the date/time API:

  1. Subclass HeaderModule in your HTML-header class.
  2. In the ConfigurableController's preferences file, p8controller.xml, set the headerModule preference to the fully qualified name of your HTML-header class.
  3. In a UI module, call DateTimeControl.includeHeaders(...) in the initialize() or onStartPage(...) method. For example:
    public void initialize() throws Exception
    {
       Locale locale = (get configured locale);
       super.initialize();
       ...
       DateTimeControl.includeHeaders(getController(), locale);
       ...
    }
  4. In the UI module, use DateTimeControl to perform any of the following functions: display date/time control, retrieve submitted form data, or display date values. See DateTimeControl Examples.

DateTimeControl Examples

This section provides pseudocode examples for:

Displaying Date/Time Control

In a UI module, you can display a JavaScript control for user input into a form. You can display it via Java or XSL. Dates are managed on the server in UTC, and are shifted to the specified time zone when displayed.

NOTE  Any valid time zone ID which is supported by the JDK is available for use in custom applications built with Workplace Application Toolkit. The JDK includes the TimeZone class (representing a time zone offset) that offers methods, such as getAvailableIDs, which can be used to iterate through all of the supported time zone IDs. For more information on obtaining or constructing a valid time zone ID, see the JDK documentation.

Display via Java

For Java or JSP modules, call DateTimeControl.getHTML(...) to render a date/time control.

public void render(Writer w) throws Exception
{
   Locale locale = (get configured locale);
   TimeZone timeZone = (get configured timeZone);
   int dateStyle = (get configured date style);
   int timeStyle = (get configured time style);
   Date currentValue = ...;
   ...
   w.write(DateTimeControl.getHTML(locale, timeZone, dateStyle, timeStyle, "formElementName",
                                   currentValue, null, true));
   ...
}
Display via XSL

For XSL-based UI modules, a template is provided in DateTimeControl.xsl to render a date/time control. Use as in the example shown here.

<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:java="http://xml.apache.org/xslt/java"
   xmlns:wcm="http://filenet.com/namespaces/wcm/apps/1.0"
   exclude-result-prefixes="java wcm" version="1.0">
<xsl:output method="html" encoding="UTF-8"
   omit-xml-declaration="yes" indent="yes"/>
...
<xsl:param name="locale" />
<xsl:param name="timeZone" />
<xsl:param name="dateStyle" />
<xsl:param name="timeStyle" />
...
<xsl:include href="../include/DateTimeControl.xsl" />
...
   <xsl:call-template name="ShowDateTimeControl">
      <xsl:with-param name="elementName" select="$symname" />
      <xsl:with-param name="currentISOValue" select="$value" />
      <xsl:with-param name="dateTimeLocale" select="$locale" />
      <xsl:with-param name="timeZone" select="$timeZone" />
      <xsl:with-param name="dateStyle" select="$dateStyle" />
      <xsl:with-param name="timeStyle" select="$timeStyle" />
   </xsl:call-template>
Retrieving Submitted Form Data

When the form is submitted, the date value in UTC can be retrieved either as a Date object or as a String ISO-formatted date. For example:

public void panelSave(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
   Locale locale = (get configured locale);
   // Retrieve Date object...
   Date dateValue = DateTimeConrol.getDate(locale, request, "formElementName");
   // Retrieve CE style ISO date...
   String isoValue = DateTimeConrol.getISODate(locale, request, "formElementName", false);
   // Retrieve PE style ISO date...
   String compressedISOValue = DateTimeConrol.getISODate(locale, request, "formElementName", true);
}
Displaying Date Values

You can display date values via Java or XSL. Date values on the server are assumed to be UTC, and are shifted to the specified time zone when displayed.

Display via Java

Below is an example of writing out a formatted date value in a Java-based UI module. The getDisplayDate(...) signatures are provided for either a Date object in UTC or an ISO-formatted date String.

public void render(Writer w) throws Exception
{
   Locale locale = (get configured locale);
   TimeZone timeZone = (get configured timeZone);
   int dateStyle = (get configured date style);
   int timeStyle = (get configured time style);
   Date utcDateValue = ...;
   ...
   w.write(DateTimeControl.getDisplayDate(utcDateValue,
       timeZone, locale, dateStyle, timeStyle, true));
   ...
}
Display via XSL

For XSL-based UI modules, a template is provided in DateTimeControl.xsl for writing out a formatted date value. Use as in the example shown here.

<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:java="http://xml.apache.org/xslt/java"
   xmlns:wcm="http://filenet.com/namespaces/wcm/apps/1.0"
   exclude-result-prefixes="java wcm" version="1.0">
   
<xsl:output method="html" encoding="UTF-8" 
   omit-xml-declaration="yes" indent="yes"/>

...

<xsl:param name="locale" />
<xsl:param name="timeZone" />
<xsl:param name="dateStyle" />
<xsl:param name="timeStyle" />

...

<xsl:include href="../include/DateTimeControl.xsl" />

...

<xsl:call-template name="displayFormattedDate">
   <xsl:with-param name="isoDate" select="$value" />
   <xsl:with-param name="dateTimeLocale" select="$locale" />
   <xsl:with-param name="dateStyle" select="$dateStyle" />
   <xsl:with-param name="timeStyle" select="$timeStyle" />
</xsl:call-template>