ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 用 WID、WPS和 Adobe Flex 为业务流程应用程序开发富 Web 客户机

用 WID、WPS和 Adobe Flex 为业务流程应用程序开发富 Web 客户机

原创 Linux操作系统 作者:CloudSpace 时间:2010-09-21 13:49:20 0 删除 编辑
Jun Xue, 软件工程师, IBM

简介: 创建可以使用 WebSphere Process Server 的 Business Flow Manager 和 Human Task Manager Web 服务 API 与业务流程和人工任务交互的富 Adobe® Flex™ Web 客户机。

简介

可以使用 WebSphere Process Server V6 设计和管理所有类型的业务流程,尤其是可能包含人工交互的以人为中心的业务流程。通常,J2EE 客户机使用 Business Flow Manager 和 Human Task Manager J2EE API 与业务流程和人工任务交互。在本文中,介绍如何在 Flex 应用程序中使用 Process Server 提供的 Web 服务 API 与业务流程和人工任务交互。

Process Server 提供两个 Web 服务接口:

  • Business Flow Manager API (BFM API),它让客户机应用程序可以与微型流和长时间运行的过程交互。
  • Human Task Manager API (HTM API),它让客户机应用程序可以创建任务、声明和完成现有的任务等等。

本文包含一个示例企业应用程序过程(其中有一个人工任务活动)和一个与此过程交互的 Flex 客户机。讨论如何使用 Flex 通过发出 Web 服务请求启动过程、声明和完成人工任务。还讨论如何开发使用 BFM 和 HTM Web 服务 API 访问在 Business Process Choreographer 环境中运行的业务流程和人工任务的其他 Web 服务客户机应用程序。

本文的目的是讲解如何使用 Flex 创建富 Web 客户机,让客户机通过 BFM 和 HTM Web 服务 API 连接业务流程。本文将带领您完成以下任务:

  • 创建业务流程应用程序
  • 研究 BFM 和 HTM Web 服务 API
  • 使用 Flex 创建富 Web 客户机

图 1 说明示例应用程序的架构。


图 1. 示例应用程序的架构
示例应用程序的架构

本文假设您有使用 WebSphere Process Server(后面简称为 Process Server)和用 WebSphere Integration Developer(后面简称为 Integration Developer)开发业务流程应用程序的经验。还假设您熟悉 Adobe Flex。关于 WebSphere Business Process Management 和相关技术的更多信息见 参考资料

在开始学习本文之前,一定要安装和运行以下软件:

  • WebSphere Integration Developer V6.2:这是一个集成开发环境 (IDE),用于构建基于面向服务架构 (SOA) 的应用程序。
  • WebSphere Process Server V6.2:这是一个高性能的业务流程自动运行时引擎。
  • Adobe Flex Builder 3:这是一个基于 Eclipse 的强大的 IDE,用于开发 Flex 应用程序。

本文的 下载 部分提供以下示例文件:

  • OrderSampleLibrary.zip 包含预定义的业务对象和接口。
  • OrderSampleProcessModule.zip 包含示例业务流程应用程序项目的源代码文件和可以在 Process Server 中安装的 Enterprise Application Archive (EAR) 文件 OrderSampleProcess.ear。
  • BizFlexClient.zip 包含 Adobe Flex 项目的源代码文件。

下载这些文件,把 OrderSampleProcessModule.zip 和 BizFlexClient.zip 解压到本地目录中。

本文中的示例演示如何构建一个订购请求过程应用程序,其中包含一个人工任务活动,经理通过这个人工任务批准请求。图 2 给出示例的业务流程。


图 2. 示例订购过程
示例订购过程

在下面几节中,要导入示例库、创建组件和分配接口以及创建所需的 Java™ 实现。

导入示例库

为了构建这个示例,需要导入 下载 中提供的 OrderSampleLibrary 中的接口和业务对象定义。按以下步骤导入库并在 Integration Developer 中创建 Order Process 应用程序模块:

  1. 选择 File => Import => thers => Project Interchange
  2. 找到并选择 OrderSampleLibrary.zip,单击 Finish,见图 3。

    图 3. 导入 OrderSampleLibrary
    导入 OrderSampleLibrary

  3. 创建模块,选择 File => New => Module
  4. 指定 OrderSampleProcess 作为 Module name,单击 Next
  5. Select Required Libraries 对话框中,确保选择 OrderSampleLibrary 并单击 Finish
  6. 应该会在 Business Integration 视图中看到 OrderSampleProcess 装配图,见图 4。

    图 4. Business Integration 视图中的 OrderSampleProcess
    Business Integration 视图中的 OrderSampleProcess

创建组件并分配接口

现在 OrderSampleProcess 应用程序可以使用 OrderSampleLibrary 中的业务对象和接口了,接下来可以创建过程、人工任务和 Java™ 组件,在模块中分配对应的接口。

按以下步骤在装配图中添加组件:

  1. 创建 Process 组件,打开装配编辑器,选择 Process 并把它拖到编辑器中,把这个组件改名为 OrderProcess。(注意:左下角的惊叹号图标表示还没有创建这个组件的实现:稍后创建这个实现。)
  2. 分配接口,右键单击 OrderProcess,选择 Add => Interface,选择 NewOrderInterface,然后单击 OK
  3. 创建 Human Task 组件,打开装配编辑器,选择 Human Task 并把它拖到编辑器中,把这个组件改名为 ManagerApproval
  4. 分配接口,右键单击 ManagerApproval,选择 Add => Interface,选择 OrderApprovalInterface,然后单击 OK
  5. 创建 Java 组件,打开装配编辑器,选择 Java 并把它拖到编辑器中,把这个组件改名为 ProcessOrderService
  6. 分配接口,右键单击 ProcessOrderService,选择 Add => Interface,选择 ProcessOrderInterface,然后单击 OK
  7. 在 Add Wire 对话框中单击 OK,在 OrderProcessManagerApproval 之间以及 OrderProcessProcessOrderService 之间创建连接。
  8. 保存装配图。装配编辑器的内容应该像图 5 这样。

    图 5. 装配编辑器
    装配编辑器

现在已经定义了三个组件,下面可以创建每个组件的实现。

创建 ProcessOrderService 的 Java 实现

当经理批准订购请求时,过程通过调用这个 Java 组件来处理订购请求。按以下步骤实现它:

  1. 打开装配编辑器,右键单击 ProcessOrderService 并选择 Generate implementation。保持默认设置并单击 OK
  2. 这时会创建一个 Java 类,其中有一个与 ProcessOrderInterface 中定义的操作同名的方法。在这个方法中添加清单 1 所示的逻辑。

    清单 1. ProcessOrderRequest 方法的实现
    						
    public String processOrderRequest(DataObject orderRequest,DataObject approvalMsg){
        String responseMsg = "This order has been approved, it will be sent to supplier 
    for further processing....."
        System.out.println(responseMsg);
        return  responseMsg;
    }
                

  3. 保存装配图。

创建 ManagerApproval 人工任务的实现

按以下步骤创建 ManagerApproval 人工任务的实现:

  1. 打开装配编辑器,右键单击 ManagerApproval 并选择 Generate implementation。保持默认设置并单击 OK
  2. 当人工任务编辑器打开并显示 ManagerApproval 时,关闭它并保存装配图。

创建 OrderProcess 的实现

OrderProcess 是一个过程组件,其中包含订购请求的业务逻辑。它接收订购请求并等待经理批准。这个业务流程是使用 Business Process Execution Language (BPEL) 建模的,在过程编辑器中显示为一系列活动。按以下步骤使用过程编辑器创建和编辑订购请求过程:

  1. 接收订购请求。
  2. 经理人工地批准请求。
  3. 判断经理是否批准了请求。如果请求被拒绝了,就向用户发送一条消息。如果请求被批准了,就调用 ProcessOrderService 继续处理它。

按以下步骤生成 OrderProcess 组件的实现:

  1. 打开装配编辑器,右键单击 OrderProcess 并选择 Generate implementation。保持默认设置并单击 OK
  2. 过程编辑器打开,其中显示一个基本的业务流程,见图 6。保存装配图。

    图 6. 过程编辑器显示 OrderProcess
    过程编辑器显示 OrderProcess

  3. 进入过程编辑器的 Properties 视图并选择 Details 以打开过程属性。
  4. 因为经理可能无法马上处理请求,应该把这个过程设置为长时间运行的过程。确保选中 Process is long-running,见图 7。
  5. 我们希望用户能够看到响应,所以不希望过程实例被自动删除。对于 Automatically delete the process after completion 选择 No

    图 7. OrderProcess 详细信息
    OrderProcess 详细信息

  6. 接下来,添加一个全局变量以保存经理批准消息。在 Variables 下面,单击加号。把这个变量命名为 approvalMsg,选择 ApprovalResponseBO 作为数据类型,然后单击 OK。这个变量会添加到变量列表中。
  7. 在过程编辑器面板中,把 Structure 类别中的 Generalized Flow 拖放到 ReceiveReply 之间。
  8. Basic Actions 类别中的 Invoke 拖放到 Generalized Flow 结构中,把它的名称设置为 InvokeTask
  9. 选择 InvokeTask 活动,然后进入 Properties 视图并选择 Details
  10. 在 Details 视图中(见图 8),选择 OrderApprovalInterfacePartner 作为 Partner,选择 approveOrder 作为 Operation
  11. 在表格中,对于 Input(s),在 approvalMsg 行(最后一列名为 Read From Variable)中选择 (none)。从下拉列表中选择 orderRequest 变量。
  12. 对于 Output(s),在 response 行(最后一列名为 Store Into Variable)中选择 (none)。从下拉列表中选择 approveMsg 变量。

    图 8. InvokeTask 活动详细信息
    InvokeTask 活动详细信息

  13. Structures 类别中的 Choice 拖放到 GeneralizedFlow 结构中,把它的名称设置为 Choice。把默认 case 改名为 Approve
  14. 在 Properties 视图中,选择 Approve case,然后选择 Details。对于 Expression Language 选择 XPath 1.0,把条件设置为 $approveMsg/isApproval=true(),见图 9。

    图 9. Approve case 详细信息
    Approve case 详细信息

  15. Choice 活动创建第二个 case:右键单击 Choice,然后选择 Add a case,把它改名为 Reject
  16. 在 Properties 视图中,选择 Reject case,然后选择 Details。对于 Expression Language 选择 XPath 1.0,把条件设置为 $approveMsg/isApproval=false(),见图 10:

    图 10. Reject case 详细信息
    Reject case 详细信息

  17. 现在已经在 Choice 活动中创建了两个 case。对于每个 case,需要创建一个后续活动。把 Basic Actions 类别中的 Invoke 拖放到 Choice 结构中,放在 Approve case 后面,把它的名称设置为 ProcessOrder
  18. Assign 拖放到 Choice 结构中,放在 Reject case 后面,把它的名称设置为 RejectedMsg
  19. 在 Properties 视图中选择 RejectedMsg 并指定详细信息,见图 11:

    图 11. RejectedMsg 详细信息
    RejectedMsg 详细信息

  20. 在 Properties 视图中指定 ProcessOrder 活动的详细信息,见图 12:

    图 12. ProcessOrder 详细信息
    ProcessOrder 详细信息

  21. 在过程编辑器中,右键单击 InvokeTask 并选择 Add a linkInvokeTask 活动与 Choice 活动连接起来。
  22. 现在,过程的实现已经完成了。保存它之后,这个过程应该像图 13 这样。

    图 13. OrderProcess 实现
    OrderProcess 实现

OrderSampleProcess 应用程序现在完成了。部署这个应用程序之后,它就可以接收来自 Web 服务客户机的请求以创建过程并声明和完成人工任务。在 下载 中可以找到完整的示例。

您需要基本了解 BFM 和 HTM Web 服务 API 的功能,因为我们将用 Flex 发出一些 Web 服务调用。Business Process Choreographer 提供两个单独的 Web 服务接口。BFM API 允许与微型流和长时间运行的过程交互。在本文中,我们用它完成以下操作:

  • 查询过程模板
  • 创建和启动过程实例

HTM API 让客户机应用程序可以与人工任务交互。在本文中,我们用它完成以下操作:

  • 查询任务集合
  • 声明现有的任务
  • 完成任务
  • 传输工作项

从 WebSphere Process Server 导出 WSDL 文件

为了研究 BFM 和 HTM Web 服务 API,可以从 Process Server 导出 Web Service Description Language (WSDL) 文件,稍后将通过它调用 Web 服务接口。

按以下步骤导出 WSDL 文件:

  1. 确认 Process Server 已经启动。
  2. 在浏览器中登录管理控制台(默认 URL http://localhost:9060/admin)。
  3. 为了导出 BFM API WSDL 文件,在左边的导航条中选择 Applications => Enterprise Applications(见图 14),单击 BPEContainer_{your_nodename}_server1

    图 14. BPEContainer 应用程序
    图 14. BPEContainer 应用程序

  4. 在应用程序的配置页面中,单击 Web Services Properties 部分中的 Publish WSDL files,见图 15。

    图 15. 应用程序的配置页面
    图 15. 应用程序的配置页面

  5. 选择 zip 文件(见图 16),把它保存到本地目录中。

    图 16. 下载页面
    图 16. 下载页面

  6. 解压文件,会看到 WSDL 文件 BFMWS.wsdl。
  7. 为了导出 HTM API WSDL 文件,选择 Applications => Enterprise Applications 并单击 TaskContainer_{your_nodename}_server1
  8. 重复以上步骤下载并解压文件,会看到 WSDL 文件 HTMWS.wsdl。

得到 BFM 和 HTM API 的 WSDL 文件之后,可以使用 Integration Developer WSDL 编辑器打开并研究它们。关于这些 Web 服务 API 的更多信息,参见 参考资料 中的文章。

后端的业务流程应用程序已经完成了,现在可以使用 Flex 构建一个富 Web 客户机,让它与刚才构建的过程和人工任务交互。BizFlexClient.zip 中包含完整的 Adobe Flex 项目源代码文件。如果您还没有下载并解压这个文件,现在就执行这个步骤。

用 Flex 调用 BFM 和 HTM Web 服务

在本节中,讨论如何用 Flex 调用 BFM 和 HTM Web 服务 API。Business Process Choreographer 提供的 Web 服务 API 由 Web 服务安全机制保护。这意味着对 Web 服务接口的所有请求必须包含一个安全令牌,安全令牌代表有效的用户凭证。

有几种安全令牌。在我们的示例中,使用 Username 令牌。WSS-SOAP 消息安全文档中引入了 元素作为一种提供用户名的方法。清单 2 说明 元素的 XML 语法:


清单 2. 的 XML 语法

				

 ... 
 ... 
 ... 
 ... 


按以下步骤用 Flex 调用 BFM 和 HTM Web 服务 API:

  1. 创建一个名为 BizFlexClient 的 Flex 项目。
  2. 为了创建一个 Web 服务代理并让它向远程 Web 服务服务器发送请求,定义一个名为 WSBase.asActionScript 类,它扩展超类 mx.rpc.soap.AbstractWebService。这个类编码 SOAP 请求消息、把消息发送出去并处理结果,还要装载和解析 WSDL 文件。
  3. 为了创建 Username 令牌,在 WSBase.as 类中定义一个名为 createWSSEHeader 的函数。
  4. 首先需要设置用户名和密码。在这里,已经生成了 元素,密码以明文形式发送。最后,createWSSEHeader()(见清单 3)将返回一个 SOAP 头 XML 消息,它代表用户凭证。

    清单 3. 在 WSBase.as 中创建 Username 令牌
    						
    public class WSBase extends AbstractWebService
    {
      	private function createWSSEHeader():XML{
    		if(this._username != null && this._password != null){
      			var userToken:String = "UsernameToken-"
    +Math.round(Math.random()*999999).toString();
      			var wsseHeader:XML = <{SOAP_CONSTS.headerQName.localName}/> 
                  wsseHeader.setNamespace(SOAP_CONSTS.envelopeNamespace);
                  var nsSecurityString:String = "http://docs.oasis-open.org/wss/2004/01
    /oasis-200401-wss-wssecurity-secext-1.0.xsd";
                  var securityQname:QName = new QName(nsSecurity,"Security");
                  var nsSecurity:Namespace = new Namespace("wsse",nsSecurityString);
                  var headerElem:XML = <{securityQname.localName}/>
                  headerElem.setNamespace(nsSecurity);
                  headerElem.addNamespace(SOAP_CONSTS.envelopeNamespace);
                  var attrStr:String = SOAP_CONSTS.envelopeNamespace.prefix;
                  headerElem.@[attrStr + ":" + SOAP_CONSTS.mustUnderstandQName.
    localName] = "1"; // Use "1" form. for WS-I compatibility
      			
      			var userNameElem:XML = 
               			
      	            		{this._username}
      	            		
    {this._password}
               			;
                  headerElem.appendChild(userNameElem);
            		wsseHeader.appendChild(headerElem);
            		this._wsseHeader = wsseHeader;
            		return wsseHeader;		
    		}
    		return null;
    	}
    }
    

  5. 为了在 WSBase.as 中编码 SOAP 消息,定义一个名为 encodeSOAPMessage 的函数,它把 SOAP Header 元素和 SOAP Body 元素编码为 SOAP Envelope 元素,见清单 4。这个元素是 SOAP 消息的根元素。

    清单 4. 在 WSBase.as 中编码 SOAP 消息
    						
    protected function encodeSOAPMessage(operationBody:XML):XML{ 
        var envelopeXML:XML = <{SOAP_CONSTS.envelopeQName.localName}/>;
        envelopeXML.setNamespace(SOAP_CONSTS.envelopeNamespace);
        envelopeXML.addNamespace(this._operationNS);
        var wsseHeader:XML = this.createWSSEHeader();
        if(wsseHeader != null){
            envelopeXML.appendChild(wsseHeader); // append the WSSE header
        }	
        // Create SOAP Body element
        var bodyXML:XML = <{SOAP_CONSTS.bodyQName.localName}/>; 
        bodyXML.setNamespace(SOAP_CONSTS.envelopeNamespace);
        operationBody.setNamespace(this._operationNS);
        bodyXML.appendChild(operationBody);
        envelopeXML.appendChild(bodyXML);
        return envelopeXML;
    }
    

  6. 为了对远程 Web 服务服务器执行调用,在 WSBase.as 中定义一个名为 call 的函数。这个函数使用 AsyncRequest 类发送异步请求,实现远程过程调用。当远程请求完成时,回调请求中指定的响应器。还需要定义 processResult 函数(处理结果数据)和 faultResult 函数(处理错误),见清单 5。

    清单 5. 在 WSBase.as 中调用服务器
    						
    private function processResult(result:Object,wrappedData:Object):void
    {		
        var body:Object = result.message.body;
        var stringResult:String = String(body);
        //    trace(stringResult);
        if(stringResult == null  || stringResult == "")
        	return;
        var bodyXML:XML = XML(body);
        // remove the namespaces from the returned xml
        var regex:RegExp = new RegExp("xmlns[^\"]*\"[^\"]*\"","gi");
        var regex2:RegExp = new RegExp("<[\\w]*:","gi");
        var regex3:RegExp = new RegExp("<\/[\\w]*:","gi");
        var regex4:RegExp = new RegExp("xsi[^\"]*\"[^\"]*\"","gi");
        var xmlWithoutNS:String = bodyXML.toXMLString().replace(regex,"");
        var xmlWithoutNS2:String = xmlWithoutNS.replace(regex2,"<");
        var xmlWithoutNS3:String = xmlWithoutNS2.replace(regex3,"

  7. 在向远程 Web 服务发送请求之前,必须装载并解析服务的 WSDL 文件。为此,在 WSBase.as 中定义一个名为 parseWSDL 的函数(见清单 6),它通过 HTTP 请求获取 WSDL 文件,当成功地装载文件时发送 Web 服务请求。

    清单 6. WSBase.as 中的 WSDL 装载器
    						
    private function parseWSDL(wsdlURL:String,aysnCallParam:Object=null):void{
       if(wsdlURL != null){
       this._wsdlURL = wsdlURL;
       var wsdlLoader:HTTPService = new HTTPService();
       wsdlLoader.url = this._wsdlURL;
       wsdlLoader.resultFormat="object";
       wsdlLoader.addEventListener(ResultEvent.RESULT,initWebService);
       wsdlLoader.addEventListener(FaultEvent.FAULT,wsdlFaultHandler);
       wsdlLoader.send();
       var obj:Object = this;
    	 function initWebService(event:ResultEvent):void{
    		    var _wsdlObj:Object = event.result;
    		    obj._importLoc = _wsdlObj["definitions"]["import"].location;
    		    obj._importNS = _wsdlObj["definitions"]["import"].namespace;
    		    obj._endpointURI = _wsdlObj["definitions"]
    ["service"]["port"]["address"].location;
    		    obj._operationNS = new Namespace("ns",obj._importNS);
    		    obj._isWSDLLoaded = true;
    		    if(aysnCallParam != null){
    		    	obj.call(aysnCallParam.operation,aysnCallParam.operationBody,
    aysnCallParam.callback);
    		    }
    		}                
    	}
    }
    private function wsdlFaultHandler(event:FaultEvent):void
    {
    var detail:String = "Uunable To LoadWSDL "+event.currentTarget.url;		
        Alert.show(detail, "Error");	
    }
    

  8. 现在已经创建了一个简单的 Web 服务代理,下面可以创建 BFMWebService.asHTMWebService.as 类来实现所需的 BFM 和 HTM API。这两个类都以 WSBase 作为超类。
  9. BFMWebService.as 中,定义 queryProcessTemplatesstartProcess 函数,它们与过程交互,见清单 7。

    清单 7. BFMWebService.as 中的 BFMWebService 类
    						
    public class BFMWebService extends WSBase
    {
    	public function queryProcessTemplates(whereClause:String=null,
    orderByClause:String=null,threshold:Number=10,
    callback:Function=null):void{
              var out:Object = new Object();
              out["whereClause"] = whereClause;
              out["orderByClause"] = orderByClause;
              out["threshold"] = threshold;
      		    var soapOperation:String = "queryProcessTemplates";
      		    var operationBody:XML = <{soapOperation}/>;
      		    var children:XMLList = this.objectToXML(out);
      		    operationBody.appendChild(children);
      		    this.aysnCall(soapOperation,operationBody,callback);
    	}
    	public function startProcess(processTemplateName:String,
    portTypeName:String,portTypeURI:String,
    operationName:String,operationInputs:IInputData,callback:Function=null):void{
              var param1:XML = {processTemplateName}
    ;
              var param2:XML = {portTypeName}
    
              var param3:XML = {operationName};
              var param4:XML = null;
              if(operationInputs != null){
              	param4 = <{operationName}/> 
              	param4.appendChild(operationInputs.toXML());
              	var inputNamespace:Namespace = new Namespace("tt",portTypeURI);
              	param4.setNamespace(inputNamespace);
              }
      		    var soapOperation:String = "sendMessage";
      		    var operationBody:XML = <{soapOperation}/>;
      		    operationBody.appendChild(param1);
      		    operationBody.appendChild(param2);
      		    operationBody.appendChild(param3);
      		    if(param4 != null){
      		    	operationBody.appendChild(param4);
      		    }
      		    trace(operationBody);
      		    this.aysnCall(soapOperation,operationBody,callback);		
    	}
    }
    

  10. HTMWebService.as 中定义以下函数来操作人工任务:getTODOTasksclaimcompleteWithOutputtransferWorkItem,见清单 8。

    清单 8. HTMWebService.as 中的 HTMWebService 类
    						
    public class HTMWebService extends WSBase
    {
    	public function getTODOTasks(threshold:int,callback:Function=null):void{
              var out:Object = new Object();
              out["selectClause"] = "TASK.TKIID,TASK.NAME,TASK.ORIGINATOR,TASK.OWNER,
    TASK.STATE,TASK.KIND";
              out["whereClause"] = "(TASK.STATE = TASK.STATE.STATE_READY OR 
    TASK.STATE = TASK.STATE.STATE_CLAIMED) AND (TASK.KIND = 
    TASK.KIND.KIND_PARTICIPATING OR TASK.KIND = TASK.KIND.KIND_HUMAN) AND 
    WORK_ITEM.REASON = WORK_ITEM.REASON.REASON_POTENTIAL_OWNER";
              out["skipTuples"] = 1;
              out["threshold"] = threshold;
    	    var soapOperation:String = "query";
    	    var operationBody:XML = <{soapOperation}/>;
    	    var children:XMLList = this.objectToXML(out);
    	    operationBody.appendChild(children);
    	    this.aysnCall(soapOperation,operationBody,callback);		    
    	}
    
    	public function claim(tkiid:String,callback:Function=null):void{
              var out:Object = new Object();
              out["tkiid"] = tkiid;
    	    var soapOperation:String = "claim";
    	    var operationBody:XML = <{soapOperation}/>;
    	    var children:XMLList = this.objectToXML(out);
    	    operationBody.appendChild(children);
    	    this.aysnCall(soapOperation,operationBody,callback);		    
    	}
    	public function completeWithOutput(tkiid:String,taskServiceInterfaceURI:String,
    tResponse:IInputData,
    callback:Function=null):void{
    		var param1:XML = {tkiid};
    		if(tResponse != null){
                  var param2 = tResponse.toXML();
              	var inputNamespace:Namespace = new Namespace
    (taskServiceInterfaceURI);
              	param2.setNamespace(inputNamespace);				
    		   var soapOperation:String = "completeWithOutput";
    	       var operationBody:XML = <{soapOperation}/>;
    	       operationBody.appendChild(param1);
    	       operationBody.appendChild(param2);
    	       trace(operationBody);
    	       this.aysnCall(soapOperation,operationBody,callback);
    		}
    	}
    
    	public function transferWorkItem(identifier:String,fromOwner:String,
    toOwner:String,
    callback:Function=null)
    :void{
              var out:Object = new Object();
              out["identifier"] = identifier;
              out["assignmentReason"] = 4;
              out["fromOwner"] = fromOwner;
              out["toOwner"] = toOwner;
    	    var soapOperation:String = "transferWorkItem";
    	    var operationBody:XML = <{soapOperation}/>;
    	    var children:XMLList = this.objectToXML(out);
    	    operationBody.appendChild(children);
    	    this.aysnCall(soapOperation,operationBody,callback);			
    	}		
    }
                

用 Flex 创建用户界面

现在已经创建了调用 BFM 和 HTM Web 服务 API 的类,下面创建一个简单的用户界面,它使用这些 API 与过程和人工任务交互。

在我们的示例中(见图 17),您会看到:

  • 顶部有一个表单,它用于配置 Web 服务的参数。
  • 左边有一个用于操作过程的面板,可以在其中查看过程模板并创建新的订购请求过程。
  • 右边有一个用于操作人工任务的面板,可以在其中查看人工任务、声明、完成并传输工作项。


图 17. 示例应用程序的简单 UI
示例应用程序 UI

解压 BizFlexClient.zip 的 Flex 项目源代码目录中的 BizFlexClient.mxml 文件包含用户界面的完整源代码。可以把这个文件复制到 Flex 项目 BizFlexClient 中以创建用户界面。

我们来看看用来构建用户界面的一些脚本函数:

  1. 在 BizFlexClient.mxml 的 Script 部分中,更新 BFM 和 HTM Web 服务 WSDL 文件 URL 的值,见清单 9。

    清单 9. 在 BizFlexClient.mxml 中更新 WSDL 文件 URL 和用户名的值
    						
    [Bindable]
    private var bfmws:BFMWebService = new BFMWebService(null);
    private var htmws:HTMWebService = new HTMWebService(null);            
    public function initWebService():void{
    	bfmws.setCredentials(this.userName.text,this.password.text);
    	bfmws.setWsdlURL(this.bfmws_url.text);
     	htmws.setCredentials(this.userName.text,this.password.text);
    	htmws.setWsdlURL(this.htmws_url.text);           	
    }  
    

  2. 对于每个按钮,添加 click 属性,让应用程序知道当用户单击按钮时应该做什么,见清单 10。onQueryProcessTemplates ()onNewOrderProcess()onGetTODOTasks()onClaim()onComplete()onTransfer() 的基本逻辑是相似的;清单 10 给出 onQueryProcessTemplate

    清单 10. BizFlexClient.mxml 中的按钮定义和相应的函数
    						
    
    
    
    
    
    
    
    
    
                

现在 Flex 客户机应用程序已经完成了,它可以通过调用 BFM 和 HTM Web 服务 API 与 Process Server 上运行的 OrderSampleProcess 交互。可以轻松地扩展它以使用其他 BFM 和 HTM Web 服务 API,以及为其他业务流程应用程序构建相似的客户机。

按以下步骤部署和运行示例:

  1. 确认 Process Server 已经启动而且在 Process Server 上已经安装了 OrderSampleProcess.ear,然后启动应用程序。
  2. 在解压 BizFlexClient.zip 的目录中找到 BizFlexClient.html。
  3. 在浏览器中打开 BizFlexClient.html。
  4. 在配置表单中(见图 18),确认 BFM 和 HTM Web 服务的 URL 是正确的,指定用户 ID 和密码。
  5. 现在,可以通过 Flex Web 页面访问部署的过程和人工任务。


图 18. 业务流程应用程序的示例 Flex 客户机
业务流程应用程序的示例 Flex 客户机

在本文中,您了解了如何使用 WebSphere Integration Developer V6.2 构建业务应用程序,以及如何在 Flex 中使用 WebSphere Process Server 提供的 Business Flow Manager 和 Human Task Manager Web 服务 API 与业务流程和人工任务交互。您现在应该能够为 WebSphere 业务应用程序设计和开发与 Adobe Flex 相似的 Web 服务客户机。

作者要感谢 Wu Yu、Xiang Cheng、Jia Gu 和 Yun Zhi Bian 为本文提供的帮助。

原文链接:http://www.ibm.com/developerworks/cn/websphere/library/techarticles/1003_xue/1003_xue.html

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14789789/viewspace-674577/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-07-08

  • 博文量
    355
  • 访问量
    855738