JBoss.orgCommunity Documentation

Chapter 14. Forms

14.1. Configure process and human tasks
14.2. Generate forms from task definitions
14.3. Edit forms
14.3.1. Form generated description
14.3.2. Customizing form
14.3.3. Field types
14.4. Document attachments
14.4.1. Process and forms configuration
14.4.2. Marshalling strategy and deployment configuration
14.5. Using forms on client applications
14.5.1. What does the API provides?
14.5.2. Sample usage

This chapter intends to describe in a simple ways all the steps required to create a process with human tasks, generate and modify the forms for these tasks and execute them. It will provide initial guidance to perform all initial steps, but it will not provide a full description of all available features.

Given that forms are going to be used in tasks, it's possible to generate forms automatically from process variables and task definitions. These forms can be later be modified by using the form editor. In runtime, forms will receive data from process variables, display it to the user and capture his input, and then finally updating process variables again with the new values.

The following example will show all the steps to follow to create a form for the 'Create order' task in the process below.

Figure 14.1. Process example

Process example

This form must look like the following in execution:

Figure 14.2. Process example

Process example

To hold values capture by forms, process variables can be created. These variables can be of a simple type like 'String' or a complex type. These complex types can be defined by using the Data Modeler tool, or be just regular POJOs (Plain Java Objects) created with any Java IDE.

In this example, we define a variable 'po' of type 'org.jbpm.examples.purchases.PurchaseOrder', defined with the Data Modeler tool.


This variable is declared in the 'variables definition' property for the process.

After that, we must configure which variables are set as input parameters to the task, which ones will receive the response back from the form and establish the mappings. This is done by setting the 'DataInputSet', 'DataOutputSet' and 'Assignments' properties for any human task. See screenshots below for details.




The Process Designer module provides some functionality to generate the forms automatically from task and variable definitions, as well as easily open the right form from the modeler.

This is done with the following menu option.


You can also click on the icon on top of task to open the form directly.


Forms are related to tasks by following a naming convention. If a form with a name formName-taskform is defined in the same package as the process, then this form is used by the human task engine to display and capture information from user.

Also, if a form named ProcessId-task form is created, it will be used as the initial form when starting this process.

For example, for our process the following forms would be generated.


Once the forms have been generated, you can start editing them. There are several artifacts that are generated in the previous process, but also can be created manually.

We can change the way the form is displayed to the user in the task list. Next, we will show different levels of customization that will allow change it

Each field can be configured to enhance performance in the form. There are a group of common properties, that we call ‘Generic field properties’ and a group of specific properties that depends on the field type.

Let's explain the specific properties of each field type:

  • Short Text (java.lang.String)

  • Long Text (java.lang.String)

    • Compatible field type: Long text, E-mail, Rich text

    • Specific properties

      • Size: input text length.

      • MaxLength: Maximum number of characters allowed.

      • Required: Indicates if it’s mandatory to fill this field.

      • Height: The number or rows to show at text area.

      • Formula. to enter expressions that will be evaluated to set the field value. These expressions are described in Formula & expression section .

      • Range value. A range formula allows you to let you specify the values that the user can select from an specific field. These expressions are described in Formula & expression section

      • Pattern. Allow introduce an expression to specify the validation of the field. In case that the field value introduced hasn’t match the expression, and error is thrown and the error message has to be shown.

      • Default Value formula. Expression to set the field default value.

  • Float (java.lang.Float)

    • Specific properties

      • Size: input text length.

      • MaxLength: Maximum number of characters allowed.

      • Required: Indicates if it’s mandatory to fill this field.

      • Formula. to enter expressions that will be evaluated to set the field value. These expressions are described in Formula & expression section .

      • Range value. A range formula allows you to let you specify the values that the user can select from an specific field. These expressions are described in Formula & expression section

      • Pattern. Allow introduce an expression to specify how the Float value has to be displayed. The pattern allowed is show in section pattern in http://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html

      • Default Value formula. Expression to set the field default value.

  • Decimal (java.lang.Double)

    • Specific properties

      • Size: input text length.

      • MaxLength: Maximum number of characters allowed.

      • Required: Indicates if it’s mandatory to fill this field.

      • Formula. Used to enter expressions that will be evaluated to set the field value. These expressions are described in Formula & expression section.

      • Range value. A range formula allows you to let you specify the values that the user can select from an specific field. These expressions are described in Formula & expression section .

      • Pattern. Allow introduce an expression to specify how the Double value has to be displayed. The pattern allowed is show in section pattern in http://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html

      • Default Value formula. Expression to set the field default value.

  • BigDecimal (java.math.BigDecimal)

    • Specific properties

      • Size: input text length.

      • MaxLength: Maximum number of characters allowed.

      • Required: Indicates if it’s mandatory to fill this field.

      • Formula. Used to enter expressions that will be evaluated to set the field value. These expressions are described in Formula & expression section.

      • Range value. A range formula allows you to let you specify the values that the user can select from an specific field. These expressions are described in Formula & expression section .

      • Pattern. Allow introduce an expression to specify how the BigDecimal value has to be displayed. The pattern allowed is show in section pattern in http://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html

      • Default Value formula. Expression to set the field default value.

  • Big integer (java.math.BigInteger)

    • Specific properties

      • Size: input text length.

      • MaxLength: Maximum number of characters allowed.

      • Required: Indicates if it’s mandatory to fill this field.

      • Formula. Used to enter expressions that will be evaluated to set the field value. These expressions are described in Formula & expression section.

      • Range value. A range formula allows you to let you specify the values that the user can select from an specific field. These expressions are described in Formula & expression section .

      • Default Value formula. Expression to set the field default value.

  • Short (java.lang.Short)

    • Specific properties

      • Size: input text length.

      • MaxLength: Maximum number of characters allowed.

      • Required: Indicates if it’s mandatory to fill this field.

      • Formula. Used to enter expressions that will be evaluated to set the field value. These expressions are described in Formula & expression section.

      • Range value. A range formula allows you to let you specify the values that the user can select from an specific field. These expressions are described in Formula & expression section .

      • Default Value formula. Expression to set the field default value.

  • Integer (java.lang.Integer)

    • Specific properties

      • Size: input text length.

      • MaxLength: Maximum number of characters allowed.

      • Required: Indicates if it’s mandatory to fill this field.

      • Formula. Used to enter expressions that will be evaluated to set the field value. These expressions are described in Formula & expression section.

      • Range value. A range formula allows you to let you specify the values that the user can select from an specific field. These expressions are described in Formula & expression section .

      • Default Value formula. Expression to set the field default value.

  • Long Integer (java.lang.Long)

    • Specific properties

      • Size: input text length.

      • MaxLength: Maximum number of characters allowed.

      • Required: Indicates if it’s mandatory to fill this field.

      • Formula. Used to enter expressions that will be evaluated to set the field value. These expressions are described in Formula & expression section.

      • Range value. A range formula allows you to let you specify the values that the user can select from an specific field. These expressions are described in Formula & expression section .

      • Default Value formula. Expression to set the field default value.

  • E-mail (java.lang.String)

    • Compatible field type: Short text, Long text, Rich text

    • Specific properties

      • Size: input text length.

      • MaxLength: Maximum number of characters allowed.

      • Required: Indicates if it’s mandatory to fill this field.

      • Default Value formula. Expression to set the field default value.

  • Checkbox (java.lang.Boolean)

    • Specific properties

      • Required: Indicates if it’s mandatory to fill this field.

      • Default Value formula. Expression to set the field default value.

  • Rich text: (java.lang.String)

    • Compatible field type: Short text, Long text, E-mail

    • Specific properties

      • Size: input text length.

      • MaxLength: Maximum number of characters allowed.

      • Required: Indicates if it’s mandatory to fill this field.

      • Height: The number or rows to show at text area.

      • Default Value formula. Expression to set the field default value.

  • Timestamp (java.util.Date)

    • Compatible field type: Short date

    • Specific properties

      • Size: input text length.

      • Required: Indicates if it’s mandatory to fill this field.

      • Formula. to enter expressions that will be evaluated to set the field value. These expressions are described in Formula & expression section .

      • Default Value formula. Expression to set the field default value.

  • Short date (java.util.Date)

    • Compatible field type: Timestamp

    • Specific properties

      • Size: input text length.

      • Required: Indicates if it’s mandatory to fill this field.

      • Formula. to enter expressions that will be evaluated to set the field value. These expressions are described in Formula & expression section .

      • Default Value formula. Expression to set the field default value.

  • Document (org.jbpm.document.Document)

    • Specific properties

      • Required: Indicates if it’s mandatory to fill this field.

  • Simple subform (Object)

    • For more details see sectionSimple Object (Subform field Type).

      Specific properties

      • Default form. Show the list of available forms to select what one will be displayed to show the object.

  • Multiple subform (Multiple Object)

    • For more details see sectionArrays of objects.( Multiple subform field Type).

      Specific properties

      • Default form. Show the list of available forms to select what one will be displayed to show the object when no other form is configured with an specific purpose.

      • Preview form. If a form is specified, it will be used to show the item details

      • Table form. If a form is specified, it will be used to show the table columns when the item list is showed

      • New item text. Text to show at New Item button

      • Add item text. Text to show at Add Item button

      • Cancel text. Text to show at Cancel button

      • Allow remove Items. If this check is selected, the form allow remove items in table view.

      • Allow edit items. If this check is selected, the form allow edit items in table view.

      • Allow preview items. If this check is selected, the form allow preview items in table view.

      • Hide creation button. Check to not show the creation button

      • Expanded. If is checked, when a new item is being added, the field display the table with the existing items and the creation form at same time

      • Allow data enter in table mode. Allow modify data in table view directly.

There are two types of complex fields: fields representing an object, and fields representing an object array.

Once the field is added to the form, either automatically or manually, it must be configured so that the form had to know how to display the objects that will contain in execution time.

Next we describe how can be the configuration process:

Once the form to represent the object, the parent form has to be configured to use them in the parent Subform or Multiple subform.

Below we will describe how the setup would be:

Form Modeler provides a Formula Engine that you can use to automatically calculate field values. That Formula engine supports Java and XPATH expressions to access the form fields values. Let’s see some examples.

There are three types of field types that you can use to model your form:

Is possible to extend the platform to add Custom Field Types that make a specific field (of any type) on the form to look and behave totally different than the standard platform fields. On this section we will take a look on how to create them and how to configure them.

Basically a Custom Field Type is a Java class that implements the org.jbpm.formModeler.core.fieldTypes.CustomFieldType interface and is packaged inside inside a JAR file that is placed on the Application Server classpath or inside the application WAR.

Lets take a look atorg.jbpm.formModeler.core.fieldTypes.CustomFieldType:


package org.jbpm.formModeler.core.fieldTypes;

import java.util.Locale;
import java.util.Map;

/**
* Definition interface for custom fields
*/
public interface CustomFieldType {
    /**
    * This method returns a text definition for the custom type. This text will be shown
    * on the UI to identify the CustomFieldType
    * @param locale The current user locale
    * @return A String that describes the field type on the specified locale.
    */
    public String getDescription(Locale locale);

    /**
    * This method returns a string that contains the HTML code that will be used to show
    * the field value on screen
    * @param value The current field value
    * @param fieldName The field name
    * @param namespace The unique id for the rendered form, it should be used to generate
    * identifiers inside the HTML code.
    * @param required Determines if the field is required or not
    * @param readonly Determines if the field must be shown on read only mode
    * @param params A list of configuration params that can be set on the field
    * configuration screen
    * @return The HTML that will be used to show the field value
    */
    public String getShowHTML(Object value, String fieldName, String namespace,
              boolean required, boolean readonly, String... params);

    /**
    * This method returns a String that contains the HTML code that will show the input
    * view of the field. That will be used to set the field value.
    * @param value The current field value
    * @param fieldName The field name
    * @param namespace The unique id for the rendered form, it should be used to
    * generate identifiers inside the HTML code.
    * @param required Determines if the field is required or not
    * @param readonly Determines if the field must be shown on read only mode
    * @param params A list of configuration params that can be set on the field
    * configuration screen
    * @return The HTML code that will be used to show the input view of the field.
    */
    public String getInputHTML(Object value, String fieldName, String namespace,
              boolean required, boolean readonly, String... params);

    /**
    * This method is used to obtain the field value from the submitted values.
    * @param requestParameters A Map containing the request parameters for the
    * submitted form
    * @param requestFiles A Map containing the java.io.Files uploaded on the request
    * @param fieldName The field name
    * @param namespace The unique id for the rendered form, it should be used to generate
    * identifiers inside the HTML code.
    * @param previousValue The previous value of the current field
    * @param required Determines if the field is required or not
    * @param readonly Determines if the field must be shown on read only mode
    * @param params A list of configuration params that can be set on the field
    * configuration screen
    * @return The value of the field based on the submitted form values.
    */
    public Object getValue(Map requestParameters, Map requestFiles, String fieldName,
              String namespace, Object previousValue, boolean required, boolean readonly,
              String... params);
}
  

As you can see this Interface defines the methods that determines how the field has to be shown on the screen for when the form is shown on insert(getInputHTML(...)) or readonly (getShowHTML(...)) mode. It also provides the method (getValue(...)) that reads the needed parameters from the request and to obtain the correct field value. Te returned value type must match with the type of the field added on the form.

Now let's see how to use and configure and use a Custom Field type. Following the example on the previous chapter, we have created a File Input type and we have it already installed on our application. So now we are going to create a new form and add a Short Text property and turn it into a File Input and edit the field properties changing the Field Type from Short text toCustom field.


After changing the field type a new set of properties will appear:



So opening the Custom field select box we'll be able to select the File Input from the available custom types:


After selecting the File Input type on the list and saving the field properties the form will look like:


If we build a simple process and configure a Short text to be shown as the sampleFile Input, if we build the project on runtime the field will behave uploading the chosen files to the server and allowing the user to download it like this:



If we take a look at what's the process variable value, we'll see that is storing a String with the file path stored in server.


On this section we are going to describe step by step how to attach documents to your process variables from your forms and how you can configure to store the uploaded documents anywhere (File System, Data Base, Alfresco...) using the Pluggable Variable Persistence.

In order to store the document using the Pluggable Variable Persistence you'll have to define your Marshalling Strategy to manage the uploaded Documents. To start create a Maven project with your favourite IDE and add the following dependencies:


<dependency>
  <groupId>org.kie</groupId>
  <artifactId>kie-api</artifactId>
  <version>{version}</version>
</dependency>
<dependency>
  <groupId>org.jbpm</groupId>
  <artifactId>jbpm-document</artifactId>
  <version>{version}</version>
</dependency>
    

Once you did that is time to create your Document Marshalling Strategy, to do so you just have to create a class that extends:


package org.jbpm.document.marshalling;

public abstract class AbstractDocumentMarshallingStrategy implements ObjectMarshallingStrategy {

  public abstract Document buildDocument( String name, long size, Date lastModified, Map<String, String> params );

  public void write( ObjectOutputStream os, Object object )
        throws IOException;

  public Object read( ObjectInputStream os )
        throws IOException, ClassNotFoundException;

  public byte[] marshal( Context context, ObjectOutputStream os, Object object )
        throws IOException;

  public Object unmarshal( Context context, ObjectInputStream is, byte[] object,
        ClassLoader classloader ) throws IOException, ClassNotFoundException;

  public Context createContext();
}
    

The methods to implement are:

You can see how the default DocumentMarshallingStrategy is implemented looking at this link.

After creating your Document Marshalling Strategy and add it to your server classpath the only thing remaining is to configure your project deployment descriptor add it to the marshalling strategies list. To do it you just have to open the Kie-Workbench on your browser, open your project on the Authoring view and edit the kie-deployment-descriptor.xml file located on <yourproject>/src/main/resources/META-INF and add your Document Marshalling Strategy to the <marshalling-strategies> list like this:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<deployment-descriptor
    xsi:schemaLocation="http://www.jboss.org/jbpm deployment-descriptor.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <persistence-unit>org.jbpm.domain</persistence-unit>
  <audit-persistence-unit>org.jbpm.domain</audit-persistence-unit>
  <audit-mode>JPA</audit-mode>
  <persistence-mode>JPA</persistence-mode>
  <runtime-strategy>SINGLETON</runtime-strategy>
  <marshalling-strategies>
    <marshalling-strategy>
      <resolver>reflection</resolver>
      <identifier>
        org.jbpm.document.marshalling.DocumentMarshallingStrategy
      </identifier>
    </marshalling-strategy>
  </marshalling-strategies>
  <event-listeners/>
  <task-event-listeners/>
  <globals/>
  <work-item-handlers/>
  <environment-entries/>
  <configurations/>
  <required-roles/>
</deployment-descriptor>
    

Since this is done you're able to build your project and upload your documents on your process.



Note

On this example we are configuring the default DocumentMarshallingStrategy, please use it for test and demo purposes.

This chapter intends to describe how you can embed process forms and interact with them on another webapp including the new Javascript API provided by the platform.

You can find the library inside the kie-wb-*.war on the js file located on js/jbpm-forms-rest-integration.js.

This JavaScript API tries to be a simple mechanism to use forms on remote applications allowing to load the forms from different KIE Workbench instances, submit them, launch processes/tasks and execute callback functions when the actions are done.

The basic methods are:

showStartProcessForm(hostUrl, deploymentId, processId, divId, onsuccessCallback, onerrorCallback): Makes a call to the REST endpoint to obtain the form URL and if it gets a valid response will embed the process start form on the given div. The parameteres needed are:
startProcess(divId, onsuccessCallback, onerrorCallback): Submits the form loaded on the given div and starts the process. The parameteres needed are:
showTaskForm(hostUrl, taskId, divId, onsuccessCallback, onerrorCallback): Makes a call to the REST endpoint to obtain the form URL and if it gets a valid response will embed the task form on the given div. The parameteres needed are:
claimTask(divId, onsuccessCallback, onerrorCallback): Claims the task whose form is being rendered
startTask(divId, onsuccessCallback, onerrorCallback): Starts the task whose form is being rendered
releaseTask(divId, onsuccessCallback, onerrorCallback): Releases the task whose form is being rendered
saveTask(divId, onsuccessCallback, onerrorCallback): Submits the form and saves the state of the task whose form is being rendered
completeTask(divId, onsuccessCallback, onerrorCallback): Submits the form and completes task whose form is being rendered
clearContainer(divId): Cleans the div content and the related data stored on the component.

Now let's see an example how you can use the library to load the HR process form and start a new process instance. We are going to define a HTML page that will contain very simple components:

First we are look at the HTML code:


<head>
  <script src="js/jbpm-forms-rest-integration.js"></script>
  <script>
      var formsAPI = new jBPMFormsAPI();
  </script>
</head>
<body>
  <input type="button" id="showformButton"
      value="Show Process Form" onclick="showProcessForm()">
  <p/>
  <div id="myform" style="border: solid black 1px; width: 500px; height: 200px;">
  </div>
  <p/>
  <input type="button" id="startprocessButton"
      style="display: none;" value="Start Process" onclick="startProcess()">
</body>
    

Notice that in first place we have added the js library and created an instance of the jBPMFormsAPI object that will manage the form rendering.

Now let's see how the showProcessForm() function looks like:


function showProcessForm() {
  var onsuccessCallback = function(response) {
    document.getElementById("showformButton").style.display = "none";
    document.getElementById("startprocessButton").style.display = "block";
  }

  var onerrorCallback = function(errorMessage) {
    alert("Unable to load the form, something wrong happened: " + errorMessage);
    formsAPI.clearContainer("myform");
  }
  formsAPI.showStartProcessForm("http://localhost:8080/kie-wb/", "org.jbpm:HR:1.0", "hiring", "myform", onsuccessCallback, onerrorCallback);
}
    

As you can see, first we are defining the callback functions:

Once we defined the callback function we proceed to call the formsAPI.showStartProcessForm(...) that is going make the REST call and embedd the form inside the specified div. Notice that we are providing a bunch of information in order to load the form, the URL where the KIE-Workbench is running (in this example "http://localhost:8080/kie-wb/"), the deployment where the process is located ("org.jbpm:HR:1.0"), the process id ("hiring"), the DIV id that is going to contain the form ("myform") and the callback functions (onsuccessCallback and onerrorCallback).

Now let's take a look at the startProcess() that is the one that is going to submit the form and start the process:


function startProcess() {
  var onsuccessCallback = function(response) {
    document.getElementById("showformButton").style.display = "block";
    document.getElementById("startprocessButton").style.display = "none";
    formsAPI.clearContainer("myform");
    alert(response);
  }

  var onerrorCallback = function(response) {
    document.getElementById("showformButton").style.display = "block";
    document.getElementById("startprocessButton").style.display = "none";
    formsAPI.clearContainer("myform");
    alert("Unable to start the process, something wrong happened: " + response);
  }
  formsAPI.startProcess("myform", onsuccessCallback, onerrorCallback);
}
    

As showProcessForm(), first we are defining the callback functions. Both are doing basically the same:

Once that is done we just do the call to the formsAPI.startProcess(...) that will send a message to the component that renders the form inside the "myform" DIV and will exectue the callback functions when the action is done. Notice that we don't need the provide any other information than the DIV that contains the form and optionally the callback functions.

With a simple code like this you'll be able to run process/task forms that are located on different Kie-Workbench instances from any other application.