Business spaces for human-centric BPM, Part 4: Using custom form renderer for human tasks

Business Space and the Human Task Management widgets allow you to start with a comprehensive out-of-the-box experience for all participants in human-centric BPM, then adapt the experience to user roles and user interactions without programming. You can also develop custom renderers and custom widgets, thus reducing the development effort compared to developing a complete custom user interface.

Learn the concepts and benefits of using a custom form renderer for human tasks. This article walks you through a step-by-step example for developing and integrating a custom form renderer into the Task Information widget. This content is part of the IBM Business Process Management Journal.

Share:

Sascha Schwarze (schwarzs@de.ibm.com), Software Engineer, IBM

Sascha Schwarze photoSascha Schwarze works as a software engineer at IBM Research and Development lab in Boeblingen, Germany. He is a member of the client development team with a focus on functional quality. As such, Sascha has established automated UI tests for various browsers using Business Space as a user interface for starting tests and analyzing results. Sascha has been part of the development team for WebSphere Process Server and IBM Business Process Manager for the last four years. He joined IBM in 2004 as student in Business Informatics, where he worked on several projects across IBM.



29 June 2011

Overview

In Business Space, when a user works on a task, the Task Information widget uses a form associated with the task definition to visualize data and collect user input. In WebSphere Process Server V7, the Task Information widget can use task forms realized either with HTML and Dojo forms or with IBM Forms. Both can be generated in WebSphere Integration Developer V7 and further customized.

With IBM Business Process Manager Version 7.5, you can now provide your own form renderer using your preferred form technology. For example, you can use browser technologies such as Dojo widgets, embed server-side technologies such as Java™ Server Pages (JSP) within an HTML IFrame element, or use other technologies, such as Adobe® Flash®.

You can implement your custom renderer as a Dojo class and register it with the Task Information widget. The Task Information widget actually includes such a Dojo class to render tasks from BPD processes. It runs the Human service and shows the Coaches of the Human Service embedded in an HTML IFrame element.

This article describes the advantages of using a custom renderer and it then describes the following steps for implementing and installing a custom renderer:

  1. Implementing the custom renderer: The custom renderer is a Dojo class you implement to render the task form and interact with the Task Information widget.
  2. Providing configuration information for the custom form renderer: For the Task Information widget, you need to specify for which task templates your custom renderer should be used.
  3. Registering the custom form with the human task template: In Integration Designer, user interface settings can be specified for a Human Task template. You need to register a new client type in Integration Designer that identifies your custom renderer as a new user interface.
  4. Registering the custom extension service with Business Space: The Task Information widget has an optional service endpoint named custom extension service. You use it to plug your custom renderer implementations into the widget. You need to register your custom extension service implementation so that the Task Information widget can access it.

Why use custom renderers?

When a task is displayed in the Task Information widget, the widget needs a form to display the message. For human tasks these forms can be either generated in Integration Designer or developed as custom renderers.

Although you can customize generated forms, there are some limitations that you can overcome only by using a custom implementation. Here are a few examples:

  • Displaying part of a task message: In some cases you might only want to display a part of the task message in a form. In Dojo forms you must set the form elements to display:none. However, this setting only hides the element, which can have performance impacts. Using a custom renderer, you can keep elements completely out of the document object model (DOM) tree.
  • Mapping elements in the task message to the fields in the form: In Dojo forms and IBM Forms, every element in the task message maps to exactly one input field in the form. This mapping applies even to elements that cannot be edited, such as input data. In a custom renderer you can display these elements as normal text.
  • Using buttons in forms: In Dojo forms and IBM Forms you do not have any control over the Save and Submit buttons because they are owned by the Task Information widget and rendered above the form. In a custom renderer, you can put buttons anywhere in the form. For example, for a confirmation style task you could include Yes and No buttons. Each of these buttons sends a different message to the API when the task is completed.
  • Entering data: With custom renderers, you do not need to rely on normal input fields to supply the data required by the task. For example, you could add tariff options to a contract by dragging the data from a custom iWidget to your custom form. Or, you could use a visual map to select an address so that the user does not need to enter the data manually.
  • Using other technologies
    With custom renderers you can include technologies other than JavaScript, such as JSP using IFrames or Adobe Flash as an embedded object.

Although custom renderers offer many advantages, they also bring some additional responsibilities, which the Task Information widget takes care of for generated forms:

  • You need to create the user interface from scratch. This will take time for your first custom form. However, by creating reusable artifacts, you can then reuse UI elements when you implement further forms.
  • You implement the communication with the API, which includes:
    • Retrieving an input or output message and filling the form with the data
    • Creating a message to send it to the API to start or complete a task. In Business Process Manager V7.5, you can now retrieve and send messages in JavaScript Object Notation (JSON) as an alternative to Extensible Markup Language (XML). JSON is a data format that can be easily converted from and to JavaScript objects. For example you can use the functions dojo.toJson() and dojo.fromJson() from the Dojo Toolkit.

In conclusion, use a generated form if you want to quickly use your task in Business Space or customization is not required. With a custom renderer, you can easily define the layout of a form, use custom input methods, and use other technologies, such as JSP. Using a custom renderer, you can easily design, develop and test your forms independent of Business Space.


Step 1: Implement the custom renderer

IBM Business Process Manager provides a super class, com.ibm.task.form.Renderer, for implementing custom renderers. To develop a custom renderer, implement a Dojo class that is derived from this class. Your implementation must display the task form to the user and interact with the API when the user performs an action in the form.

You can use IBM Rational® Application Developer V8 or IBM Integration Designer V7.5 as your development environment. Both provide a powerful JavaScript editor with auto-completion and validation for native JavaScript and Dojo Toolkit functionality, as well as testing capabilities.

The following listing shows a simple renderer implementation, CardNumberForm.js, that displays an input field with the label Card Number and a Send button. The implementation uses the dijit._Templated Dojo mixin to define the user interface as an HTML template that is resolved at construction and put in the DOM tree by the load() function.

Listing 1. CardNumberForm.js
dojo.provide("com.acme.CardNumberForm");

dojo.require("com.ibm.task.form.Renderer");

dojo.declare("com.acme.CardNumberForm", [dijit._Widget, dijit._Templated, 
com.ibm.task.form.Renderer], {

	cardNumberInput: null,
	templateString: "<div><p>Card Number: " +
               "<input type='text' dojoAttachPoint='cardNumberInput' /></p>" +
               "<p><button dojoAttachEvent='onclick: submit'>Send</button></p></div>",

	load: function(elem) {
		this.placeAt(elem);
	},

	unload: function() {
		this.destroy();
	},

	submit: function() {
		var url = this.htmServiceURL + "v1/task/" + this.task.tkiid
				+ "?action=complete";

		var message = {
			"cardNumber": this.cardNumberInput.value
		};

		var that = this;

		dojo.xhrPut({
			"url": url,
			"contentType": "application/json; charset=UTF-8",
			"putData": dojo.toJson(message),
			"handleAs": "json",
			"load": function() {
				that.onSubmitted(that.task.tkiid);
			},
			"error": function(response) {
				that.onErrorOccurred(response);
			}
		});
	}
});

The following functions and callbacks from the com.ibm.task.form.Renderer class are used in the sample implementation to interact with the Task Information widget:

  • The task or task template object, the iContext of the iWidget, and the endpoint URLs are provided as parameters to the constructor. If you use the dijit._Widget class as a super type, Dojo automatically mixes these parameters in as member variables. If you do not use this class, you can access the parameters by implementing a constructor.

    In the sample renderer, the htmServiceURL and task members are used. htmServiceURL is a string containing the URL for the Task Services REST API. task is an object containing the task properties, including the tkiid with the task instance identifier.

  • The load() and unload() functions are called at the beginning and end of the implementation to allow the renderer to put content in the DOM tree and to clean up the session when the widget is closed. In the sample renderer, the load() function takes the elem parameter and places itself at that position in the DOM tree. During unload, the destroy method provided by the dijit._Widget class is called.
  • The onSubmitted() and onSaved() callbacks must be invoked by the renderer to notify the Task Information widget that the renderer made an API call that changed the status of the task. For example, when a user completes his or her work on a task, you can call the onSubmitted() callback and the Task Information widget closes the task tab and fires a widget event to notify other widgets of the change in status of the task. The sample renderer calls the onSubmitted() callback if the REST API request to complete the task is successful.
  • Calling the onErrorOccurred() callback with an error message as a parameter displays a dialog in Business Space, which contains the message. The sample renderer calls the onErrorOccurred() callback if the REST API request to complete the task fails. This might happen, for example, if the corresponding BPEL process activity is skipped.

The com.ibm.task.form.Renderer class also provides the following functions and callbacks that you can use in your custom renderer implementation:

  • The enableActions() and disableActions() functions are called depending on the state of the task. For example, a task is currently suspended and therefore it cannot be completed. The Task Information widget takes the role of telling the renderer whether the current task can be completed.
  • The onCanceled() callback allows the task tab to be closed without any further actions.
  • The resize(), show() and hide() functions are called to give the renderer information about the layout status. The Task Information widget automatically hides the form if another tab is selected by the user, therefore usually you do not need to implement these functions unless you manually size parts of your form, which is only possible if the DOM tree containing the form is currently visible.
  • The callbacks onDirty(), onReset(), onValid() and onInvalid() can be called to tell the Task Information widget about the current state of the form. If, for example, the user tries to close a tab that contains unsaved changes, the Task Information widget automatically displays dirty markers and prompts the user to cancel the closure.

Step 2: Provide configuration information for the custom form renderer

The custom form renderer is made available in a custom extension service. You need to provide the extension service with configuration information for the custom renderer. To do this, you create a configuration file, config.json, and place it at the root of the web application, as shown in Figure 1.

Figure 1. Web project with the config.json file
Web project with the config.json file

The config.json file registers the custom renderer with the Task Information widget, providing its location, class name, and the client type it is associated with. The following listing shows a sample configuration file. The sample renderer is registered as the CardNumberForm client type.

Listing 2. config.json file for the sample renderer
{
	"renderers" : [
		{
			"clientType" : "CardNumberForm",
			"location" : "/script",
			"className" : "com.acme.CardNumberForm"
		}
	]
}

If you have only one renderer, you can omit the client type. This renderer is then used for all human tasks that do not have a matching renderer.

After you have created the config.json file, package all the files that belong to the custom renderer, including the script, CSS, and image files, and the config.json file as a web application. If you provide a pure browser-based implementation, this static content could be directly served from a Web server.


Step 3: Register the custom form with the human task template

A custom renderer always maps to a client type. In Integration Designer, the client type must be registered in the Human Task editor as the user interface for all the human tasks it is used for.

You can assign one client type to multiple task templates. If you are implementing custom renderers for several task templates, you can do this in one of the following ways:

  • You can define one client type and one custom renderer for each task that you want to use a custom form for. This is useful as long as you have only a small number of task forms.
  • If you have a lot of different forms, you can define a single client type and implement a single custom renderer. In this renderer you then delegate to different implementations based on the task definition name, the message types, or the custom client settings. This is particularly useful if you leverage a templating engine such as Velocity and delegate to a form template provided with each task template.

    One client type for multiple tasks is also suitable if you implement a custom renderer as a wrapper for rendering technologies other than HTML and Dojo, such as Flash.

Figure 2 shows how you assign the client type to the user interface in Integration Designer:

Figure 2. Assign the client type to the user interface
Assign the client type to the user interface

To add the client type to the list of the available user interfaces, you need to implement an Eclipse plug-in as described in the support topic How to embed a custom client type into the human task editor.


Step 4: Register the custom extension service with Business Space

The web application with the custom renderer and the config.json file needs to be deployed to the application server. For a clustered environment, you might want to deploy the web application in the same cluster as Business Space. This way, the browser can directly access the files. When files are served from a different site, the AJAX proxy in Business Space needs to be used to overcome cross-site scripting, a type of browser security vulnerability.

To make the web application available to Business Space, you need to register it as a custom extension service endpoint by doing the following:

  1. Create an endpoint definition XML file to define the endpoint for the custom extension service. The name of the endpoint must be {com.ibm.bpm}CustomExtension. Listing 3 shows the content of the endpoint file. Note that the id, type and version elements have fixed values, but you need to change the value of the url element to match the context root of your web application.
Listing 3. CustomExtensionServiceEndpoint.xml
<?xml version="1.0" encoding="UTF-8"?>
<tns:BusinessSpaceRegistry xmlns:tns="http://com.ibm.bspace/BusinessSpaceRegistry" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://com.ibm.bspace/BusinessSpaceRegistry 
BusinessSpaceRegistry.xsd ">
  <tns:Endpoint>
    <tns:id>{com.ibm.bpm}CustomExtension</tns:id>
    <tns:type>{com.ibm.bpm}CustomExtension</tns:type>
    <tns:version>7.5.0.0</tns:version>
    <tns:url>/AcmeCustomExtension</tns:url>
    <tns:description>Location of the ACME custom extension service</tns:description>
  </tns:Endpoint>
</tns:BusinessSpaceRegistry>
  1. Use wsadmin and the updateBusinessSpaceWidgets AdminTask with the endpoint definition file to register the custom extension service with Business Space. Listing 4 shows the syntax of the command.
Listing 4. updateBusinessSpaceWidgets command for wsadmin
AdminTask.updateBusinessSpaceWidgets('[-nodeName acmeNode -serverName server1 
-endpoints CustomExtensionServiceEndpoint.xml]')
AdminConfig.save()

Conclusion

In this article, you created a custom renderer class to display the task form for a task with a simple message. The renderer was assigned the CardNumberForm client type, which was registered with the human task in Integration Designer and also with the Task Information widget using the config.json file. You packaged all the renderer-related files in a web application and registered it as custom extension service with Business Space.

If you now log in to Business Space and open a task in the Task Information widget that references the CardNumberForm as the client type, the custom renderer will be used to display the form.

While you implemented a simple custom renderer for a single task template, you have also seen how the same extension point can be leveraged to integrate other form technologies and template engines.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=682005
ArticleTitle=Business spaces for human-centric BPM, Part 4: Using custom form renderer for human tasks
publish-date=06292011