IBM BPM 提供了一组基于 REST 协议的 API,使用它们作为查询和访问流程实例、任务和业务应用程序数据的工具。这些 REST API 能够访问外部客户端和内部流程中与业务流程定义 (BPD)、业务流程执行语言 (BPEL) 模块和连锁的资源相关的数据。提供的 REST API 列表可以通过 IBM BPM 中的 REST API Tester 门户进行查看。
创建长时间运行的有状态工作流,利用 来自 Bluemix 的 Workflow 服务 中的同步或异步的事件驱动交互来协调任务和服务。免费试用该服务!
您可能会发现,在某些情况下,能够从以编程方式启动 REST API、BPD 或服务组件架构 (SCA) 应用程序(比如 BPEL 流或中介)中获益。例如,一个异常治理流程可能需要访问停止的流程实例的业务和流程数据,以便它可重新启动或恢复一个流程实例。REST API 可直接从 IBM BPM 数据库检索流程变量、输入/输出参数、业务对象、事务状态,以及其他细节。这些 API 是轻量型的,可以编程方式从各种设备启动,比如桌面、平板电脑和移动设备。
本教程展示一种使用 Java™,利用 IBM BPM REST API 从一个 BPD 以编程方式访问流程实例数据的方法。该实例实现展示了流程管理员如何从一个 coach 管理停止的流程,该 coach 使用了一个基于 REST API 的流程应用程序。本教程中包含的示例是在 IBM BPM V8.5.5 上实现的,但无需更改它就可以将它用于所有 IBM BPM V8.x 版本。
要从本教程中获得最大的收获,您应熟悉 IBM BPM 的基本功能和特性。此外,REST、JavaScript、JSON、Java 和编程的知识通常也会对您有所帮助。
回页首
在一个主要使用无头 IBM BPM 流程模式的环境中,获得由于异常而停止(失败或暂停)的流程的可视性很重要,这样您才能恢复或停止流程。举例而言,在 IBM BPM 工作流的无头模式中,一个完成的流程包含一系列步骤作为无人干预的自动化工作流,而人机接口仅用于异常处理或流程治理。要高效地管理此类型的异常治理流程,一种有帮助的方法是:应用程序的用户和管理员使用门户来查询停止的流程,并批量管理它们。
例如,想象您需要一个简单的异常治理流程来查询无头 IBM BPM 流程的已停止流程实例的状态,以便可以重新启动或恢复它们。它们通常是 SCA 流程,比如长期运行的 BPEL 流程。
图 1 显示了一个如何实现对已停止流程的状态的查询的示例。
图 1. 实现实例:使用 REST API 查询流程实例状态
此示例实现包含一个名为 Process Query 的 BPD,该 BPD 包含一个简单的 coach(用户界面),应用程序的用户可以根据流程类型(IBM BPM 或 SCA)和停止状态(失败或暂停)在该界面中查询处于异常状态的流程。出于设计简单性的考虑,我们假设用户希望重新启动或结束停止的流程实例。
对失败或暂停的流程实例的搜索,可以使用一个 IBM BPM 集成服务组件来处理,该组件使用一个名为 RESTQuery.jar
的自定义 Java 归档文件来运行 IBM BPM REST API 查询。RESTQuery Java 类(包含在 RESTQuery.jar
中)以 JSON(JavaScript 对象表示法)对象的形式向集成服务返回检索的流程实例数据列表。为了解析返回的 JSON 对象,该示例使用 json2.js
实用程序库来提取停止的流程实例的 ID,然会在 coach 中将它们显示给用户。之前已经提到过,IBM BPM REST API 支持 HTTP Accept 标头中设置的 JSON、JSONP 和 XML 返回格式。(JSONP 返回格式仅支持 IBM BPM Standard,默认情况下未启用。有关的详细信息,请参阅 IBM 知识中心中的 IBM BPM 8.5.5 文档中的 IBM BPM REST API 支持的内容类型 )。
根据返回的列表,用户可以选择重新启动或终止一个或多个流程实例。选择的流程 ID 传递到另一个集成服务组件,该组件通过 RESTQuery Java 类启动 REST API 来重新启动或终止所选的流程实例。
此实例实现的范围是一个受 REST API 支持的简单的用户界面,但还可以使用此设计方法来构建更加自动化的治理流程。
现在详细查看每个组件。
回页首
图 2 显示了 ProcessQuery_BPD ,其中包含一个名为 Process Query HS 的人工服务 。
图 2. Process Query BPD 示例
如图 3 所示,这个人工服务包含一个名为 Query Process HT 的 coach,应用程序的用户可以在其中查询停止的流程实例。图 4 显示了 coach 布局。
图 3. Process Query HS 实现示例
图 4. Query Process HT coach 布局示例
Process Query HS包含 3 个组成该实现的服务( Retrieve Instance GS 、 Parse Result GS 和 Act on Instance GS 服务)。用户在流程或实例上输入搜索条件并单击 Get Process IDs 时, Retrieve Process GS 服务会使用 Java 集成组件启动 RESTQuery
java 类的 getStoppedInstances()
方法。这个 类构建 REST 服务 URL,并对 IBM BPM 服务器运行该查询。请求的响应类型在 HTTP Accept 标头中被设置为 JSON。请求的响应类型也可以作为 URL 查询字符串的一部分进行发送。
图 5 展示了启动 RESTQuery
Java 类的 getStoppedInstances()
方法的 Java 集成步骤,清单 1 给出了 getStoppedInstances()
方法的一部分代码。它根据 coach 中的用户指定的参数来构造并启动该 REST API URL。该方法接受 3 种字符串类型的参数:IBM BPM server(主机和端口)、type of the query 和 process state。IBM BPM 服务器值存储在一个环境变量中。
图 5. Get Process Id 集成服务示例
清单 1. 构建和调用 REST URL 的 Java 代码
点击查看代码清单
关闭 [x]
/* Map state values */ if (state.equalsIgnoreCase("FAILED")) iState = "5"; else if (state.equalsIgnoreCase("SUSPENDED")) iState = "2"; /* Set the URI based on the resource type */ if (processType.equalsIgnoreCase("BPD")) { restURI = "rest/bpm/wle/v1/"; } else if (processType.equalsIgnoreCase("SCA")) { restURI = "rest/bpm/bfm/v1/processes/"; /* Set default query parameters: for BPD (process), default is all * detail; for SCA (service) default is blank (GET) */ parameters = parameters.concat("filter?whereClause=PROCESS_INSTANCE.STATE=").concat(iState); } urlStr = buildURL(bpmServer, restURI, parameters); logger.info("REST URL: " + urlStr); try { /* open connection, set method and headers */ conn = createConnection(urlStr, method); logger.info("Connection created..."); /* Invoke REST service over HTTP and get response */ StringBuffer response = readResponse(conn); result = response.toString(); logger.info("Result: " + result); } catch (MalformedURLException me) { String msg = "IOException thrown... " + me.getLocalizedMessage() + "...for: (" + urlStr + "," + method + ")"; logger.severe(msg); throw new Exception(msg); } catch (IOException io) { String msg = "IOException thrown... " + io.getLocalizedMessage() + "...for: (" + urlStr + "," + method + ")"; logger.severe(msg); throw new Exception(msg); } catch (Exception e) { String msg = "Exception thrown... " + e.getLocalizedMessage() + "...for: (" + urlStr + "," + method + ")"; logger.severe(msg); throw new Exception(msg); } return (Object) result;
代码清单 1 中的 Java 代码根据流程类型来构建 REST URL,如表 1 所示。
表 1. getStoppedInstances() 方法构建的 REST URL
流程类型 | Java 构建的 URL | 方法 |
---|---|---|
IBM BPM 流程类型 - 失败的实例 | http://bpm_server:port/rest/bpm/wle/v1/search/query?condition=instanceStatus %7CFailed&organization=byInstance&run=true &shared=false&filterByCurrentUser=false | PUT |
IBM BPM 流程类型 - 暂停的实例 | http://bpm_server:port/rest/bpm/wle/v1/search/query?condition=instanceStatus%7CSuspended&organization=byInstance&run= true&shared=false&filterByCurrentUser=false | PUT |
SCA 流程类型 - 失败/暂停的实例 | http://bpm_server:port/rest/bpm/bfm/v1/processes/filter?whereClause=PROCESS_INSTANCE.STATE= state_integer_code (其中 state_integer_code 可以是 5 或 11) | GET |
RESTQuery.java
打包为一个 Java 归档文件,并作为文件资源导入到流程应用程序中(通过单击 Library 导航窗格的 File 菜单选项旁边的 + 符号),以便可以将它用在 Java 集成组件中。可以从本教程的 “下载” 部分下载code_sample.zip和包含完整代码的示例 .jar
文件的摘录。
因为 REST 客户端需要向 IBM BPM 服务器执行身份验证,所以 RESTQuery
类实现了 Authenticator 接口来提供用于基本身份验证的用户 ID 和密码。这种粗略的身份验证机制很简单。在实际生活中,您可能希望考虑其他更安全的单点登录技术。
RESTQuery
java 类的 getStoppedInstances()
方法以 Java 字符串对象形式将 JSON 结果对象返回给调用的 BPM。然后,此对象被传递到 Parse Result GS 服务(如图 6 所示),该服务使用一个服务器端 Javascript 步骤将字符串结果转换为纯 JSON 对象,解析结果元素来提取停止的流程实例 ID 和任何其他所需的元素。
图 6. 解析 Result GS 一般服务实现
清单 2 给出了 Parse Result GS 步骤中包含的 Javascript。
清单 2. 解析 JSON 结果对象的 Javascript
if (tw.local.response != null && tw.local.response != '') { log.info("Result: " + tw.local.response); var jsonObject = JSON.parse(tw.local.response); log.info("JSON Object: " + jsonObject); // Build process id list tw.local.processIds = new tw.object.listOf.String(); if(tw.local.processType == "BPM") { for ( var pid=0; pid<jsonObject.data.data.length; pid++) { tw.local.processIds[pid] = jsonObject.data.data[pid].instanceId.toString(); tw.local.state = jsonObject.data.data[pid].instanceStatus; } } else { for ( var pid=0; pid<jsonObject.items.length; pid++) { tw.local.processIds[pid] = jsonObject.items[pid].topLevelProcessInstanceName; tw.local.state = jsonObject.items[pid].executionState; } } } else log.error("NULL Response returned!");
IBM BPM 8.5.x 需要一个实用程序库来处理服务器端 Javascript 中的 JSON 对象。此示例演示了如何使用 json2.js
(参见 “参考资料” 部分),必须将它作为文件资源导入到 BPD 中。图 7 显示了实现此解决方案所需的文件资源。
图 7. 文件资源
检索的流程实例 ID 会返回到 coach,后者将它们显示为一个多选列表。然后用户可以选择一个或多个流程实例 ID,并决定是单击 Restart 还是 Terminate (参见图 8)。为了简便起见,示例只列出了停止的流程的实例 ID。在实际生活中,您可能希望列出实例 ID 的其他细节,比如流程名称、启动日期和失败日期,帮助用户确定如何处理该流程。
图 8. Query Process coach
用户单击 Restart 或 Terminate 时,coach 将控制权转交给 Act on Instance IS 服务(参见图 9),后者循环每个实例 ID 并启动 RESTQuery.java
类的 processAction()
方法
图 9. Act on Instance 集成服务
此类接受 4 个字符串类型的参数: IBM BPM server
、 instance ID
、 action to perform
和 process type
。它基于操作和流程类型来构建合适的 REST URL,并启动该 API。
清单 3 显示了此方法的一部分(可以查阅 “下载” 部分中的 code_sample.zip
获取完整的代码示例)。
清单 3. processAction() 方法的部分代码清单
点击查看代码清单
关闭 [x]
/* Set the URI based on the resource type */ if (processType.equalsIgnoreCase("BPM")) { restURI = "rest/bpm/wle/v1/process/"; parameters = parameters.concat(instanceId).concat("?action=").concat(action).concat("&parts=all"); } else if (processType.equalsIgnoreCase("SCA")) { restURI = "rest/bpm/bfm/v1/process/"; if (action.equalsIgnoreCase("restart") || action.equalsIgnoreCase("resume")) parameters = parameters.concat(instanceId).concat("?action=").concat(action); else if (action.equalsIgnoreCase("terminate")) { parameters = parameters.concat(instanceId).concat("?action=forceTerminateamp;invokeCompensation=false"); } else if (action.equalsIgnoreCase("delete")) { parameters = parameters.concat(instanceId); method = "DELETE"; // can only delete a failed/suspended process } } urlStr = buildURL(bpmServer, restURI, parameters); logger.info(urlStr); try { /* open connection, set method and headers */ conn = createConnection(urlStr, method); /* Invoke REST service over HTTP and get response */ String response = readResponse(conn).toString(); object = ((response==null || response.trim().equals(""))? (conn.getResponseCode() + " " + conn.getResponseMessage()):response).toString(); logger.info( "Response object: " + (String)object); } }
表 2 显示了该方法构建和调用的 URL(基于流程类型和采取的操作)。
表 2. 重新启动/终止 REST API URL
流程类型 | Java 构建的 URL | 方法 |
---|---|---|
IBM BPM 流程类型 -重新启动流程 | http:/bpm_server:port/rest/bpm/wle/v1/process/process_instance_ID?action=retry&parts=all | PUT |
IBM BPM 流程类型 -终止流程 | http://bpm_server:port/rest/bpm/wle/v1/process/process_instance_ID?action=terminate&parts=all | PUT |
SCA 流程类型- 重新启动流程 | http://bpm_server:port/rest/bpm/bfm/v1/process/process_instance_ID?action=restart | PUT |
SCA 流程类型- 恢复流程 | http://bpm_server:port/rest/bpm/bfm/v1/process/process_instance_ID?action=resume | PUT |
SCA 流程类型- 删除流程 | http://bpm_server:port/rest/bpm/bfm/v1/process/process_instance_ID | DELETE |
SCA 流程类型- 终止流程 | http://bpm_server:port/rest/bpm/bfm/v1/process/process_instance_ID?action=forceTerminate&invokeCompensation=false | PUT |
然后在 coach 底部的 Results 部分向用户显示调用的状态,如图 8 所示。
回页首
要测试该应用程序,可以执行用户将执行的步骤。首先在您的环境中识别一些失败或停止的实例。查找 IBM BPM 和 BPEL 流程实例:对 BPD 实例使用 Process Designer 中的 Inspector,对 BPEL 实例使用 Business Process Choreographer Explorer。记下每个实例的实例 ID。从 Process Designer 或 Process Portal 运行 ProcessQuery_BPD ,并在 Coach 屏幕中提供以下参数(参见图 8):
Process Type:从列表中选择 BPM 。
Process State:从列表中选择 Failed 。
RESTQuery
java 类构造并启动 REST 服务,然后返回结果,该结果将显示在 Process ID List 字段中。将显示的实例 ID 的列表与您之前手动创建的列表对比。
从显示的列表中选择一个或多个流程 ID,然后单击 Restart 。如果 IBM BPM 服务器能够重新启动流程,则会在 coach 底部的 Results 部分显示一个简短结果(例如 STATE_RUNNING
)。
对 SCA 流程类型和 Suspended 状态重复这些步骤。WebSphere Application Server 中的 SystemOut.log
会显示写入该代码中的消息。类似地,选择一个或多个检索的流程 ID,单击 Terminate 终止并删除这些流程。
要对比和验证这些结果,可以从 IBM BPM REST API Tester ( http://Your_IBM_BPM_Server:Your_http_port/bpmrest-ui
) 运行 RESTQuery
Java 类构建的相同查询(可以从 SystemOut.log
输出中复制该类编写的 URL)。
回页首
本教程介绍了从 IBM BPM 流程流以编程方式访问 IBM BPM REST API 的方法。文中介绍了一个简单用例和示例实现,演示了如何使用 IBM BPM REST API 快速、轻松地构建一个自定义异常管理流程,该流程需要在运行时访问 IBM BPM 流程实例数据。
因为 REST API 为 IBM BPM 数据库提供了一个透明层,所以对流程、服务和任务数据的访问比直接访问表和视图更简单一些,而且更容易维护。REST API 简化了对分散在两个数据库上的 BPD 和 SCA 层上的流程和实例数据的访问。可以扩展此方法来构建一种更加自动化和更具操作性的异常流程管理工作流,以便管理大量流程实例。
感谢 Bobby Pham 对本教程的技术审校。
回页首
描述 | 名字 | 大小 |
---|---|---|
代码示例 | code_sample.zip | 1458KB |