Developing an HTML Step Processor

The Web Application Toolkit includes resources to build workflow functionality into your Web applications, or to extend the existing workflow functionality in the FileNet P8 Workplace application. You can leverage the Toolkit framework and APIs to execute and manage workflows in the Process Engine, to store and manage versions of workflow definitions in the Content Engine, and to render UI, handle events, and manage state information in the Web application.

In a Web application, workflow-related operations are performed by what's generically referred to as a "Step Processor", a set of components that provide and process the information and resources that participants need to complete steps in a workflow. Technically, however, a Step Processor is one of two categories of processors that are used in sequence. First, a Launch Step Processor is used to begin a workflow: it contains the information necessary to initialize the workflow. Second, a Step Processor is used for each step in the workflow: it displays the instructions, the attachments retrieved from an object or file store, current field values, response options, or other resources to the workflow participant.

There are two type of processors you can develop for a Toolkit-build Web application: a zero-download HTML processor, and a downloadable Java™ processor (application or applet). (The FileNet P8 Workplace application includes out-of-the-box HTML and Java processors.) This topic shows you how to add custom HTML processors to the FileNet P8 Workplace application. Note that this information also applies to creating HTML processors for any Toolkit-based Web application.

See Also
System Overview
Developing HTML and Java Step Processors
Developing Custom Java Processors - Applications vs. Applets

Basic Processor Operations

All processors, whether HTML or Java, must at a minimum perform the following basic operations. For general information on a particular operation, click the applicable link. For details on coding these operations in an HTML processor, see HTML Processors Development Procedure.

HTML Processors Development Procedure

This procedure explains how to develop a custom HTML Launch Processor and Step Processor for the FileNet P8 Workplace application. The procedure presents this information by describing the processor components in the FileNet P8 Web Application Toolkit Basic Step Processor Sample Code, v 4.0. This is a fully-functional processor sample that you can modify or run as-is and includes a workflow definition. You can download this sample from the IBM support site. For download instructions, see Accessing IBM FileNet documentation.

NOTE   For the remainder of this topic, the FileNet P8 Web Application Toolkit Basic Step Processor Sample Code will be referred to as the "Basic Step Processor Sample".

After you have downloaded the Basic Step Processor Sample, you may develop HTML Processors as follows:

  1. Set up your development environment, as described in Development Requirements.
  2. Create and deploy the processor components, as described in Processor Components.
  3. Register the processors with the Process Engine, as described in Register the HTML Processors.
  4. Create a test workflow, as described in Create the Workflow Definition.
  5. Test the processors, as described in Test the HTML Processors.
Development Requirements

To develop, deploy, and test processor components:

  1. Configure the FileNet P8 Workplace application to access a Content Engine and a Process Engine. See the IBM FileNet P8 Platform Installation and Upgrade Guide. To download this document from the IBM support page, see Accessing IBM FileNet Documentation.
  2. Place the Basic Step Processor Sample file, basicProcessor4_x.zip, in the deployed Workplace directory, and extract the files into the Workplace directory structure.
  3. Set your project class path to the following Java™ Archive (JAR) files in Workplace/WEB-INF/lib: p8toolkit.jar and pe.jar. Also, set the class path to the JAR file that contains the javax.servlet.http package. The JAR names vary between application servers, for example, weblogic.jar in WebLogic, j2ee.jar in WebSphere, and javax.servlet.jar in JBoss.
Processor Components

The components listed in the following table comprise a Launch Processor and Step Processor for a Toolkit-build Web application. As you can see, each processor consists of a framework page (event Java™Server Pages (JSP) and a UI JSP), a UI module, and a UI module JSP for rendering, although you could use XSL- or Java-based rendering instead. The CSS stylesheet defines the styles specified in the UI module JSP. Also listed are the FileNet P8 Workplace directories where you must deploy the components. Create new directories if they don't currently exist.

Note that these components are used in the Basic Step Processor Sample. For a description of a component, click on the applicable link. To view the entire source of the component, open the source file included with the sample.

Component Deployment Directory Name in Sample
Launch Processor: Event JSP Workplace/eprocess/launchers/html/custom CustomLaunch.jsp
Launch Processor: UI JSP Workplace/UI-INF/jsp/ui/eprocess/
  launchers/html/custom
CustomLaunch.jsp
Launch Processor: UI Module Workplace/WEB-INF/classes/com/filenet/
  samples/processors/basic/apps/server/ui
CustomLaunchModule.class
Launch Processor: UI Module JSP
(for rendering)
Workplace/UI-INF/jsp/modules/apps CustomLaunchModuleJSP.jsp
Step Processor: Event JSP Workplace/eprocess/stepprocs/html/custom CustomStep.jsp
Step Processor: UI JSP Workplace/UI-INF/jsp/ui/eprocess/
  stepprocs/html/custom
CustomStep.jsp
Step Processor: UI Module Workplace/WEB-INF/classes/com/filenet/
  samples/processors/basic/apps/server/ui
CustomStepModule.class
Step Processor: UI Module JSP
(for rendering)
Workplace/UI-INF/jsp/modules/apps CustomStepModuleJSP.jsp
CSS Stylesheet Workplace/css Processors.css

Launch Processor: Event JSP

As in all event JSP pages, the event JSP page for a launch processor must declare the controller and modules, and register the modules with the controller. As shown in the following code fragment, a UI module and data provider module are declared. The UI module (CustomLaunchModule) provides event handling and presentation, and WcmEProcessDataProvider provides application-level access to the Process Java API. Note that WcmEProcessDataProvider is bound to CustomLaunchModule with the addDataProvider(...) call.

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

<%-- UI Beans --%>
<jsp:useBean
   id="customLaunchModule"
   class="com.filenet.samples.processors.basic.apps.server.ui.CustomLaunchModule"
   scope="request">
   <jsp:setProperty name="customLaunchModule" property="name" value="customLaunchModule" />
</jsp:useBean>

<%-- Data Provider Bean --%>
<jsp:useBean
   id="eProcessDataProvider"
   class="com.filenet.wcm.toolkit.server.dp.WcmEProcessDataProvider"
   scope="request">
   <jsp:setProperty name="eProcessDataProvider" property="name" value="eProcessDataProvider" />
</jsp:useBean>

<%-- WcmController CONTROLLER --%>
<jsp:useBean
   id="controller"
   class="com.filenet.wcm.apps.server.controller.WcmWorkplaceController"
   scope="request">
</jsp:useBean>

<%
   customLaunchModule.addDataProvider(eProcessDataProvider);

...

Launch Processor: UI JSP

This is a typical UI JSP page in that it contains HTML tags and invokes rendering of the HTML header tags and body text. As shown in the following code fragment, the WcmString is used to retrieve a localized string—if any—that will be used in the HTML title element of the output. The getHeaderModule(...) method returns the HTML header module registered with the controller, and the CSS stylesheet is set. The renderHeaders(...) method retrieves the HTML header module, which renders the headers onto the page. Lastly, the UI module is rendered through the UI module JSP.

<%@ include file="/WEB-INF/jsp/WcmHeader.jsp" %>

<html>
<head>
   <%
      WcmString topic = new WcmString
        ("server.properties_CustomLaunch_jsp.topic", "Custom Launch Processor");
      WcmWorkplaceUi.getHeaderModule(request).addCssFile("css/Processors.css");
      WcmWorkplaceUi.renderHeaders(request, out, true, topic);
   %>
</head>
<body class="proBody">
   <% WcmUi.render(request, "customLaunchModule", out); %>
</body>
</html>

Launch Processor: UI Module

The UI module for a Launch Processor creates the workflow, and, therefore, must retrieve the required parameters to do so. The UI module for a Launch Processor does not have to track the workflow state as does the UI module for the Step Processor.

Like all Toolkit UI modules, CustomLaunchModule includes the initialize(...) and onStartPage(...) callbacks. For rendering, CustomLaunchModule delegates to a JSP module. An event handler is required to launch the workflow, and an event handler is provided to exit the launch page without launching.

This section discusses the following methods in CustomLaunchModule: initialize(...), onStartPage(...), onLaunch(...), onExit(...), redirectTo(...), and getFormName().

initialize Method

As shown in the listing below, the initialize(...) method does the following:

public void initialize() throws Exception
{
   WcmController controller = getController();

   eProcessDataProvider = (WcmEProcessDataProvider)
                          queryDataProvider(WcmEProcessDataProvider.TYPE);
   if (eProcessDataProvider == null)
   {
      throw new WcmException("server.CustomLaunchModule.dataProviderUndefined",
                             "WcmEProcessDataProvider undefined: {0}", getName());
   }

   // Get the url parameters that specify which workflow to launch,
   // and if passed, the initiating attachment id
   workflowVersion = WcmEncodingUtil.decodeLabel(controller.getPageParameter(WcmParameter.WORKFLOW_VERSION));
   attachmentId = WcmEncodingUtil.decodeLabel(controller.getPageParameter(WcmParameter.ATTACHMENT_ID));
   subject = WcmEncodingUtil.decodeLabel(controller.getPageParameter(WcmParameter.SUBJECT));

   if ( workflowVersion != null && workflowVersion.length() > 0 ) // Must have a vwVersion
   {
      eProcessDataProvider.setClassProperty("workflowVersion", workflowVersion );
      eProcessDataProvider.setClassProperty("attachmentId", attachmentId);
      eProcessDataProvider.setClassProperty(WcmEProcessStateKeys.KEY_SUBJECT, subject);
   }
   else // Add for Attachment page changes
   {
      workflowVersion = (String) eProcessDataProvider.getClassProperty("workflowVersion");
      attachmentId = (String) eProcessDataProvider.getClassProperty("attachmentId");
      subject = (String) eProcessDataProvider.getClassProperty(WcmEProcessStateKeys.KEY_SUBJECT);
   }

   String returnURL = controller.getPageParameter(WcmParameter.RETURN_URL);
   if (returnURL != null && returnURL.length() > 0)
   {
      eProcessDataProvider.setClassProperty("custlaunch.returnurl", returnURL);
   }

   // Edit this JSP file to change the rendering
   setJSP("apps/CustomLaunchModuleJSP.jsp");

   super.initialize();
}

onStartPage Method

As shown in the listing below, the onStartPage(...) method does the following:

public void onStartPage(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
   Document documentXML = (Document) eProcessDataProvider.doCreateWorkflow(workflowVersion,
                          subject, attachmentId);
   super.onStartPage(request, response);
}

onLaunch Method

As shown in the listing below, the onLaunch(...) method does the following:

public void onLaunch(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
   // Get the step element object from the state class
   WcmStepElementState stepState = WcmStepElementState.getGlobalInstance(eProcessDataProvider);
   VWStepElement stepElement = stepState.getVWStepElement();

   // Get the step response (if there is one defined in the Workflow Definition)
   String stepResponse = (String) request.getParameter("StepResponse");

   // Save the form data into the step element object
   if ( stepResponse != null )
      stepElement.setSelectedResponse(stepResponse);

   // Get the list of user defined data fields exposed on this step (no attachments
   // or participants).
   VWParameter parameters[] = stepElement.getParameters(VWFieldType.BASIC_FIELD_TYPES,
                              VWStepElement.FIELD_USER_DEFINED);
   if ( parameters != null )
   {
      String parameterName;   // The Data Field name
      String formData;        // The html form field value

      // Loop through the list of custom data fields exposed on the workflow step,
      // get the html form data (using the data field name as the form field name)
      // and save the data into the step element
      int size = parameters.length;
      for (int index = 0; index < size; index++)
      {
         parameterName = parameters[index].getName();
         formData = (String) request.getParameter(parameterName);

         // Will do data type validation, and throw exception if there are problems
         stepElement.setParameterValue(parameterName, formData, true);
      }
   }

   // Finally, launch the workflow
   eProcessDataProvider.setStepElementParameters(WcmXMLTagsProcessEngine.TYPE_ALL);
   eProcessDataProvider.doStepElementDispatch();
   eProcessDataProvider.resetClassProperties(true);

   String destURL = (String) eProcessDataProvider.getClassProperty("custlaunch.returnurl");
   redirectTo(destURL);
}

onExit Method

As shown in the listing below, the onExit(...) method clears the step element data. It then retrieves the value of the return URL from the data store and redirects to that URL.

public void onExit(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
   eProcessDataProvider.resetClassProperties(false);

   String destURL = (String) eProcessDataProvider.getClassProperty("custlaunch.returnurl");
   redirectTo(destURL);
}

redirectTo Method

This method is called by the onLaunch(...) and onExit(...) methods. As shown in the listing below, the redirectTo(...) method redirects to the return URL if specified, or closes the window if there is no return URL.

private void redirectTo(String destUrl)
throws Exception
{
   if (destUrl != null)
   {
      WcmURLBuilder url = new WcmURLBuilder(destUrl);
      String uri = url.getURI();
      if (uri.indexOf("WcmCloseWindow.jsp") < 0 )
      {
         url = new WcmURLBuilder(
                  WcmUi.encodeWindowId(getController().getWindowId(),
                  getBasePath() + "/WcmCloseWindow.jsp") );
         url.addParameter("refreshUrl", WcmEncodingUtil.encodeURL(destUrl) );
      }
      getController().sendRedirect(url.toString());
   }
   else // Invoked from direct URL, not Tasks tab in Workplace application
   {
      getController().closeWindow();
   }
}

getFormName Method

This method is called by the UI module JSP (CustomLaunchModuleJSP) and returns the name of the HTML form.

public String getFormName()
{
   return "CustomLaunchModule";
}

Launch Processor: UI Module JSP

The UI module JSP renders the Launch Processor HTML form. In the Basic Step Processor sample, the form is similar to the following screen shot.

Launch Processor HTML form

CustomLaunchModuleJSP.jsp is specified as the rendering JSP in the initialize(...) method of the UI module. This section discusses the following tasks in rendering the launch processor: initialize strings to be rendered, get required objects, get values from workflow data fields, and render HTML.

Initialize Strings to be Rendered

The following code fragment shows the initialization of strings that will be rendered. Note that the WcmString class is used to retrieve localized UI strings from a resource bundle.

// Globalization strings displayed in the html form
String stepName = WcmString.localize("server.CustomLaunchModule_jsp.StepName", "Step Name");
String stepResponse = WcmString.localize("server.CustomLaunchModule_jsp.Response", "Response");
String selectResponse = WcmString.localize("server.CustomLaunchModule_jsp.Response", "Select a response");
String fields = WcmString.localize("server.CustomLaunchModule_jsp.Fields", "Fields");
String value = WcmString.localize("server.CustomLaunchModule_jsp.Value", "Value");
String field1 = WcmString.localize("server.CustomLaunchModule_jsp.Field1", "Field1: (String)");
String field2 = WcmString.localize("server.CustomLaunchModule_jsp.Field2", "Field2: (Float)");
String field3 = WcmString.localize("server.CustomLaunchModule_jsp.Field3", "Field3: (Integer)");
String field4 = WcmString.localize("server.CustomLaunchModule_jsp.Field4", "Field4: (Boolean)");
String field5 = WcmString.localize("server.CustomLaunchModule_jsp.Field5", "Field5: (Date, mm/dd/yyyy hh:mm:ss)");
String launch = WcmString.localize("server.CustomLaunchModule_jsp.Launch", "Launch");
String exit = WcmString.localize("server.CustomLaunchModule_jsp.Exit", "Exit");
Get Required Objects

To render, you need the instance of the UI module (CustomLaunchModule), and the instances of WcmEProcessDataProvider and VWStepElement instantiated in the UI module.

In the following statement, the instance of the UI module is returned.

CustomLaunchModule customLaunchModule = CustomLaunchModule)
   WcmJSPModule.getCurrentModule(request);

In the following statement, the WcmEProcessDataProvider object that is bound to CustomLaunchModule is returned.

WcmEProcessDataProvider eprocessDataProvider = (WcmEProcessDataProvider)
   customLaunchModule.queryDataProvider(WcmEProcessDataProvider.TYPE);

In the following statements, the instance of the WcmStepElementState is returned, and then used to retrieve the VWStepElement object.

WcmStepElementState stepState = WcmStepElementState.getGlobalInstance(eprocessDataProvider);
VWStepElement stepElement = stepState.getVWStepElement();
Get Values from Workflow Data Fields

Data fields are defined in the workflow. They can be defined with or without default values, and may or may not be changed by the user. You get the values in the data fields with the VWStepElement object. The following statements assign the data field values to variables.

String dataField1 = (String)stepElement.getParameterValue("DataField1");
Double dataField2 = (Double)stepElement.getParameterValue("DataField2");
Integer dataField3 = (Integer)stepElement.getParameterValue("DataField3");
Boolean dataField4 = (Boolean)stepElement.getParameterValue("DataField4");
Date dateField = (Date)stepElement.getParameterValue("DataField5");
Render HTML

This section of the JSP page consists of the HTML, including the HTML form tag that provides users with input fields. Many of the HTML elements include class attributes set to styles defined in the CSS stylesheet, Processors.css.

JSP expressions are used to insert values retrieved from the workflow data fields. The following HTML is for a single input field in the form.

<!-- Table data, display the hardcoded list of data fields, customize here as appropriate -->
<!-- The form field names used here must match the data field names exposed on the step element -->
<tr>
   <td align="center" class="proFormRowEven" width="5%">&#160;</td>
   <td align="left" class="proFormRowEven" width="40%"><%=field1%></td>
   <td align="left" class="proFormRowEven" width="55%">
   <input type="text" name="DataField1" style="width:100%" value="<%=dataField1%>"/></td>
</tr>

Two links are rendered: Launch to submit the form input, and Exit to return to the previous page without submitting the input. As shown in the following code fragment, the links include JSP expressions for the form name, the URL, and the anchor text. The form name is set in the UI module and is returned via the getFormName() call. The URL is returned by getEventUrl(), a derived method of the UI module.

String formName = customLaunchModule.getFormName();
...
<a class="proFormLink" href="javascript:document.forms.<%=formName%>.action=
   '<%=customLaunchModule.getEventUrl("Launch")%>';
   document.forms.<%=formName%>.submit();"><%=launch%></a>
...
<a class="proFormLink" href="<%=customLaunchModule.getEventUrl("Exit")%>">
   <%=exit%></a>

Step Processor: Event JSP

As in all event JSP pages, the event JSP page for a step processor must declare the controller and modules, and register the modules with the controller. As shown in the following code fragment, a UI module and data provider module are declared. The UI module (CustomStepModule) provides event handling and presentation, and WcmEProcessDataProvider provides application-level access to the Process Java API. Note that WcmEProcessDataProvider is bound to CustomStepModule with the addDataProvider(...) call.

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

<%-- UI Beans --%>
<jsp:useBean
   id="customStepModule"
   class="com.filenet.samples.processors.basic.apps.server.ui.CustomStepModule"
   scope="request">
   <jsp:setProperty name="customStepModule" property="name" value="customStepModule" />
</jsp:useBean>

<%-- Data Provider Bean --%>
<jsp:useBean
   id="eProcessDataProvider"
   class="com.filenet.wcm.toolkit.server.dp.WcmEProcessDataProvider"
   scope="request">
   <jsp:setProperty name="eProcessDataProvider" property="name" value="eProcessDataProvider" />
</jsp:useBean>

<%-- WcmController CONTROLLER --%>
<jsp:useBean
   id="controller"
   class="com.filenet.wcm.apps.server.controller.WcmWorkplaceController"
   scope="request">
</jsp:useBean>

<%
   customStepModule.addDataProvider(eProcessDataProvider);

...

Step Processor: UI JSP

This is a typical UI JSP page in that it contains HTML tags and invokes rendering of the HTML header tags and body text. As shown in the following code fragment, the WcmString is used to retrieve a localized string—if any—that will be used in the HTML title element of the output. The getHeaderModule(...) method returns the HTML header module registered with the controller, and the CSS stylesheet is set. The renderHeaders(...) method retrieves the HTML header module, which renders the headers onto the page. Lastly, the UI module is rendered through the UI module JSP.

<%@ include file="/WEB-INF/jsp/WcmHeader.jsp" %>

<html>
<head>
   <%
      WcmString topic = new WcmString
        ("server.properties_CustomStep_jsp.topic", "Custom Step Processor");
      WcmWorkplaceUi.getHeaderModule(request).addCssFile("css/Processors.css");
      WcmWorkplaceUi.renderHeaders(request, out, true, topic);
   %>
</head>
<body class="proBody">
   <% WcmUi.render(request, "customStepModule", out); %>
</body>
</html>

Step Processor: UI Module

CustomStepModule is similar to CustomLaunchModule in that it includes the initialize(...) and onStartPage(...) callbacks, and delegates rendering to a JSP module. However, whereas CustomLaunchModule creates a workflow and launches it, CustomStepModule retrieves the workflow from a specified queue, renders the data for a specified step, and provides an event handler to save user input and dispatch the completed step to the Process Engine.

This section discusses the following methods in CustomStepModule: initialize(...), onStartPage(...), onComplete(...), onExit(...), and redirectTo(...). (The getFormName() method is identical to the corresponding method in CustomLaunchModule.)

NOTE  Typically a workflow would consist of multiple steps and, after a completed step, the next step would be routed to a different participant(s). However, the workflow definition in the Basic Step Processor Sample consists of only one step (in addition to the launch step). Therefore, when CustomStepModule dispatches the completed step, the workflow is removed from the system.

initialize Method

As shown in the listing below, the initialize(...) method does the following:

public void initialize() throws Exception
{
   WcmController controller = getController();

   eProcessDataProvider = (WcmEProcessDataProvider)
                          queryDataProvider(WcmEProcessDataProvider.TYPE);
   if (eProcessDataProvider == null)
   {
      throw new WcmException("server.CustomStepModule.dataProviderUndefined",
                             "WcmEProcessDataProvider undefined: {0}", getName());
   }

   // Get the url parameters that specify which step to display
   and where to return when finished
   wobNum = controller.getPageParameter(WcmParameter.WOB_NUM);
   queueName = controller.getPageParameter(WcmParameter.QUEUE_NAME);
   if ( (wobNum != null && wobNum.length() > 0 ) && (queueName != null && queueName.length() > 0 ))
   {
      // Set info into data provider so that other step processors can use it later to get the data
       eProcessDataProvider.setClassProperty(WcmEProcessStateKeys.KEY_WOB_NUM, wobNum );
       eProcessDataProvider.setClassProperty(WcmEProcessStateKeys.KEY_QUEUE_NAME, queueName);
   }

   // Get the url parameter that specifies where to return when finished
   String returnURL = controller.getPageParameter(WcmParameter.RETURN_URL);
   if (returnURL != null && returnURL.length() > 0)
   {
      eProcessDataProvider.setClassProperty("custstep.returnurl", returnURL);
   }

   // Edit this JSP file to change the rendering
   setJSP("apps/CustomStepModuleJSP.jsp");

   super.initialize();
}

onStartPage Method

As shown in the listing below, the onStartPage(...) method does the following:

public void onStartPage(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
   // Retrieve the actual step element object from the data provider.
   // Making this call will also store the VWStepELement object in
   // the WcmStepElementState object. You can reference this
   // object later to do the rendering and process the form data.
   Document documentXML = (Document) eProcessDataProvider.getStepElement(
      queueName, wobNum, false);

   super.onStartPage(request, response);
}

onComplete Method

As shown in the listing below, the onComplete(...) method does the following:

public void onComplete(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
   // Get the step element object from the state class
   WcmStepElementState stepState = WcmStepElementState.getGlobalInstance(eProcessDataProvider);
   VWStepElement stepElement = stepState.getVWStepElement();
   stepElement.doLock(true);

   // Get the step response (if there is one defined in the Workflow definition)
   String stepResponse = (String) request.getParameter("StepResponse");

   // Save the form data into the step element object
   if ( stepResponse != null )
      stepElement.setSelectedResponse(stepResponse);

   // Get the list of user defined data fields exposed on this step
   // (no attachments or participants).
   VWParameter parameters[] = stepElement.getParameters(VWFieldType.BASIC_FIELD_TYPES,
                              VWStepElement.FIELD_USER_DEFINED);
   if ( parameters != null )
   {
      String parameterName; // The Data Field name
      String formData; // The html form field value

      // Loop through the list of custom data fields exposed on the workflow step,
      // get the html form data (using the data field name as the form field name)
      // and save the data into the step element
      int size = parameters.length;
      for (int index = 0; index < size; index++)
      {
         parameterName = parameters[index].getName();
         formData = (String) request.getParameter(parameterName);

         // Will do data type validation, and throw exception if there are problems
         stepElement.setParameterValue(parameterName, formData, true);
      }
   }

   // Finally, complete the step
   eProcessDataProvider.setStepElementParameters(WcmXMLTagsProcessEngine.TYPE_ALL);
   eProcessDataProvider.doStepElementDispatch();
   eProcessDataProvider.resetClassProperties(true);

   String destURL = (String) eProcessDataProvider.getClassProperty("custstep.returnurl");
   redirectTo(destURL);
}

onExit Method

As shown in the listing below, the onExit(...) method unlocks the work item associated with the step without updating the fields on the work item. It then retrieves the value of the return URL from the data store and redirects to that URL.

public void onExit(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
   eProcessDataProvider.doStepElementAbort();
   eProcessDataProvider.resetClassProperties(false);

   String destURL = (String) eProcessDataProvider.getClassProperty("custstep.returnurl");
   redirectTo(destURL);
}

redirectTo Method

This method is called by the onComplete(...) and onExit(...) methods. As shown in the listing below, the redirectTo(...) method redirects to the specified return URL if specified, or closes the window if there is no return URL.

private void redirectTo(String destUrl)
throws Exception
{
   if (destUrl != null&& destUrl.length() > 0)
   {
      getController().closeWindow();
      WcmURLBuilder url = new WcmURLBuilder(destUrl);
      url.addParameter("refreshUrl", WcmEncodingUtil.encodeURL(destUrl));
      getController().sendRedirect(url.toString());
   }
   else // Invoked from direct URL, not Tasks tab in Workplace application
   {
      getController().closeWindow();
   }
}

Step Processor: UI Module JSP

The UI module JSP renders the Step Processor HTML form. In the Basic Step Processor Sample, the form is similar to the following screen shot. Note that because the sample workflow definition consists of only a single step (in addition to the launch step), the workflow is removed from the system after the one step is completed.

Step Processor HTML form

CustomStepModuleJSP.jsp is specified as the rendering JSP in the initialize(...) method of the UI module. This section discusses the following tasks in rendering the step processor: initialize strings to be rendered, get required objects, get values from workflow data fields, and render HTML.

Initialize Strings to be Rendered

The following code fragment shows the initialization of strings that will be rendered. Note that the WcmString class is used to retrieve localized UI strings from a resource bundle.

// Globalization strings displayed in the html form
String stepName = WcmString.localize("server.CustomStepModule_jsp.StepName", "Step Name");
String stepResponse = WcmString.localize("server.CustomStepModule_jsp.Response", "Response");
String selectResponse = WcmString.localize("server.CustomStepModule_jsp.Response", "Select a response");
String fields = WcmString.localize("server.CustomStepModule_jsp.Fields", "Fields");
String value = WcmString.localize("server.CustomStepModule_jsp.Value", "Value");
String field1 = WcmString.localize("server.CustomStepModule_jsp.Field1", "Field1: (String)");
String field2 = WcmString.localize("server.CustomStepModule_jsp.Field2", "Field2: (Float)");
String field3 = WcmString.localize("server.CustomStepModule_jsp.Field3", "Field3: (Integer)");
String field4 = WcmString.localize("server.CustomStepModule_jsp.Field4", "Field4: (Boolean)");
String field5 = WcmString.localize("server.CustomStepModule_jsp.Field5", "Field5: (Date, mm/dd/yyyy hh:mm:ss)");
String complete = WcmString.localize("server.CustomStepModule_jsp.Complete", "Complete");
String exit = WcmString.localize("server.CustomStepModule_jsp.Exit", "Exit");
Get Required Objects

To render, you need the instance of the UI module, CustomStepModule, and the instances of WcmEProcessDataProvider and VWStepElement instantiated in the UI module.

In the following statement, the instance of the UI module is returned.

CustomStepModule customStepModule = (CustomStepModule) WcmJSPModule.getCurrentModule(request);

In the following statement, the WcmEProcessDataProvider object that is bound to CustomStepModule is returned.

WcmEProcessDataProvider eprocessDataProvider = (WcmEProcessDataProvider)
      customStepModule.queryDataProvider(WcmEProcessDataProvider.TYPE);

In the following statements, the instance of the WcmStepElementState is returned, and then used to retrieve the VWStepElement object.

WcmStepElementState stepState = WcmStepElementState.getGlobalInstance(eprocessDataProvider);
VWStepElement stepElement = stepState.getVWStepElement();
Get Values from Workflow Data Fields

Data fields are defined in the workflow. They can be defined with or without default values, and may or may not be changed by the user. You get the values in the data fields with the VWStepElement object. The following statements assign the data field values to variables.

String dataField1 = (String)stepElement.getParameterValue("DataField1");
Double dataField2 = (Double)stepElement.getParameterValue("DataField2");
Integer dataField3 = (Integer)stepElement.getParameterValue("DataField3");
Boolean dataField4 = (Boolean)stepElement.getParameterValue("DataField4");
Date dateField = (Date)stepElement.getParameterValue("DataField5");
Render HTML

This section of the JSP page consists of the HTML, including the HTML form tag that provides users with input fields. Many of the HTML elements include class attributes set to styles defined in the CSS stylesheet, Processors.css.

JSP expressions are used to insert values retrieved from the workflow responses and data fields. The following HTML is for the drop-down box where the user selects either "Approved" or "Rejected". Note that the check for a selected response evaluates to false because the response was not available to be set in the launch step.

<tr>
   <td align="center" class="proFormRowOdd" width="5%">&#160;</td>
   <td align="left" class="proFormRowOdd" width="40%"><%=stepResponse%>:</td>
   <td align="left" class="proFormRowOdd" width="55%">
      <select name="StepResponse" size="1" class="proLabel">
         <option class="proFormText">&lt;<%=selectResponse%>&gt;</option>
         <%
            String selectedResponse = stepElement.getSelectedResponse();
            for (int i = 0; i < responses.length; i++)
            {
               if ( responses[i].equals(selectedResponse) )
               {
         %>
               <option selected="true" class="proFormText" ><%=responses[i]%></option>
         <%
               }
               else
               {
         %>
               <option class="proFormText"><%=responses[i]%></option>
         <%
               }
            }
         %>
         </select>
      </td>
   </tr>

Two links are rendered: Complete to submit the form input, and Exit to return to the previous page without submitting the input. As shown in the following code fragment, the links include JSP expressions for the form name, the URL, and the anchor text. The form name is set in the UI module and is returned via the getFormName() call. The URL is returned by the getEventUrl(), a derived method of the UI module.

String formName = customStepModule.getFormName();
...
<a class="proFormLink" href="javascript:document.forms.<%=formName%>.action=
   '<%=customStepModule.getEventUrl("Complete")%>';
   document.forms.<%=formName%>.submit();"><%=complete%></a>
...
<a class="proFormLink" href="<%=customStepModule.getEventUrl("Exit")%>">
   <%=exit%></a>

CSS Stylesheet

The CSS stylesheet, Processors.css, is used for both the Launch Processor and the Step Processor. Its use is specified in the UI JSPs of the processors. CSS definitions are based on class names rather than HTML element names; that is, HTML tags to which styles are applied include a class attribute. Many of the HTML tags in the UI module JSP pages include class attributes.

Register the HTML Processors

Using the Process Configuration Console, you must register new processors with the Process Engine. This section summarizes the procedure.

To register the custom processors:

  1. On the Workplace Admin page, click Process Configuration Console.
  2. From the tree view, select the Process Engine connection point, then right click and choose Connect.

    Your connection point setting must match the "Process Engine Connection Point" setting in the Workplace Site Preferences.

  3. From the tree view, select the Process Engine connection point, then right click and choose Properties.
  4. Choose the Step Processor Info tab.
  5. Click the Add icon in the right corner.
  6. Enter the following values for the Launch Processor:
  7. Press Enter.
  8. Click the Add icon in the right corner
  9. Enter the following values for the Step Processor:
  10. Press Enter.
  11. Choose OK.
  12. Click the Action button and choose Commit Changes.
  13. Exit the Process Configuration Console.
Create the Workflow Definition

You create workflow definitions with the Process Designer. You can create a test workflow from scratch, or you can use the workflow provided in the Basic Step Processor Sample. This section summarizes both approaches.

To launch the Process Designer from the Workplace tree view, select Author/Advanced Tools, then choose Process Designer.

To create a workflow definition:

  1. Add your required data fields to the Workflow properties. The data field names must match any data field references you made in the UI modules and JSP rendering files.
  2. For each step in your workflow definition, specify the registered processor that will process that step's resources.
  3. From the File menu, select FileNet Add New, and add the workflow definition to a Content Engine folder. Make sure to specify the document class as "Workflow Definition".

To use the sample workflow definition:

  1. From the File menu, select Open, and select CustomWorkflow.pep.
  2. For the LaunchStep, choose the Launch Processor that you registered with the Process Engine.
  3. For Step 1, choose the Step Processor that you registered with the Process Engine.
  4. From the File menu, select FileNet Add New, and add the workflow definition to a Content Engine folder. Make sure to specify the document class as "Workflow Definition".
Test the HTML Processors

To test your custom Launch Processor and Step Processor:

  1. From Workplace, navigate to the folder where you stored your workflow definition.
  2. Select the workflow.
  3. If you didn't previously transfer the workflow definition from the Process Designer, display the Actions menu and choose Transfer Workflow.

    The Transfer Workflow page is displayed.

  4. Click Transfer

    The workflow is transferred to the Process Engine.

  5. If you didn't previously launch the workflow from the Process Designer, display the Actions menu and choose Launch.

    If you are using the workflow from the Basic Step Processor Sample, the HTML form for the launch step should be similar to the following screenshot.

    Launch Step

  6. Choose the Launch link.

    This saves the workflow and dispatches the next work item to its assigned queue (as specified in the workflow definition). If you are using the sample workflow, the next work item appears in the Inbox on the Tasks page.

  7. Navigate to the applicable queue and open the work item.

    If you are using the workflow from the Basic Step Processor Sample, the HTML form for Step 1 should be similar to the following screenshot.