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.)
The Toolkit base UI modules:
See Also
Containment
Toolkit Implementation of MVC
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.
See Also
Toolkit Packages
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.
See Also
Containment: Routing an Event to the
Parent
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.
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.
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.
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
The Toolkit includes two classes for laying out and rendering pages into regions:
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.
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.
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.
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.
See Also
XSLT-Based Rendering
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.
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 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 methodpackage mypackage;
public class MyUIModule extends WcmUiModule
{
public void initialize() throws Exception
{
super.initialize(); // Never forget this!
// initialize from stateful data.
}
}
- initialize() is a phase notification callback that will be called at the point where the controller is initializing all of the UI modules on the JSP page.
- In initialize(), the UI module has access to its stateful data. Therefore, it can initialize from existing state information via get...Property methods or by direct access to WcmDataStore.
onStartPage methodpackage mypackage;
public class MyUIModule extends WcmUiModule
{
...
public void onStartPage(HttpServletRequest request,
HttpServletResponse response) throws Exception
{
super.onStartPage(request, response);
// prepare for rendering (queries)
}
}
- onStartPage(...) is a phase notification callback that will be called at the point where the controller has initialized all modules, has optionally routed an event to one of the UI modules, and has determined that the page will be rendered (that is, one of the earlier phases didn't trigger a redirect).
- This is a good place to execute server queries for data that will be displayed by the UI module.
render method
package mypackage;
public class MyUIModule extends WcmUiModule
{
...
public void render(Writer w) throws Exception
{
w.write("<br><center>Hello World.</center><br>");
}
}
- Renders the UI module's content onto the page.
- Above is an example of a Java-rendered UI module (uses
w.write()
coded in Java).- Any UI module can delegate to JSP-based rendering.
- WcmXSLModule base class provides XSL-based rendering.
See Also
Event URLs
XSLT-Based Rendering
JSP-Based Rendering
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 ModuleThe 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 EventThe 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 ParentIn a child UI module, you can route an event to the parent module with the following WcmUiModule methods:
getUiParent()
androuteEvent(...)
. For example:
public void onAddSelection(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
WcmUiModuleInterface parent = getUiParent();
if ( parent != null )
parent.routeEvent("AddSelection", request, response);
}
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> |
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).
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.
You access the date/time API from UI modules. This section covers the following topics:
The JavaScript control is located in <app_root>/js/jscalendar.
HeaderModule parents DateTimeHeader.class.
DateTimeControlStringsJSP.jsp is located in <app_root>/UI-INF/jsp/modules/apps/presentation.
A UI module that will display the date/time control must call DateTimeControl.includeHeaders(...), either in its initialize() or onStartPage(...) method. The includeHeaders(...) method will access the header module that subclasses HeaderModule.class, and make the necessary calls to ensure that the required jscalendar JavaScript and CSS files are included in the headers.
DateTimeControl.xsl is located in <app_root>/WEB-INF/xsl/include.
To use the date/time API:
headerModule
preference to the fully qualified
name of your HTML-header class.
public void initialize() throws Exception
{ Locale locale = (get configured locale); super.initialize(); ... DateTimeControl.includeHeaders(getController(), locale); ... } |
This section provides pseudocode examples for:
Displaying Date/Time ControlIn 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 JavaFor 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 XSLFor 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 DataWhen 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 ValuesYou 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 JavaBelow 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 XSLFor 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>