December 2014 - Tony Pigram
"I have 5 minutes to spare, tell me everything I need to know...."
All content in these presentations is for example learning exercises, it has no official support from IBM and if you wish to use this material, you must make sure it is fit for your purpose. No warranty is implied or given.
All REST API Calls are listed here:
http://www.ibm.com/developerworks/websphere/library/techarticles/1108_thaker/1108_thaker.html
AngularJS
Ionic
HTML
JavaScript
AngularJS
Controller
ExpressJS
NodeJS
ExpressJS
REST API
BPM REST API calls
IBM BPM
BPM REST API
event driven calls
secure BPM user event driven calls
The main aim of this presentation is to highlight how to call the BPM REST API and deal with the results.
(It is not the aim to teach you IBM BPM)
A Web client tool is installed on each Process Center and Process Server node as part of the IBM BPM installation. This client tool is useful for learning and getting familiar with the capabilities and functions provided by the REST API. For instance, you can learn about the actual HTTP calls that are made, which is useful for writing your own REST client implementation in the language of your choice. To access this Web client, you can direct your Web browser to the following URL:
Where:
For example, if your IBM BPM server, such as "ibmbpm", uses port 9080 as the HTTP server port, you would use the following URL in your browser to access the IBM BPM REST Api Tester web client.
http://host_name:port_number/bpmrest-ui
http://ibmbpm:9080/bpmrest-ui
http://www-01.ibm.com/support/knowledgecenter/SSFTDH_8.5.5/com.ibm.wbpm.bpc.doc/topics/cdev_restapis.html?lang=en
The Tree navigation on the left-hand side allows you to select which REST API call you wish to make. You will mainly be interested in Process & Task.
Below, you can see an active usage of requesting to see the Task Details for Task Id #403. As this Task has just been created it contains the basic information.
If you have already used IBM BPM and have already created your BPDs with activities and nested services and have built coaches for the end-users to execute your process, then you can easily use the REST API to navigate and populate the process, usually with no modifications required.
If you have not yet created your BPDs and have decided that ALL user interaction will be delivered and managed via external user interfaces then you could consider using External Implementations at the BPD level.
http://www-01.ibm.com/support/knowledgecenter/SSFTDH_8.5.5/com.ibm.wbpm.wle.editor.doc/topics/using_external_activities.html?cp=SSFTDH_8.5.5&lang=en
Our example BPD will contain 2 swimlanes of users.
The initiator of the process will enter details that are then sent to an approver to review and decide to approve or decline.
As is good design, the Task service from the BPD layer performs some initialisation and drops through to the actual Human service (where the coach is created and displayed to the end user)
The Human service that we have created is very simple. It takes as Input the following variable (newApplication)
The coach controls are bound to the variable and upon entering as stored within the variable.
When accessed by the REST API we populate the output variable.
For this example, we have used the following technologies for the Web application that will integrate with the BPM REST API.
1. Download & install NGinX
http://nginx.org/
3. Download & extract the example
https://hub.jazz.net/project/tonypigram/bpm_sdk/
(For ease of setup, the example will contain all the files that are needed)
2. Download & install NodeJS
http://nodejs.org/
JavaScript client-side libraries used
NodeJS server-side modules installed
AngularJS controller files
AngularJS routing / navigation file
HTML fragments to display to user
Main index controller page of Web app
*It is not the aim of this presentation to teach you how to build AngularJS web apps.
Please visit the following URL to get a background on AngularJS:
https://angularjs.org/
NodeJS server-side REST API application
include routing controller
include all other AngularJS controllers
http://localhost:8091/bpm_sdk/index.html
Fragment / View to display to user
http://localhost:8091/bpm_sdk/scripts/routing.js
/settings
/myProcesses
/myStartProcess
/viewMyTasks
/viewTasks
/viewTask
/views/mySettings.html
mySettingsCtrl.js
When the index.html page is loaded, it includes <script> links to the AngularJS controllers aswell as the routing controller. The <ng-view> tag in index.html will be populated with the html files that are determined within the routing.js controller file.
Depending what route shortcut is used, the routing.js controller determines which AngularJS controller and corresponding html file to use and then render the output to the users web browser.
include routing controller
include all other AngularJS controllers
http://localhost:8091/bpm_sdk/index.html
Fragment / View to display to user
/views/mySettings.html
mySettingsCtrl.js
If the user selects the 'More' tab the 'Settings' side-menu will be displayed. If the user clicks on this, the index.html page will load the mySettings.html/mySettingsCtrl.js files and show this to the user. This will display to the user the values for the bpmHostname, bpmPort, the BPM username & password and the name of the Exposed Business Process to use for this web app. When the user submits the HTML form, the AngularJS controller code will post this to the ExpressJS REST API and this method will update the global variable values that will then be used to connect to the BPM REST API.
Currently, the bpm_sdk.js .get/.post methods here do not call the BPM REST API.
http://localhost:8091/bpm_sdk/server/bpm_sdk.js
bpmHostname = "ibmbpm"
bpmPort = "9080"
username = "tony"
password = "pigram"
app.get('/v1/settings')
app.post('/v1/settings')
ExpressJS listening on port 3000
/views/myTasks.html
myTasksCtrl.js
By default the index.html page will display the myTasks page. The myTasksCtrl controller will invoke a call to the ExpressJS REST API ('/v1/tasks') that will then perform a REST API call to BPM using the constructed query as shown above.
There is a generic function called performRequest() that actually performs the BPM REST API calls, populating the relevant headers, etc and passing the JSON response back to the calling function. This calling function ('/v1/tasks'), will then create the JSON data to pass back to the calling myTasksCtrl controller that will then be rendered in the HTML to the end user.
If a Task is selected by the user, the user is navigated to the myTask.html screen.
http://localhost:8091/bpm_sdk/server/bpm_sdk.js
bpmHostname = "ibmbpm"
bpmPort = "9080"
username = "tony"
password = "pigram"
app.get('/v1/tasks')
ExpressJS listening on port 3000
/rest/bpm/wle/v1/search/query?columns=taskStatus,bpdName,instanceDueDate,instanceName,taskDueDate,taskPriority,taskSubject&condition=taskStatus%7CReceived&condition=assignedToUser%7Ctony&organization=byInstance&run=true&shared=false&filterByCurrentUser=true
IBM BPM v8.5.x
gather a list of Tasks belonging to the calling username, matching the query criteria and return the JSON array with the specified field values.
/views/myProcesses.html
myProcessesCtrl.js
http://localhost:8091/bpm_sdk/server/bpm_sdk.js
bpmHostname = "ibmbpm"
bpmPort = "9080"
username = "tony"
password = "pigram"
app.get('/v1/processes')
ExpressJS listening on port 3000
IBM BPM v8.5.x
gather a list of Exposed Processes that are visible to the current user and return the JSON array with the specified field values.
/views/myStartProcess.html
myStartProcessCtrl.js
app.get('/v1/startProcessInstance/')
app.get('/v1/claimTask/')
/rest/bpm/wle/v1/task/'+taskID+'?action=assign&toMe=true
/rest/bpm/wle/v1/process?action=start&bpdId=25.12df730b-3c1f-4658-98c9-cb99eefbc9ad&processAppId=2066.1c793d64-d2bd-4302-a847-25a98f37c561
/rest/bpm/wle/v1/exposed/process
start a new Process instance for the given BPD. Start the first Task and return the taskId
assign the Task to the current user, thereby allowing it to be viewed in the current users MyTasks screen only
The myProcesses.html screen displays the list of Exposed Processes to the user. For this example, we have limited this to just one Process, but there is nothing to stop you having multiple displayed. When a user selects a Process to run, the myStartProcess.html screen is displayed, upon confirmation multiple REST API calls are made from the ExpressJS REST API to the BPM REST API. Once the Task is claimed the user is navigated to the myTask.html screen.
/views/myTask.html
myTaskCtrl.js
The myTask.html screen is a screen built independently from BPM, although it must contain the controls to obtain the values required to pass back to the Task via the BPM REST API.
Standard HTML (Ionic & AngularJS) controls are used to enter the data, when this is submitted the myTaskCtrl.js controller passes the JSON data to the ExpressJS REST API. This then calls the BPM REST API passing the Task data. Upon success, the Task variables are updated and the Process Token moves along to the next Task in the BPD.
The end-user is informed that the update was a success and is then displayed the myTasks.html screen. Due to the query being used, the user will not see 'Completed' Tasks.
http://localhost:8091/bpm_sdk/server/bpm_sdk.js
bpmHostname = "ibmbpm"
bpmPort = "9080"
username = "tony"
password = "pigram"
app.post('/v1/task')
ExpressJS listening on port 3000
/rest/bpm/wle/v1/task/"+jsonData.taskId+"?action=finish
IBM BPM v8.5.x
update the Task output variables with the passed data and finish the Task, moving the Token onto the next Task in the BPD Process
Perform the following steps:
cd /bpm_sdk/server/
node bpm_sdk.js
nginx
http://localhost:8091/bpm_sdk/index.html
IBM BPM is running.
As you can see there are 3 Tasks in the Process Portal list of 'My Tasks'.
If you look closer, you will see that the first two are titled 'Review application'. These are assigned to the 'Approvers' group and not directly to the user 'tony'.
Therefore, only the last Task 'Fill in application', Task Id 403 should be visible to the Web App.
NodeJS / ExpressJS is running and listening on port 3000
And there we have it!
The My Tasks controller has called ExpressJS, this in turn has called the BPM REST API, obtained the list of Tasks for the current user.
The My Tasks controller and screen have now rendered that to the end user.
BPM REST API information
Git repository of code used in this presentation
http://nodejs.org
http://expressjs.com
http://www.npmjs.com
http://angularjs.org
http://ionicframework.com
http://www.google.co.uk
- for all other information that you may need
https://hub.jazz.net/project/tonypigram/bpm_sdk/overview
http://www.ibm.com/developerworks/websphere/library/techarticles/1108_thaker/1108_thaker.html
http://www-01.ibm.com/support/knowledgecenter/SSFTDH_8.5.5/com.ibm.wbpm.ref.doc/covw_bspace_ref.html?lang=en
http://www-01.ibm.com/support/knowledgecenter/SSFTDH_8.5.5/com.ibm.wbpm.wle.editor.doc/topics/using_external_activities.html?cp=SSFTDH_8.5.5&lang=en
http://pic.dhe.ibm.com/infocenter/dmndhelp/v8r5m0/index.jsp
http://www.ibm.com/developerworks/bpm/bpmjournal/1308_gabutti/1308_gabutti.html
Other useful resources
Naturally, as we start the journey of using the BPM REST API, curiosity will come into play. Questions will arise. Such as,
"We have some services already being used in a Human Service, can we expose those nested services so we can call them from the external UI?"
The answer is. It depends.
As you recall, with a Human Service, once the Token hits a Coach or Postpone, the token stops. Any nested services before this point will be executed. But, no nested services after this will get executed when you finish the Task.
BPM allows you to expose BPDs, Human Services and Web Services.
Let's investigate calling Web Services from our external UI.
https://www.npmjs.com/package/soap
First.
Download a SOAP library. Which one?
Well, it's up to you.
I chose the following one, as it seemed very easy & familiar to use.
Navigate to /bpm_sdk and type:
npm install soap
As you can see, the usage is very similar to using ExpressJS.
It also offers a lot more security related options than other soap clients.
1. Create a System Service
Input variables: loanAmount, duration
Perform some calculation
Output variable: monthlyPayments
2. Create a Web Service
Operation: connect to the above System Service
3. Verify the Web Service WSDL in a web browser
4. We should be good to go.
(Notice we are not putting any additional security on the WSDL, you are more than welcome to)
//bpm-sdk.js ExpressJS REST API fascade SDK layer
//
var application_root = __dirname,
express = require("express"),
soap = require('soap'),
http = require("http"),
querystring = require('querystring');
var app = express();
//cannot use IP address. need to use the hostname for this to work
var bpmHostname = "ibmbpm"; //put the FQN here BUT do not put the protocol
var bpmPort = "9080"
...
...
/*
//
//Call an Exposed BPM Web Service NOT via the BPM REST API (as that is not possible)
//
*/
app.get('/v1/callBPMWebService', function (req, res) {
res.header("Access-Control-Allow-Origin", "*"); //allow from any IP
res.header("Access-Control-Allow-Methods", "POST");
var returnedMonthlyPaymentValue = '0';
if(!useStubbedData) {
var url = 'http://'+bpmHostname+':'+bpmPort+
'/teamworks/webservices/RAT1/calculateLoanRepayment.tws?WSDL';
var args = {
loanAmount: '3000',
duration: '24'
};
soap.createClient(url, function(err, client) {
client.monthly(args, function(err, result) {
//console.log(result); //{ monthlyPayments: '187.5', success: true }
var success = result.success;
if(success == true) {
returnedMonthlyPaymentValue = result.monthlyPayments;
}
res.json({ "monthlyPayments": returnedMonthlyPaymentValue });
});
});
} else {
returnedMonthlyPaymentValue = '187.50';
res.json({ "monthlyPayments": returnedMonthlyPaymentValue });
}
});
1. add the extra global variable at the top
2. Create a new ExpressJS API
For testing, let's make it an app.get()
We can hardcode the values to allow us to be able to test this from a command-line:
curl http://localhost:3000/v1/callBPMWebService
{
"monthlyPayments": "187.5"
}
which returns the following:
Re-examining the BPM Web Service, it takes the input variable values and performs the following calculation:
loanAmount*1.5 / duration
3000*1.5/24 = 187.5
Therefore, we can confirm the result is correct!
Now that we've tested that ExpressJS -> BPM Web Service works okay,
we need to build an HTML page, a matching AngularJS controller and
change the app.get() to an app.post() and modify the code to pass the
data that the user entered in the HTML form to the Web Service.
We also want to display the result back to the user on the HTML page.
*Don't forget to add reference to the new controller to the index.html file
and we'll add a link to the LoanCalculator to the side-menu bar
oops! let's just fix that cross-site access error.
Why did that happen? coder-error!
/v1/callBPMWebService
is the name of the REST API call..not
/v1/callBPMService
The Web app that we've used throughout this example presentation, works perfectly well on your desktop/laptop web browser.
But, it also works just as well on your iPad, iPhone, Android Tablet or Phone.
Minor modifications would be needed to extend it to work within the IBM MobileFirst Platform...
http://thejackalofjavascript.com/architecting-a-restful-node-js-app/
Here is great article that walks you through implementing a secure RESTful web app.
AngularJS
Ionic
HTML
JavaScript
AngularJS
Controller
ExpressJS
NodeJS
ExpressJS
REST API
BPM REST API calls
IBM BPM
BPM REST API
secure event driven calls
secure BPM user event driven calls
http://www.hacksparrow.com/express-js-https.html
Go visit:
It's simpler than you might think!
"Well, that was fun. Can I now get back to finishing off my hot-rod?"
Tony Pigram
http://www.thealbatrosshotrod.co.uk/