Create a mobile BPM application by integrating IBM Worklight and IBM Business Process Manager

This article describes how to integrate IBM® Worklight® and IBM Business Process Manager V8.0.1 Standard (IBM BPM) by leveraging the IBM BPM REST APIs. By combining the powerful development environment of IBM Worklight with the simplicity of the IBM BPM REST APIs, BPM developers can quickly deliver mobile applications to their BPM users. This content is part of the IBM Business Process Management Journal.

Gianpaolo Gabutti (ggabutti@it.ibm.com), Senior IT Specialist, IBM

Gianpaolo GabuttiGianpaolo Gabutti is a Senior IT Specialist in Italy, where he works as a business process management consultant in IBM Software Services for WebSphere. He has been working in the IT industry since 1988, and has experience in diverse technologies, such as object-oriented programming, Enterprise Application Integration, J2EE and Eclipse. He holds a degree in Economics from the Catholic University of Milan.



Luciano Raso (luciano.raso@it.ibm.com), Senior IT Architect, IBM

Luciano RasoLuciano Raso is an IBM IT Architect from Italy. In IBM since 1989, he has been working as an IT architect on different technologies related first to distributed systems and then to JEE systems. In 2010, he joined Software Group as a Technical Sales and Solution Specialist in the business process management (BPM) and operational decision management (ODM) areas. He holds a degree in Electronic Engineering.



Tony Pigram (tony.pigram@uk.ibm.com), Solution Architect, IBM

Tony Pigram photoTony Pigram is an IBM Solution Architect with 20 years experience across a broad spectrum of technologies. He spent seven of those years working as a Consultant in the Enterprise Mobile Application industry. He currently works on the IBM Smarter Process portfolio.



28 August 2013

Also available in Portuguese

Introduction

This article describes the various components of a simple IBM Worklight mobile application that interacts with BPM processes via REST API calls. It shows all of the necessary components needed to create a Worklight mobile application (in an Android™ environment) that enables authorised BPM users to activate, work on, and complete process tasks using their mobile devices.

This article is targeted mainly at BPM developers who want to better understand how to enhance their BPM solutions with mobile capabilities, or who need to quickly improve their understanding of the possibilities offered by integrating the two products. The focus of this article is on hands-on development, not on infrastructure.

For all the aforementioned reasons and from an architectural standpoint, we have decided to keep things as simple as possible. We developed our solution on the simplest and most basic environment, composed of a standalone IBM BPM server (IBM BPM Express V8.0.1), and IBM Worklight Developer Edition V5.0.6, because this environment is likely available to the majority of the readers. This simplified architecture has the advantage of being installable on a single machine (the reader's laptop, for example) and can therefore be utilised as a self-study environment by "lone" developers to prove the concept and to enhance it as they experiment and learn more.

Although we assume that the reader has a basic knowledge of Java, JavaScript®, jQuery and BPM development, we have tried to avoid any possible complexity that could make reading this article particularly difficult to inexperienced developers.

Sample code is included so you can set up and test the scenario yourself (and make your own improvements). This solution is a sample of the capabilities, and should only be used as a learning exercise in a development or test environment for self-study and education purposes.

Prerequisites

The process package is composed of a sample BPM process application called Car Tyres Order Placement, or CTOP, developed with IBM BPM Express V8.0.1 and available in the file CarTyresOrderPlacement.twx.

The mobile package is composed of an IBM Worklight project, CarTyresOrderPlacementProject, developed with IBM Worklight Developer V5.0.6 in an Eclipse Juno 4.2 SR2 installation. The package is available in the file CarTyresOrderPlacementProject.zip

The operating system we used was Microsoft® Windows® 7 with Java® Development Kit Version 7 Update 13.

While we were writing the article, IBM released a new version of IBM Worklight (V6.0). We tested the Worklight project in the new release and have not found any issues in migrating or running our artefacts (adapters and application), so you can decide which version of Worklight to use. Please note that the only supported Eclipse version for Worklight V6.0 is Eclipse Juno 4.2 SR2 package.

IBM also released a new version of IBM BPM (V8.5), and we also tested in this new release and found no obvious issues. However, be aware that we developed and tested this sample on a BPM V8.0.1 environment.

In order to set up your IBM Worklight environment, we recommend that you follow the instructions in IBM Worklight : Getting started. We will assume you are familiar with those documents and have followed those instructions.

You can import the sample IBM Worklight project into your Eclipse workspace in the same way as any other Eclipse project, although you must have previously installed the IBM Worklight plug-in, as instructed on the above link.

To import the sample, download and unzip the file onto your hard drive and use the standard Eclipse option Import => Existing project into workspace.

In order to view the sample BPM process, you will also need to import the provided .twx file into your BPM environment. Although not necessary, you may want to create some users in your BPM Process Center server (the user repository used by the process application). We assume that you know how to create BPM internal users using the Process Admin Console. If not, refer to the product documentation.


Overview of IBM Worklight

Worklight helps organisations extend their business to mobile devices. It provides an open, comprehensive and advanced mobile application platform to build, run and manage mobile applications. With Worklight, you can effectively develop, run and manage HTML5, hybrid and native apps, and reduce your development cost, improve time-to-market and enhance mobile app governance and security. IBM Worklight uses standards-based technologies that avoid the use of code translation, proprietary interpreters and unpopular scripting languages.

A good starting point for understanding IBM Worklight is IBM Worklight : Getting Started. Here you'll find videos, demos, how-to information and other materials to help you gain a thorough understanding of Worklight. You can also check out the Worklight Developer Edition support community on stackoverflow to ask questions and find answers about getting, installing, and using Worklight.


Setting up the environment

After successfully installing and setting up the IBM Worklight and IBM BPM environments, you need to import the sample process. Open the IBM BPM Process Designer and import the process application called Car Tyre Order Placement (CTOP) contained in the file CarTyresOrderPlacement.twx included in the download sample package.

Test the sample process

Once you have imported the process application, open it in the Process Designer and then open the BPD called Car Tyres Order Placement. then click Run to execute a new process instance. Switch to the Process Inspector view and verify that the sample process is working as expected.

Set up IBM Worklight

Unzip the file CarTyresOrderPlacementProject.zip onto your hard drive. Open up your Eclipse IDE and import the project by selecting File => Import, then select Existing project into workspace, as shown in Figure 1.

Figure 1. Import the Worklight project into Eclipse
Import the Worklight project into Eclipse

If you're using Worklight V6.0, the system will recognize that the project needs to be upgraded and will automatically start the migration procedure for you.

For this sample, we used Android as the target platform for the mobile devices, but your choice of the client environment operating system can be different from ours. You can add extra environments to the project after you have tested and ensured that the Android version is working correctly.

Once you've finished importing the project, navigate to the server/conf directory of the project and open the file worklight.properties. You'll need to modify the last section of this file to match your BPM environment settings, as shown in the code snippet below.

########################################
#    Car Tyres Order Placement         #
########################################
bpm.admin.user=admin
bpm.admin.password=admin
bpm.hostname=192.168.201.169
bpm.port=9080

where:

  • bpm.hostname is the BPM host name responding to the REST calls
  • bpm.port is the BPM port number for the REST calls (the default value is 9080).

    Make sure you don't leave trailing blanks on the bpm.port element, or you'll see the following error message on the Worklight console when you deploy the adapters on the server:

    [2013-07-01 10:10:04]    Adapter deployment failed
    [2013-07-01 10:10:04]    Element <port> must be a number.

Overview of the sample process

In order to demonstrate how to integrate Worklight and IBM BPM, we created a simplified business scenario, concerning an fictitious company called FooTyres.com. In our scenario, FooTyres.com is a tyre reseller company. The sales agents of FooTyres.com periodically visit their clients (such as tyre dealers, tyre repairers, car mechanics, and so on) and collect orders from them during their visits. In some cases, the orders are placed by a sales agent after a telephone conversation with the clients.

The sales agent starts the process by filling in the order details (such as the tyre characteristics, the quantity, and the proposed discount rate), and the system will calculate the total price for the order. Once the sales agent fills in the remaining details (such as shipment address and due date), and the client is happy with the calculated price, the sales agent can send the order for approval. If the order has a total price or a discount rate greater than a given threshold (in our sample these limits have been set to 5000 for the total price and to 8% for the discount rate), the order requires approval by a sales manager. If the total price or discount rate is lower than the threshold, the order does not require approval and goes directly to the warehouse for shipment (the order is auto-approved).

The sales manager has the ability to reject the order for commercial reasons (for example, if they believe the discount rate is too high or the total price for the order is excessive for that specific client). In such cases, the sales manager must explain the reason for the rejection and the order will be returned to the sales person. The sales person then has to decide to cancel the order, or resend it for approval, usually after having made an update. If the sales manager approves the order, it is sent to the warehouse for the fulfillment.

The warehouse manager also has the ability to return the order to the sales agent, but in this case the reason is bound to logistic issues, for example, because they know they have run out of stock for that particular tyre, or because it is impossible for them to arrange the shipment by the expected date. Likewise the sales managers have the ability to notify the sales agent of the reasons for their refusal to proceed with the order. Once the order has returned to the sales agent, he or she can update the order details (by changing, for example, the expected delivery date) and resubmit or cancel the order.

Once the order has been approved by the warehouse managers, the shipment is arranged and the process terminates. At this point, the process could be extended to notify an external accounting system, but this is not included in our sample.

The business scenario is illustrated in the business process definition (BPD) shown in Figure 2.

Figure 2. The sample process
The sample process

A walkthrough of the scenario

To better understand which files and code do what, we'll step through a scenario from the mobile application and indicate which related code is responsible for the functionality. To test the application, we'll use the Android v4.0.3 emulator.

From the Home page of the device, select to see the installed applications and click the CarTyresOrderPlacement icon, as shown in Figure 3.

Figure 3. Start the application
Start the application

This starts the application and displays the initial screen. If the user is not already logged in, he or she will see a simple screen showing two buttons: Get Task List and Logout.

Clicking Get Task List invokes the challenge interaction (explained in depth in Implement authentication and, if the user isn't logged in, he or she is prompted to enter a user name and password, then click Submit, which again invokes the challenge interaction. The authentication adapter is called and an attempt to log in is made.

If this fails (for instance, the user forgot to change the IP address of the BPM server), the error message in Figure 4 is displayed.

Figure 4. Authentication error message
Authentication error message

As you can see, the IP address that was set in the worklight.properties file points to 192.168.201.169. Because this is incorrect, an exception is thrown. The Worklight console log also displays the message shown in Figure 5.

Figure 5. Worklight console output
Worklight console output

As you can see, that message is little more detailed. You need to open the worklight.properties file and modify it point to the correct location of the BPM server, as shown in the code snippet below.

#############################################################
#    Car Tyres Order Placement  
#############################################################
bpm.admin.user=admin
bpm.admin.password=admin
bpm.hostname=192.168.201.172
bpm.port=9083

Once you've made this update, you'll need to rebuild and redeploy the application on the Android environment. After downloading and reinstalling the application onto the device, you can log in as before. Once you're successfully authenticated, you'll see the BPM Task list associated with the user (you).

Fetch and render the task list

As mentioned, clicking Get Task List" invokes the challenge interaction. This is done internally by Worklight because we have declared this method "protected" in the authenticationConfig.xml file.

Once the challenge has completed, the BPM task list is sent to the client application to be processed and rendered to the UI. Here is what happens in the callback function: function getTaskListOK(response) The purpose of this function is to receive the data returned by the adapter and to dynamically construct the content to be output to the <div> tag named responseDiv.

You can click on a listed task to open it, as shown in Figure 6.

Figure 6. Task list screen
Task list screen

Notice the click handler attached to each row (of class taskRow) representing an available task, as shown in the snippet below.

$('tr.taskRow').click(function() {
	var idx = $('tr').index(this);
	showOrder(myTaskData[idx-1].instanceId, myTaskData[idx-1].taskId);
});

This JavaScript snippet invokes the showOrder() function when the task is clicked on by a user. The function is passed the instance id and the task id.

If you click on the first row in Figure 6, you should see the screen shown in Figure 7.

Figure 7. Existing order details
Existing order details

The screen indicates that this order was previously submitted and was automatically approved. The fields are in read-only mode, except for the Notes field, which can be modified if there are further instructions for the shipping manager.

If you click the Get Task List button, you are returned to the initial task list screen.

To create a New Order on the mobile device, click the New Order button. A new order submission screen is displayed, as shown in Figure 8.

Figure 8. New order
New order

The values for the dropdown selection boxes are located in the UIMaterial.js file. For this sample, these values were hard-coded because they are unlikely to change often, if at all. The actual HTML for the screens is also hard-coded in the UIMaterial.js file. Depending upon which screen is being rendered, a call to the relevant function is made and a string response is returned. This is, in turn, returned and rendered in the responseDiv div tag. Following is function that returns the code to render the New Order screen.

//Get the layout for placing a new order or updating an existing one 
	(most of the data can be entered / updated)
	function getNewOrderLayout() {
	
		return '<div class="box" id="message"></div>' + 
			'<select id="widthSelect"></select><select id="profileSelect" 
				style="float: right;"></select>
			<br><br>'+
			'<select id="rimSizeSelect"></select>
			<select id="quantitySelect" style="float: right;"></select>
			<br><br>'+
			'<label id="unitPriceLabel" for="unitPriceOutput" style="float: left; 
				">Unit Price : </label>
			<label  isNumeric="true" baseType="Decimal" id="unitPriceOutput" 
				style="font-weight : bold; ">0</label>'+
			'<span style="float: right;margin-right:10px">
			<label class="" id="totalPriceLabel" for="totalPriceOutput" 
				>Total Price : </label>
			<label isNumeric="true" baseType="Decimal" id="totalPriceOutput" 
				style="font-weight : bold;" >0</label>
			</span><br><br>'+
			'<select id="discountSelect"></select>
			<input type="button" value="Calculate Price" onclick="calculatePrice()" 
				class="formButton" style="float: right;" />
			<br><br>'+
			'<table width="100%">'+
			'<tr>
			<td><label class="" id="nameLabel" for="nameInput" 
				>Name :  </label></td>
			<td colspan="2"><input id="nameInput" type="text" value="" 
				initialValue="" style="width: 100%; float: right;" /></td>
			</tr>'+
			'<tr><td><label class="" id="streetLabel" for="streetInput" 
				>Street : </label></td>
			<td colspan="2"><input id="streetInput" type="text" value="" 
				initialValue="" style="width: 100%;float: right;"/></td>
			</tr>'+
			'<tr>
			<td><label class="" id="cityLabel" for="cityInput" 
				>City : </label></td>
			<td colspan="2"><input id="cityInput" type="text" value="" 
				initialValue="" style="width: 100%;float: right;" /></td>
			</tr>'+
			'<tr>
			<td><label class="" id="datePickerLabel" for="datePicker" 
				>Shipment Date : </label></td>
			<td><input id="datePicker" type="text" 
				style="width: 100%;float: right;" />
			</td>
			</tr>'+
			'</table><br><br>'+
			'<label class="" id="notesLabel" for="noteInput" 
				>Notes : </label>
			<textarea  id="notesInput" rows="2" 
				style="width: 80%;float: right;"></textarea>
			<br><br>';
			
	}

This function might look a little weird at first glance, but it actually simply returns a String representing the content for a div HTML element. The div is further manipulated by some jQuery code, as you'll see in the section Client-side development. The user can select the values from the selection boxes, as shown in Figure 9.

Figure 9. Device dropdown selection
Device dropdown selection

In a web browser, the dropdown selection box would have just shown itself as such on the page and the user would have selected a value with either the keyboard or a mouse click. However, because this application is running on a mobile device, the native method of rendering a dropdown selection is used. The user can swipe up and down to go through the list of items. The UI functions the same way for the Profile, Rim Size, Quantity and Discount fields.

Once those fields have been selected, the user can press the Calculate Price button, as shown in Figure 10 to calculate the Unit and Total price based upon any selected Discount value.

Figure 10. JQuery datePicker control
JQuery DatePicker control

The user can then enter text for Name, Street and City. Since this is a mobile application, text entry should be kept to a minimum to prevent typing mistakes.

When the user clicks the Shipment Date field, the jQuery datePicker is displayed, as shown in Figure 10 and he or she can scroll through a calendar to select a future date.

The code to include the datePicker in the screen is located in three files: UIMaterial.js, CarTyresOrderPlacement.js and CarTyresOrderPlacement.html. As mentioned earlier, the UIMaterial.js file returns the HTML to render the output to the screen. The following snippet shows where the datePicker is defined.

<input id="datePicker" type="text" style="width: 100%;float: right;" />

In the CarTyresOrderPlacement.js file, an initialiser function is called when the New Order screen is to be displayed. This initialises the datePicker and sets the correct date format. Because the input field has an id of datePicker, it is detected as requiring the pop-up calendar to be invoked as shown below.

function initNewOrderLayout() {

	$('#ResponseDiv').html(getNewOrderLayout());
	$('#message').hide(); // Hide the message box
	$('#message').click(function() {

		$('.box').animate({
			opacity : 'toggle',
			height : 'toggle'
		});
	});
	//Init the date picker with the proper format...
	$( "#datePicker" ).datepicker({ dateFormat: "dd-mm-yy" });
	
	addOptions('#widthSelect', widthOptions);
	addOptions('#profileSelect', profileOptions);
	addOptions('#rimSizeSelect', rimSizeOptions);
	addOptions('#quantitySelect', quantityOptions);
	addOptions('#discountSelect', discountOptions);
}

Finally, the CarTyresOrderPlacement.html file contains the include files that are required for the JQuery DatePicker, as shown in the snippet below.

	<!-- jquery for custom datePicker -->
	<link rel="stylesheet"    
    href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
	<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
	<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
	<!-- jquery for custom datePicker -->

Check out the jQuery datepicker web site for more information on the jQuery datePicker.

Submit the new order

Once the user has finished entering the details, he or she can press Submit Order, as shown in Figure 11.

Figure 11. Submit a new order
Submit a new order

The new order details are passed back to the newOrder() function (contained in the CarTyresPlacement.js file). As shown in the snippet below, this function then calls the startProcess() function in the CarTyresOrderPlacementSOAPAdapter-impl.js file. The startProcess() function constructs a SOAP message containing the new order data and invokes a SOAP call to the BPM server.

Note that the other interactions, such as getOrderDetails, getTaskList and CompleteOrder use the REST API.

function newOrder() {

	initNewOrderLayout();

	$('#newOrder').hide(); // Hide new order button
	$('#submitOrder').show(); // Show submit order button
	$('#complete').hide();// Hide complete button
	$('#header').html("New order submission");
	$('#submitOrder').click(function() {
		hideMessage();

		var myOrder = checkOrder();
		// WL.Logger.debug(JSON.stringify(myOrder));

		if (myOrder != null) {
			var invocationData = {
				adapter : "CarTyresOrderPlacementSOAPAdapter",
				procedure : "startProcess",
				parameters : [ myOrder ]
			};
			var options = {
				onSuccess : newOrderOK,
				onFailure : newOrderFAIL
			};
	
			WL.Client.invokeProcedure(invocationData, options);
		}

	});
}

Once the submission has been successful, the user gets the message shown in Figure 12.

Figure 12. New order successful
New order successful message

If for some reason the order submission failed, the user is informed of this via this same mechanism. You can use Process Designer to verify that the new order submission really worked. Load the Car Tyres Order Placement process and click on the Process Inspector view, as shown in Figure 13.

Figure 13. Process Inspector view
Process Inspector view

Here you can see that a new process instance has been created and that the process token has moved onto the Approval step. By using the debugging feature on the right, you can double-click the order variable and view the contents to verify that the data you entered on the New Order screen on the mobile device has been successfully passed to this new process instance.

Now, when you return back to the Task List screen on the mobile device, shown in Figure 14 you will see the new task in the list and you will see that the indicator is a different colour, which indicates that the task requires approval.

Figure 14. Task List showing new task in the list
Task List showing new task in the list

Note: Because we're logged in as admin in our sample, we're able to see all tasks associated with the sample process. If you were logged in as a non-admin user, you would only see the tasks that belong to our user. Because this is a developer article, we want to show everything, but be aware that when you run this sample with a real user account assigned to the swimlanes and activities, you won't see tasks that do not belong to you on the Task List screen.

If you click on the last Task in the list (the new order that is awaiting approval), you can verify that the data is correct, as shown in .

Figure 15. Display task details
Display task details

The screen in is dynamically constructed from the getApproveOrderLayout() function in the UIMaterial.js file. The actual order details are retrieved by calling the getOrderDetails() function in the CarTyresOrderPlacement.js file, as shown below.

function getOrderDetails(taskId,callBack) {

	var order = null;
	var invocationData = {
		adapter : "CarTyresOrderPlacementRestAdapter",
		procedure : "getOrderDetailByTaskId",
		parameters : [ taskId ]
	};

	WL.Client.invokeProcedure(invocationData,
					{
						onSuccess : function(response) {
    [...]

This in turn calls the REST API adapter getOrderDetailByTaskId() function in the CarTyresOrderPlacementRestAdapter-impl.js file, as shown below.

function getOrderDetailByTaskId(taskId){
	
	path = 'rest/bpm/wle/v1/task/'+taskId+'?parts=all';
	
	var input = {
	    method : 'get',
	    returnedContentType : 'json',
	    path : path
	};
	
	response=WL.Server.invokeHttp(input);
	WL.Logger.debug(JSON.stringify(response));
	return response;
}

Log out

On any of the screens, the user can click on Logout to cancel the current session authentication. If the user subsequently selects Get Task List, he or she will have to re-enter the user name and password and be re-authenticated.

Approve an order

The approval scenario occurs when an order needs approval by the managers or by the warehouse. In this scenario, most of the order data is presented as labels, because it cannot be modified by the approvers, except for the Notes field, where the approvers are supposed to enter the reason for denying approval before sending back the order to the sale agent, and the Approved and Shipped checkboxes.

Update an existing order

This scenario occurs when an order has been sent back to the sales agents by the managers or by the warehouse. The UI in this case is similar to that in the Submit the New Order scenario, except that in this case the data is already filled in and ready to be modified.


Server-side development

For information on the role of the adapters in Worklight, their different typology, and how to configure them, refer to the developerWorks Worklight server-side development documents.

Our sample shows the usage of HTTP adapters in two different flavours: a SOAP/HTTP adapter (the adapter that starts the process) and a REST adapter (to carry on all other interactions with the BPM server)

Implement authentication

In a real production environment, the authentication will be handled differently than in our sample application. Nevertheless, we believe there are some advantages in developing an ad-hoc, simplified authentication mechanism, even for a basic environment such as ours, because:

  • It helps in understanding the functioning of the authentication and authorisation mechanism available out-of-the-box with IBM Worklight.
  • It can be used in proofs of concept to simulate the runtime behaviour for more complex environments.

A general description of how security is handled by the IBM Worklight platform is explained in detail in the developerWorks Worklight authentication and security topics. These documents provide clear and simple instructions on how to create adapters using the wizard that comes with the Worklight plug-in.

Before discussing the adapter authentication implementation, we want to clarify some concepts that we believe are important to understand before proceeding further. As described in the IBM Worklight documentation:

  • An authenticator is a server-side entity responsible for collecting the credentials from the client application (this activity is also called "challenge").
  • A login module is a server-side entity responsible for verifying the user credentials (and for creating a user identity object, which holds the user properties for the remainder of the session).
  • An authentication realm defines the process to be used to authenticate users.
    • Each authentication realm consists of one authenticator and one login module.
    • Each authentication realm requires a challenge handler component to be present on a client side.
  • A security test is an ordered set of authentication realms that is used to protect a resource, such as an adapter procedure, an application, or a static URL.

All these authentication settings are configured in the server/conf/authenticationConfig.xml file of the project.

With a clearer understanding of these concepts, let's look at how to proceed in order to protect a resource (in our case the resource is represented by an adapter procedure).


Server-side configuration

The first things to be configured are the adapter procedures, which need to be protected. In our sample, we've protected the procedure that provides the users with the list of tasks available to them (what's known on a BPM portal server as the Task Inbox view). The procedure's name is getTasksList() and it is implemented by the adapter CarTyresOrderPlacementRestAdapter. You must add the following entry in the CarTyresOrderPlacementRestAdapter.xml file.

<procedure name="getTaskList"
		securityTest="SimpleAuthAdapter-securityTest">
		<description>Gets the initial task list for the user</description>
</procedure>

We are stating here that the usage of this procedure is subject to a security test called "SimpleAuthAdapter-securityTest".

The next step is the definition of the security test: this needs another entry in the file "server/conf/authenticationConfig.xml":

</securityTests>
	<customSecurityTest name="SimpleAuthAdapter-securityTest">
       	<test isInternalUserID="true" realm="CTOPAuthRealm"/>
	</customSecurityTest>  	
</securityTests>

If the internal users are in the authentication realm called CTOPAuthRealm, they are to be considered as authenticated.

The next step is the definition of the realm, which is another entry in the same file, as shown below.

<realms>
   <realm name="CTOPAuthRealm" loginModule="SimpleAuthLoginModule"> 
      <className>com.worklight.integration.auth.AdapterAuthenticator</className>
      <parameter name="login-function" value="SimpleAuthAdapter.onAuthRequired"/>
      <parameter name="logout-function" value="SimpleAuthAdapter.onLogout"/>
   </realm>
</realms>

As defined earlier, an authentication realm is made up of one authenticator and one login module. Therefore, here we declare the login module used by this realm and the class implementation for our authenticator. We also declare the callback methods invoked by Worklight when authentication is required or when the user logs out.

The final configuration step is to define our login module. To do this, you add the entry below in the server/conf/authenticationConfig.xml file.

<loginModules>
	<loginModule name="SimpleAuthLoginModule">
	     <className>com.worklight.core.auth.ext.NonValidatingLoginModule</className>
	</loginModule>
<loginModules>

Here we chose the predefined NonValidatingLoginModule, which means that no additional validation is performed by Worklight, and the developer must take responsibility for the credential validation in the adapter (in our sample, this is contained in SimpleAuthAdapter).

Now that the authentication configuration steps are complete, you need to implement the JavaScript components. To accomplish this, you need a client-side challenge handler and a server-side authenticator.

Implement the challenge handler

The challenge handler must implement two methods:

  • isCustomResponse(): This function is called by Worklight each time that a response is received from the server. It is used to detect whether the response contains data that is related to this challenge handler and must return either true or false.
  • handleChallenge(): If the isCustomResponse returns true, the framework calls the handleChallenge() function. This function is used to perform required actions (in our sample, we present the user with a login screen on which they can enter their user name and password. Once they have entered these values, we invoke the adapter's authentication procedure using the API submitAdapterAuthentication. This challenge handler's API is used to send collected credentials to a specific adapter procedure.

    In the sample provided, you'll find the following this function call:

    var invocationData = {
    	adapter : "SimpleAuthAdapter",
    	procedure : "submitAuthentication",
    	parameters : [ username, password ]
     };
    
     simpleAuthRealmChallengeHandler.submitAdapterAuthentication(invocationData, {});

Implement server-side authentication

On the server side, you need to implement the authenticator SimpleAuthAdapter. To develop our adapter, we found that a good starting point is the example provided in the presentation IBM Worklight V5.0.6 Getting Started: Custom Authenticator and Login Module (PDF).

During the challenge, the client application invokes submitAuthentication(username, password), so you need to create a function to handle this. This function must return a JSON object to the client, stating whether the authentication was successful or not. The returned object is as follows:

{
	authRequired: true,
	errorMessage: errorMessage,
	isSuccessful : false
}

If you need to authenticate the user (the security test was unsuccessful) or if the security test is passed, the following is returned:

{
	authRequired: false
}

By examining our sample, you'll notice that in order to check whether the credentials are valid, the submitAuthentication() function utilises the internal function checkUser(user, password). In our implementation, we send an HTTP post request to the BPM server and check whether the response contains an LtpaToken. If the credentials are valid, the server will send back a cookie (LtpaToken2) to be used for subsequent requests, otherwise the cookie will not be present in the response. For our sample, we're not interested in storing the cookie, we just need to check that it exists.

Following is the implementation of the submitAuthentication() function:

function submitAuthentication(username, password){

	var userDetails = checkUser(username,password);
	
	if (!userDetails.isSuccessful) { 		
		return onAuthRequired(null, userDetails.errors[0]);

	} elseif 
    (userDetails.data != undefined && userDetails.data != null  ){
		//Store user's data
		var userIdentity = {
				userId: username,
				displayName: userDetails.data.fullName,
				attributes: {
					memberships : userDetails.data.memberships
				}
		};

		WL.Server.setActiveUser("CTOPAuthRealm", userIdentity);
		
		return {
			authRequired: false 
		};
	}

It's worth noting that if the authentication succeeded, the user is set as active in the CTOPAuthRealm by using the server API WL.Server.setActiveUser(). This will prevent the failure of further security tests.

The second function that needs to be implemented is the protected function getTaskList(). This performs a query on the BPM server using the REST API, and returns a list of tasks available for the authenticated user (the list is represented by an array of JSON objects). This request is made on behalf of the user, but this time the system utilises the HTTP "basic authentication" mechanism, which we'll explain in more detail.

To confirm what happens at runtime, following is the complete sequence of steps that occur when the protected function is invoked:

  1. The client invokes the adapter's protected procedure (getTaskList()).
  2. Worklight intercepts the request and activates the challenge mechanism. If the security test is not satisfied, the client challenge handler receives a callback on its isCustomResponse method, signaling that authentication is requested.
  3. The client handles the challenge by invoking the adapter's submitAuthentication() procedure
  4. The client receives a second notification and is now able to determine whether the authentication procedure ended successfully (the user is authenticated).
  5. If the user is authenticated, the client informs the server that it intends to carry on with the initial procedure invocation (this is done by invoking the challenge handler API submitSuccess()).
  6. The client receives the response of the initial invocation to the protected procedure and renders the result.

Create the adapters

Each adapter can be created using the wizard provided by the Worklight development environment. When you create a new adapter, you'll see the wizard shown in Figure 16, where you enter the adapter name and type.

Figure 16. Worklight Adapter wizard
Worklight Adapter wizard

This creates a folder with the structure shown in Figure 17.

Figure 17. Adapters folder structure
Adapters folder structure

<AdapterName>.xml is the adapter descriptor, and contains several adapter configuration parameters. If the adapter type is set to HTTP, you need to enter information about the used protocol, the server address and port used for the connection and the type of authentication, as shown in Figure 18.

Figure 18. Adapters descriptor connection policy
Adapters descriptor connection policy

The SOAP adapter

When the user presses the Submit button on the New Order screen, a new process instance of the BPM sample process Car Tyres Order Placement is created. The new instance can be launched using the Start Event (WS Start) that is associated with a web service, as shown in Figure 19.

Figure 19. The entry point of the SOAP adapter in the process
The entry point of the SOAP adapter in the process

This task is performed by the HTTP adapter CarTyresOrderPlacementSOAPAdapter, which is defined by the following descriptor:

<wl:adapter name="CarTyresOrderPlacementSOAPAdapter"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:wl="http://www.worklight.com/integration"
	xmlns:http="http://www.worklight.com/integration/http">

	<displayName>CarTyresOrderPlacementHTTPAdapter</displayName>
	<description>CarTyresOrderPlacementSoapAdapter</description>
	<connectivity>
		<connectionPolicy xsi:type="http:HTTPConnectionPolicyType">
			<protocol>http</protocol>
			<domain>${bpm.hostname}</domain>
			<port>${bpm.port}</port>	
			<authentication>
				<basic />
				<serverIdentity>
					<username>${bpm.admin.user}</username>
					<password>${bpm.admin.password}</password>
				</serverIdentity>
			</authentication>
		</connectionPolicy>
		<loadConstraints maxConcurrentConnectionsPerNode="2" />
	</connectivity>

	<procedure name="startProcess" securityTest="SimpleAuthAdapter-securityTest">
		<displayName>start process</displayName>
	</procedure>
</wl:adapter>

The adapter contains only the procedure exposed to the client: startProcess(order). This procedure is set as protected, (the same as the other procedures in this sample), by means of the security test SimpleAuthAdapter-securityTest described in the previous section. This procedure invokes the web service by building the SOAP envelope derived from the WSDL file that describes the web service itself.

In general, if you have to invoke a web service from a Java class, you can use one of the several frameworks available, such as AXIS, which provides wizards to generate the helper classes as well as the core classes needed to call the web service. These helper classes provide a more abstract layer that helps developers simplify a web service call, thereby hiding the complexity of the marshalling and un-marshalling of the object model used to exchange data between the client and the web service. They also hide the complexity of communicating through the HTTP protocol.

In our sample we're using JavaScript to implement the adapter, not Java, so we have no framework or wizard available to generate the web service request. However, a Worklight HTTP adapter simplifies the exchange of data with a back-end system via the HTTP protocol, because it only requires the SOAP envelope that is needed to invoke the web service.

To create the envelope, we exploited the envelope skeleton generated by the open-source SoapUI tool, which helps with the testing and analyzing of web services. Given a WSDL, SoapUI can generate the corresponding envelope template filled in with the requested data, as shown in Figure 20.

Figure 20. The envelope to start the process as shown in SOAP UI
The envelope to start the process as shown in SOAP UI

Each of the above ? symbols needs to be replaced with the correct data value. Using the following snippet, the adapter can merge the above template with the requested data:

var request = '<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:star="http://CTOP/StartWS.tws">'
			+ '  <soapenv:Header/>'
			+ '  <soapenv:Body>'
			+ '     <star:createOrder>'
			+ '        <star:order>'
			+ '          <star:userId>'+user.userId+'</star:userId>'
			+ '          <star:quantity>'+order.quantity+'</star:quantity>'
			+ '          <star:width>'+order.width+'</star:width>'
			+ '           <star:profile>'+order.profile+'</star:profile>'
			+ '           <star:rimSize>'+order.rimSize+'</star:rimSize>'
			+ '           <star:unitPrice>'+order.unitPrice+'</star:unitPrice>'
			+ '           <star:discount>'+order.discount+'</star:discount>'
			+ '           <star:total>'+order.total+'</star:total>'
			+ '           <star:notes>'+order.notes+'</star:notes>'
			+ '            <star:dateRequired>'+order.dateRequired+'</star:dateRequired>'
			+ '           <star:shippingAddress>'
			+ '                 <star:name>'+order.shippingAddress.name+'</star:name>'
			+ '                 <star:street>'+order.shippingAddress.street+'</star:street>'
			+ '                 <star:city>'+order.shippingAddress.city+'</star:city>'
			+ '           </star:shippingAddress>'
			+ '           <star:approved>'+order.approved+'</star:approved>'
			+ '           <star:canceled>'+order.canceled+'</star:canceled>'
			+ '           <star:shipped>'+order.shipped+'</star:shipped>'
			+ '        </star:order>'
			+ '     </star:createOrder>'
			+ ' </soapenv:Body>'
			+ '</soapenv:Envelope>';

The following snippet obtains the envelope that will be sent to the BPM using the API provided by Worklight:

var path = "teamworks/webservices/CTOP/StartWS.tws";var input = {
		method : 'post',
		returnedContentType : 'xml',
		path : path,
		headers : {
			'SOAPAction' : 'http://CTOP/StartWS.tws/createOrder'
		},
		body : {
			content : request,
			contentType : 'text/xml; charset=utf-8'
		}
	};
	response = WL.Server.invokeHttp(input);

In the snippet above, there is no evidence of the web service endpoint. This is computed by Worklight, which concatenates the information in the adapter descriptor as shown here:

<connectivity>
		<connectionPolicy xsi:type="http:HTTPConnectionPolicyType">
			<protocol>http</protocol>
			<domain>${bpm.hostname}</domain>
			<port>${bpm.port}</port>

The value of the variable path is set to the following:

var path = "teamworks/webservices/CTOP/StartWS.tws";

The REST APIs

IBM BPM provides a set of APIs that are implemented using Representational State Transfer (REST) services. A set of business process definition (BPD) related REST resources are provided for accessing business process, human task and business category data. These REST APIs enable developers to build a user interface or customise an existing portal application. The APIs are simple enough to be called from mobile devices or from Rich Internet Applications (RIAs).

For more information on how to use the REST APIs in IBM BPM, refer to the developerWorks article Using the REST APIs in IBM Business Process Manager V7.5.

The REST adapter

The REST adapter CarTyresOrderPlacementRestAdapter contains all the functions needed to invoke some of the RESTFUL services provide by the IBM BPM. Like the SOAP adapter, the REST adapter is an HTTP adapter. The REST API is invoked through the HTTP protocol. The descriptor of the REST adapter shows that it defines and exposes to the client the following three functions:

function getTaskList()
function getOrderDetailByTaskId(taskId)
function completeOrder(order)

You can define the connectivity policy in the descriptor, as shown in Figure 21, so that when the API WL.Server.invokeHttp is called, you don't need to provide the connectivity details.

Figure 21. The adapter editor
The adapter editor

Following is a brief description of each of the three functions defined by the REST adapter:

Function getTaskList()
The purpose of this function is to retrieve the list of tasks assigned to the current mobile user or to the participant group to which this user belongs. To retrieve the task list the following snippet of code is used:
function getTaskList() {
	var user = WL.Server.getActiveUser().userId;
	path = 
'rest/bpm/wle/v1/search/query?condition=bpdName%7CCar%20Tyres%20Order%20Placement&
condition=taskStatus%7CReceived&organization=byInstance';
	var input = {
		method : 'put',
		returnedContentType : 'json',
		path : path
	};
	return filterTaskList(WL.Server.invokeHttp(input), user);
}

Because the authentication mechanism is based on the information hard-coded in the adapter descriptor, each call to a service is done using the "admin" user. In this way, the retrieved task list can contain tasks that cannot be assigned to the user logged into the mobile application. For this reason, the task list must be filtered in order to exclude those tasks and only include the tasks that belong to the logged in user.

In order to do that, for each task the assignedTo property is compared to the list of groups to which the logged on user belongs. If the task is assigned to a group of which the user is member the task is left in the list, otherwise it is removed.

function filterTaskList(response, user) {
	var filteredTaskList = [];
	var data = response.data.data;
	var groups = getUserGroups(user);
	for ( var i = 0; i < data.length; i++) {
		var task = data[i];
		if (checkAssignement(task,user,groups)){
			filteredTaskList[filteredTaskList.length]=task;
		}
	}
	response.data.data=filteredTaskList;
	return response;
}

To retrieve the list of groups to which the user belongs, you can use the following function:
function getUserGroups(user) {
	var groups = new Array();
	var path = 'rest/bpm/wle/v1/users?filter='
			+ user
			+ '&includeTaskExperts=false&sort=true
                &includeInternalMemberships=true&parts=all';
	var input = {
		method : 'get',
		returnedContentType : 'json',
		path : path
	};
	response = WL.Server.invokeHttp(input);	
	if (response != null 
            && response.data.users.length > 0) {
		groups = response.data.users[0].memberships;
	}
	return groups;
}
Function getOrderDetailByTaskId(taskId)
When the user selects a row on the task list, the data related to the corresponding order is retrieved by calling this function. In this case, the required data is retrieved calling a RESTful service provided by BPM. This function does not present any particular issue, as you can see by looking at the following code:
function getOrderDetailByTaskId(taskId) {
	path = 'rest/bpm/wle/v1/task/' + taskId + '?parts=all';
	var input = {
		method : 'get',
		returnedContentType : 'json',
		path : path
	};
	response = WL.Server.invokeHttp(input);
	return response;
}
function completeOrder(order)
When the user creates or approves a new order or modifies a rejected order they have to press the Submit button to invoke the function.

This function calls a RESTful service and passes the order data that the user has entered via the mobile application. This behaviour is the same as if the user had worked on the order within a traditional BPM human task coach. Because a task has been created in BPM, the task data is passed to that service and the task is completed. Once this occurs, the process flows to the next task in the process.

The only remarkable aspect in this function is that BPM expects the date in ISO 8601 format (0000-00-00T00:00:00Z), but when JavaScript converts the object order from JSON to a String, each property defined as a date is converted in the format 0000-00-00T01:02:03.mmmmZ, which makes the REST call fail. We solved the problem with the following workaround:

var orderToBeSent = JSON.stringify(bpmOrder).replace(/\.[0-9][0-9][0-9]Z/g,"Z");

This replaces each date to the format as expected by BPM. The following is the complete function code:

function completeOrder(order) {
	var bpmOrder = new BPMOrder(order);
	if (bpmOrder.userId == null || bpmOrder.userId == "")
		bpmOrder.userId = "admin";
	var orderToBeSent = JSON.stringify(bpmOrder).replace(/\.[0-9][0-9][0-9]Z/g,"Z"); 
// correct date format: millisec not accepted by bpm -> from
					// 0000-00-00T01:02:03.mmmmZ to 0000-00-00T01:02:03Z
	path = 'rest/bpm/wle/v1/task/' + order.taskId + '?action=finish&params='
			+ escape('{"order":' + orderToBeSent + '}') + '&parts=all';
	var input = {
		method : 'put',
		returnedContentType : 'json',
		path : path
	};
	response = WL.Server.invokeHttp(input);
	return response;
}

Client-side development

Although there are many possibilities to improve the client UI with fancy widgets, we decided to keep the UI as basic and simple as possible. The UI can be improved in many ways, but this should be done once the basic pieces of functionality have been understood, set up and implemented. We based the UI for this article on what is available out-of-the-box with the IBM Worklight: platform: jQuery.

In order to show how a jQuery plug-in can be effectively used, we placed a jQuery datepicker widget for selecting dates in the UI. The widget is available here.

Client-side material

The client material is composed by a set of JavaScript .js files, an HTML file, a .css file and some images. After you have imported the project into your workspace, open the Java EE perspective and check that the Project Explorer view is the same as shown in Figure 22. The client-side materials are described in this section.

Figure 22. The apps folder structure
The apps folder structure

CarTyresOrderPlacement.html

This is the main HTML page and will not change throughout the lifespan of a user's session. The HTML contains two HTML div elements (ResponseDiv and AuthDiv), which are manipulated through the jQuery functions whenever a response has been received by the Worklight server. A typical example of manipulation of DOM in order to change the div content is represented by the function getTaskListOK(), the callback function that runs upon a successful invocation of the adapter procedure getTaskList() :

var myTaskData = response.invocationResult.data.data;	
	var tasks = null;
	if (myTaskData != null) {
		tasks = $.map(myTaskData, function(value, i) {
			
			var image= "'images/mblDomButtonOrangeBall.png'";
			if (value.taskSubject.indexOf("Approval") > 0)
				image= "'images/mblDomButtonRedBall.png'";
			elseif (value.taskSubject.indexOf("Shipment") > 0)
				image= "'images/mblDomButtonGreenBall.png'";
			
			return '<td><img src='+image+' 
/></td><td><b>Order Number : </b>' 
+ value.instanceId + '&nbsp;<b>Activity : </b>'+ value.taskSubject+'</td>';
		});
	}
	if (tasks == null || tasks.length == 0)
		$('#ResponseDiv').html('No orders found ');
	else
		$('#ResponseDiv').html(
				'<br/><table><tr class="taskRow">' + 
tasks.join('</tr><tr class="taskRow" >') 
+ '</tr></table>');

As you may notice, the JSON object representing the response is used to build a valid array of HTML td elements. These elements are then joined together so to build an HTML table, which is eventually used to set the content of the div (by using the jQuery html() function).

BO.js

Bo.js contains the JavaScript business objects used client-side CarTyresOrderPlacement.js. It contains the main JavaScript code to handle the interactions with the Worklight server. Basically, depending on the button clicked by the user, an adapter procedure gets invoked and a response is received back as a JSON object. The code then builds the content of the ResponseDiv and attaches the handlers to various elements in order to provide the correct sequence of events. The code is commented to make easy to understand what operations are being executed.

You can use the usual JavaScript debugging tools to debug this code when it runs as a common resource or in the mobile browser simulator.

InitOptions.js

This file is generated automatically by the wizard when a new project is generated, and we left it mostly untouched.

Messages.js

This file is also generated automatically by the wizard when a new project is generated. Its purpose is to provide a place for the internationalisation (i18n) of the messages, which we did not consider in our sample (although it is something which is normally necessary in a real world application).

SimpleAuthRealmChallengeProcessor.js

This file contains the JavaScript client code to handle the challenge, as described previously in this article

UIMaterial.js

This file contains some utility functions to support the UI interface.

CarTyresOrderPlacement.css

This file contains the common CSS statements (that is, the default CSS definitions). These statements may be overridden by other CSS files leveled at the diverse environments (such as Android, for example)


Conclusion

In this article, we provided concepts and sample code to help you see the benefits and possibilities of integration between IBM Worklight and IBM BPM using the REST API. It's our hope that you've seen how simple it is to achieve this integration -- not a single line of Java code was needed to develop the application!


Next steps

The following is a list of potential enhancements that you could undertake. These are things that either we didn't have time to finish or would have liked to have done a little differently:

  • Internationalisation
  • Pushing notifications to the mobile users once events occur on the server side
  • UI improvements (using additional jQuery plug-ins)

Downloads

DescriptionNameSize
Sample applicationCarTyresOrderPlacement.twx1MB
Sample project fileCarTyresOrderPlacement.zip17MB

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 Business process management on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Business process management, WebSphere, Mobile development
ArticleID=942182
ArticleTitle=Create a mobile BPM application by integrating IBM Worklight and IBM Business Process Manager
publish-date=08282013