使用 Dojo 将业务流程扩展到移动领域

Dojo 和 WebSphere Application Server Feature Pack for Web 2.0 and Mobile 提供了丰富的功能和很大的灵活性

本文演示了一个如何构建与业务流程交互的简单移动用户界面的示例。移动 UI 的实现结合使用了 Dojo 和 IBM® WebSphere® Application Server Feature Pack for Web 2.0 and Mobile,示例业务流程是使用 IBM Business Process Manager V7.5 实现的。这里构建的移动 Web 应用程序使用了启用 webkit 的移动设备(比如 iPhone、iPad、Android 和 RIM 智能电话和平板电脑)上的原生外观进行渲染。 本文来自于 IBM WebSphere Developer Technical Journal 中文版

Etienne Noiret, WebSphere 解决方案架构师, IBM

Etienne Noiret 在 BPM 领域使用不同技术工作了 6 年多。他还担任过 6 年的 Java EE 架构师。使用 Java 和 Flex 开发了一些原生移动接口之后,他发现使用 Dojo 进行开发非常容易!



2012 年 9 月 13 日

免费下载:IBM® WebSphere® Application Server 试用版
下载更多的 IBM 软件试用版,并加入 IBM 软件下载与技术交流群组,参与在线交流。

简介

业务流程定义如何在企业中通过人员和 IT 系统来完成工作。尽管一些流程仍然是不正式的,但越来越多的组织在尝试使其业务流程自动化,从而提高用户生产力,改善总体业务运营。自动化的过程中常常涉及到任务形式的用户交互,并且随着智能电话和平板电脑的迅速增多,员工可将更多时间用在办公室以外的地方,同时保持高生产力。因此,为这些设备提供合适的用户界面就变得很有必要。

本文提供的示例展示了如何构建移动用户界面,使员工或客户能与示例流程交互,本文先大体介绍了原型的架构,然后概述各个组件和它们的实现,包括示例流程、调用的移动形式以及与流程的动态交互。此示例移动 UI 的实现将通过 IBM WebSphere Application Server Feature Pack Feature Pack for Web 2.0 and Mobile 来使用 Dojo。示例业务流程是在 IBM Business Process Manager V7.5 中实现的,移动 UI 通过其 Web 服务或 REST API 连接到流程引擎。本文提供了 示例代码,所以您可以在自己的环境中测试示例。


示例场景概述

图 1 显示了本示例中涉及到的组件:

  • IBM Process Designer 是在 IBM Business Process Manager 中用于建模业务流程建模表示法 (Business Process Modeling Notation, BPMN) 流程及其工件(比如业务规则)的开发环境。
  • IBM Process Server 是处理流程的执行的运行时服务器。它还有一个 REST 接口,所以外部应用程序可与引擎进行交互。
  • IBM Rational® Application Designer 是用于创建用户界面(HTML 页面和它的 Dojo 组件)并将它包装为 Web 应用程序的开发环境。
  • IBM WebSphere Application Server 是处理 Web 应用程序的执行的运行时组件。作为 Web 2.0 and Mobile 功能包的一部分,可部署一个 Ajax 代理来代理应用程序与远程服务之间的请求(出于安全原因,客户端浏览器默认会阻止跨站点脚本)。
图 1. 示例的架构
图 1. 示例的架构

因为 IBM Process Server 构建于 WebSphere Application Server 之上,所以可以直接在 IBM Process Server 内部署 Web 应用程序。在这种情况下,不需要使用 Ajax 代理,因为 Web 应用程序和流程服务集中在同一个实例上。

本示例中使用的业务流程演示了保险领域的一种简化的合同订阅。该业务流程使用 IBM Process Designer 实现。图 2 显示了该流程的 BPMN 渲染。

图 2. 示例流程图
图 2. 示例流程图

让我们看看 BPMN 图中列出的流程步骤的实现(参见图 2)。IBM Process Designer 支持通过以一种几乎不需要代码的方法配置代理、服务或表单来实现此流程。

步骤 1:记录案例

这是流程的起点,BPMN 被建模为一个外部事件的接收方,负责传输输入数据。为了捕获这样一个事件,Business Process Manager 使用一个所谓的 秘密代理 (UCA),如图 3 所示。

图 3. 用于启动流程的秘密代理
图 3. 用于启动流程的秘密代理

秘密代理附加到一个服务上,以响应收到的消息(举例而言,服务可将收到的数据转换为流程想要的正确格式)。为了将流程公开为一个 Web 服务(这将是您从移动设备启动它的集成点),需要两个附加步骤:

  1. 创建一个启动 UCA 的简单服务。
  2. 创建一个以操作的形式调用后者的 Web 服务。

图 4 给出了最终的 Web 服务。

图 4. 启动流程的示例 Web 服务
图 4. 启动流程的示例 Web 服务

可以选定图中显示的 WSDL URL,以检查想要的输入参数。

步骤 2:检查案例

这一步使用 Business Process Manager 内置的规则引擎建模为一条规则。在本例中,此规则的用途是确定订阅能否按原样接受,或者它是否需要额外的医疗经验(取决于合同金额和类型)。图 5 显示了为了配置此规则而使用的来自流程上下文的输入参数。

图 5. 业务规则
图 5. 业务规则

步骤 3:医疗经验

如果前面的规则导致需要医疗经验,则需要向某个角色分配一项处理 医疗专家 配置文件(对应于图 2 中标为 “Medical expert” 的 BPMN 管道)的任务。Business Process Manager 提供了多种方法来构建处理任务收件箱和任务细节页面的用户界面。使用 IBM Process Designer 的内置工具,最简单的方式是构建一系列称为 coach 的 UI 表单,并建模每个表单之间的页面流,如图 6 和图 7 所示。

图 6. 原生 coach 之间的页面流
图 6. 原生 coach 之间的页面流
图 7. 创建 coach 的内置编辑器
图 7. 创建 coach 的内置编辑器

然后这些用户界面会以 Web 应用程序的形式自动部署在 IBM Process Server 内,并将来自 IBM Process Portal 的默认任务列表用作一个入口点。

如果您希望使用现有的基础架构来构建和集成用户界面,那么 Business Process Manager REST API 是管理用户界面与流程本身之间的交互的理想之选。通常需要执行 3 个主要的操作:

  1. 获取当前用户的任务列表。
  2. 获取当前用户选定的特定任务的详细信息。
  3. 在用户完成一项任务的工作后更新任务内容和状态。

为了帮助您利用 REST API,Business Process Manager 提供了一个 Web 应用程序测试器,使您能够轻松地确定需要哪些参数(参见图 8)。

图 8. 使用 REST API 测试器
图 8. 使用 REST API 测试器

这里提供的示例将使用 REST API 来动态构建任务列表和任务细节页面。

接下来,让我们看看如何从一个移动设备调用业务流程。


构建一个 Dojo 表单来调用业务流程

一种创建可移植移动用户界面的简单方法是使用开放标准(比如 HTML5、CSS3)和一个关联的 JavaScript™ 框架(比如 Dojo)。Dojo 提供了针对移动设备优化的、具有原生外观的丰富的部件,使您能够创建强大的移动用户界面。IBM 通过 WebSphere Application Server Feature Pack for Web 2.0 and Mobile 提供了对 Dojo 的支持(WebSphere Application Server 用户可免费使用)。一些集成开发环境现在包含一个支持 Dojo 的 WYSIWYG 编辑器,包括 Maqetta 和 IBM Rational Application Developer。

图 9. 使用 Rational Application Developer 创建一个 Dojo 移动用户界面
图 9. 使用 Rational Application Developer 创建一个 Dojo 移动用户界面

从用户的角度讲,样例应用程序包含 4 个简单页面:

  • Main 页面:一个占满页面的列表,包含 Create subscription 页面的链接和 My tasks 页面的链接。
  • Create subscription 页面:一个表单,用于输入订阅详细信息并通过公开的 Web 服务启动流程。
  • My tasks 页面:显示当前用户正在运行的任务。
  • Task details 页面:My tasks 列表中的每一行都指向这里,显示订阅详细信息并使当前的用户能够接受或拒绝该案例。

最后两页将使用 Business Process Manager REST API,稍后就会看到。

在传统的 Web 应用程序中,这些页面通常通过 4 个不同的动态 Web 页面(比如 JSP 页面)构建,每一次在服务器与浏览器之间同时传输演示层和数据。在富 Internet 应用程序中,编程模型有所不同:演示层仅加载一次,用户在各个状态之间导航,同时使用 Ajax 异步调用动态加载数据。在本示例中,只有一个 HTML 文件使用 Dojo 部件来定义视图和它们的交互。

清单 1 展示了如何创建一个简单视图,使您能够使用流畅的滑块过渡在应用程序中进行导航。在 Android 设备上,前面的代码的渲染结果如图 10 所示。

清单 1. 主要视图的 HTML 代码
 <div data-dojo-type="dojox.mobile.View"
     id="MainView"
     data-dojo-props="selected:true"> 
   <h1 data-dojo-type="dojox.mobile.Heading"
       data-dojo-props="label:'Contracts subscription'"> 
   </h1> 
   <div data-dojo-type="dojox.mobile.RoundRectList"> 
      <div data-dojo-type="dojox.mobile.ListItem"
           data-dojo-props="label:'Create subscription',moveTo:'CreateView', 
		 transition:'slide'"> 
      </div> 
      <div data-dojo-type="dojox.mobile.ListItem"
           data-dojo-props="label:'My tasks',moveTo:'TaskListView',transition:'slide'"
           onClick="getTaskList()"> 
      </div> 
   </div> 
 </div>
图 10. Android 设备所显示的主要页面
图 10. Android 设备所显示的主要页面

为了调用业务流程,需要使用相同技术创建一个表单视图:标准 HTML5 标记和 data-dojo-xxx 属性,如清单 2 所示。在运行时,Dojo 分析器识别这些属性并生成额外的 DOM、CSS 和 JavaScript 元素,具体取决于目标浏览器。

清单 2. 用于提交合同数据的表单
 <!-- Create contract view --> 
 <div data-dojo-type="dojox.mobile.ScrollableView"
     id="CreateView"
    data-dojo-props="selected:false"> 
   <h1 data-dojo-type="dojox.mobile.Heading"
       data-dojo-props="label:'Subscribe contract',back:'Home',moveTo:'MainView', 
	 fixed:'top'"> 
   </h1> 
   <h2 data-dojo-type="dojox.mobile.RoundRectCategory"
       data-dojo-props="label:'Applicant'"> 
   </h2> 
   <ul data-dojo-type="dojox.mobile.RoundRectList"> 
      <li data-dojo-type="dojox.mobile.ListItem"> 
         <label class="itemText" for="ctnameField">Last name:</label> 
         <input class="itemInput" id="ctnameField" type="text" value="Doe"/> 
      </li> 
      <li data-dojo-type="dojox.mobile.ListItem"> 
         <label class="itemText" for="ctfirstnameField">First name:</label> 
         <input class="itemInput" id="ctfirstnameField" type="text" value="John"/> 
      </li> 
      <li data-dojo-type="dojox.mobile.ListItem"> 
         <label class="itemText" for="ctaddressField">Address:</label> 
         <input class="itemInput" id="ctaddressField" type="text"
       value="avenue des champs Elysees, 75000 Paris"/> 
      </li> 
   </ul> 
   <h2 data-dojo-type="dojox.mobile.RoundRectCategory" 
		 data-dojo-props="label:'Contract'"> 
   </h2> 
   <ul data-dojo-type="dojox.mobile.RoundRectList"> 
      <li data-dojo-type="dojox.mobile.ListItem"> 
         <label class="itemText" for="cttypeField">Contract type:</label> 
         <select id="cttypeField"> 
               <option value="Life insurance" selected>Life insurance</option> 
               <option value="Retirement savings" >Retirement savings</option> 
         </select> 
      </li> 
      <li data-dojo-type="dojox.mobile.ListItem"> 
         <label class="itemText" for="ctamountField">Amount:</label> 
         <input class="itemInput" id="ctamountField" type="number" /> 
      </li> 
   </ul> 
   <h2 data-dojo-type="dojox.mobile.RoundRectCategory"> 
      <div align="center"> 
     <button data-dojo-type="dojox.mobile.Button"
             class="mblButton greyBtn baseBtn normalBtn"
             onclick="subscribe()">Subscribe</button> 
     </div> 
   </h2> 
   <div id="responseStatus" class="itemText"></div> 
 </div>
图 11. 在 Android 设备上渲染的表单
图 11. 在 Android 设备上渲染的表单

在清单 2 的末尾,请注意在按钮的 onclick 事件上对 subscribe() 方法的调用。此方法需要写入到一个 JavaScript 代码块中,以管理对 Web 服务的调用。除了提供一组丰富的部件,Dojo 还包含一个用来处理异步调用的完整的库。一个执行 Web 服务调用的简便方法是:手动创建 SOAP 信封,动态附加表单中包含的数据,使用 dojo.xhrPost() 执行异步调用并管理响应,如清单 3 所示。

清单 3. 一个执行 Web 服务调用的 Dojo Javascript 方法
 <script type="text/javascript"> 
 function subscribe() { 
    var soapMsg = '<soapenv:Envelope 
		 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"'
    + ' xmlns:sub="http://SCA/SubscriptionWS.tws" 
		 xmlns:sch="http://IBMDemos:9080/schema/">'
    + '<soapenv:Header/>'
    + '<soapenv:Body>'
    + '<sub:submitSubscription>'
    + '<sub:subscription>'
    + '    <sch:applicant>'
    + '       <sch:lastName>' + dojo.byId("ctnameField").value + '</sch:lastName>'
    + '    <sch:firstName>' + dojo.byId("ctfirstnameField").value + '</sch:firstName>'
    + '       <sch:birthDate>2011-12-05T00:00:00</sch:birthDate>'
    + '       <sch:address>' + dojo.byId("ctaddressField").value + '</sch:address>'
    + '    </sch:applicant>'
    + '    <sch:contract>'
    + '       <sch:subscriptionDate>2011-12-05T00:00:00</sch:subscriptionDate>'
    + '       <sch:contractType>' + dojo.byId("cttypeField").value + 
			'</sch:contractType>'
    + '       <sch:amount>' + dojo.byId("ctamountField").value + '</sch:amount>'
    + '    </sch:contract>'
    + '</sub:subscription>'
    + '</sub:submitSubscription>'
    + '</soapenv:Body>'
    + '</soapenv:Envelope>'; 

    var xhrArgs = { 
        url: getServerBase() + "/teamworks/webservices/SCA/SubscriptionWS.tws", 
        postData: soapMsg, 
        handleAs: "text", 
        headers: { 
            "Content-Type": "text/xml;charset=UTF-8", 
            "SOAPAction": http://SCA/SubscriptionWS.tws/submitSubscription 
        }, 
        load: function(data) { 
            dojo.byId("responseStatus").innerHTML = "Message posted."; 
        }, 
        error: function(error, ioargs) { 
            dojo.byId("responseStatus").innerHTML = "Bad reply,status:" + 
			 ioargs.xhr.status + ": reason:" + ioargs.xhr.statusText; 
        } 
    } 
    dojo.byId("responseStatus").innerHTML = "Message being sent..."
    var deferred = dojo.xhrPost(xhrArgs); 
 } 
 </script>

在上面的示例中,如果 Web 服务返回一个正确的响应,则会在表单末尾使用 <div id="responseStatus".../> 标记动态显示一条状态消息。


使用 Dojo 构建动态任务列表

在这一阶段,依据当前用户未完成的任务数量来动态构建用户界面。清单 4 给出了一段简单的 HTML 代码,我们将动态修改它来插入任务项。请注意,在清单 1 中,在从主要视图过渡到任务列表视图时,会调用 getTaskList() 方法,以便在一开始就自动填充该列表。

清单 4. 任务列表的 HTML 代码
 <div data-dojo-type="dojox.mobile.View" id="TaskListView"
    data-dojo-props="selected:false"> 
    <h1 data-dojo-type="dojox.mobile.Heading"
        data-dojo-props="label:'My tasks',back:'Back',moveTo:'MainView'"> 
        <div data-dojo-type="dojox.mobile.ToolBarButton"
            style="float: right;" onClick="getTaskList();">Refresh</div> 
    </h1> 
    <div data-dojo-type="dojox.mobile.RoundRectList" id="taskItems"> 
    </div> 
    <div id="taskListStatus" class="itemText"></div> 
 </div>

Business Process Manager REST API 用于填充 taskItems div 标记。然后会分析结果(以 JSON 结构的形式返回),并使用这些结果动态添加任务项,将这些任务项作为新节点,如清单 5 中所示。

清单 5. 填充任务列表的 JavaScript 函数
 <script type="text/javascript"> 
 function getTaskList() { 
    var xhrArgs = { 
        url: getServerBase() + "/rest/bpm/wle/v1/tasks/query/IBM.DEFAULTALLTASKSLIST_75? 
        interactionFilter=ASSESS_AND_WORK_ON", 
        preventCache : true, 
        handleAs: "json", 
        user : "admin", /* should be handled differently */ 
        password : "admin", 
        load: function(jsonData) { 
            var items = dijit.byId("taskItems"); 
            items.destroyDescendants(); 
            if(jsonData.data.size==0) { 
                dojo.byId("taskListStatus").innerHTML = "No task waiting"; 
            } else { 
                dojo.byId("taskListStatus").innerHTML = ""; 
                for(var i=0; i<jsonData.data.size; i++) { 
                    var taskItem = jsonData.data.items[i]; 
                    var item = new dojox.mobile.ListItem({ 
                        moveTo: "TaskDetailsView", 
                        transition: "slide", 
                        label: taskItem.NAME, 
                        rightText: taskItem.TKIID, 
                    }); 
                    items.addChild(item); 
                    item.on("click", function() {getTaskDetails(taskItem.TKIID);}); 
                } 
            } 
        }, 
        error: function(error, ioargs) { 
            dojo.byId("taskListStatus").innerHTML = "Bad reply,status:" + 
 ioargs.xhr.status + ": reason:" + ioargs.xhr.statusText; 
        } 
    } 
    dojo.byId("taskListStatus").innerHTML = "Loading tasks..."; 
    var deferred = dojo.xhrGet(xhrArgs); 
 } 
 </script>

在 getTaskList() 函数的末尾可以看到,在每个新项上,通过 dojo/on API 添加了一个事件处理函数,可使用该函数捕获每一行上更进一步的 onClick 事件,以便显示正确的任务细节页面。任务细节页面是使用相同方式构建的,清单 6 展示了如何结合使用 REST API 和作为参数给出的任务 ID。

清单 6. 加载任务细节页面的 JavaScript 函数摘录
 var xhrArgs = { 
	 url: getServerBase() + "/rest/bpm/wle/v1/task/"+taskId+"?parts=all", 
	 preventCache : true, 
	 handleAs: "json", 
 ...

汇总

您已看到该流程和 Dojo 移动用户界面是如何构建的了,现在让我们来看看如何将它们汇总在一起。

首先,您需要启动一个新流程实例。从主要视图导航到 Create subscription 视图,然后填充表单并单击 Subscribe 按钮。这样,应该会在表单末尾更新状态消息,如图 12 所示。

图 12. 从移动设备启动流程
图 12. 从移动设备启动流程

现在,让我们验证一下该流程是否真的已启动以及它正在等待哪个步骤。此操作可通过 IBM Process Portal 或 IBM Process Designer 中的 Inspector 来完成,如图 13 所示。

图 13. 等待任务完成的流程实例
图 13. 等待任务完成的流程实例

该流程图表明,流程正在等待步骤 “Medical expertise”(以黄色列出),任务列表显示了一个正在等待的 ID 为 705 的新任务,流程变量包含已成功传递到流程实例的您的输入数据。返回到移动设备,您可以返回到主要视图并导航到 My tasks 视图;图 14 显示了添加到列表中的具有正确任务 ID 的任务。

图 14. 任务列表
图 14. 任务列表

如果单击该任务项,则会显示 Task detail 页面,您可通过单击适当的按钮来决定是接受还是拒绝案例(参见图 15)。

图 15. Task details 页面
图 15. Task details 页面

做出接受或拒绝选择之后,就可以返回到流程的监视视图,您可以看到流程实例已完成(参见图 16)。您觉得简单吗?

图 16. 完成的流程
图 16. 完成的流程

结束语

本文演示了一个简单案例,展示了移动用户如何轻松连接到业务流程并与其交互。使用这个基本的应用程序作为起点,借助 Dojo 或 Worklight Mobile Platform,您可以利用多个令人激动的功能来增强用户体验:

  • 离线工作(例如,离线启动流程或离线填充任务)。
  • 使用 Worklight 提供的统一的通知 API,在分配新任务时向用户发送通知。
  • 向流程模型添加关键极小指标,使用 Dojo 图表功能在移动设备上渲染它们。
  • 使用 Worklight 验证框架管理用户 ID 和密码,提供简化的验证。

您可以下载本文中提供的 示例项目,其中包括一个自述文件,该文件会帮助您将资源导入您自己的测试环境中。


下载

描述名字大小
样例应用程序1203_noiret_sources.zip8.3 MB

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere, Web development
ArticleID=835047
ArticleTitle=使用 Dojo 将业务流程扩展到移动领域
publish-date=09132012