热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

BPEL的基本思想

由于工作需要,接手别人用bpel写的工作流程序,一点都不懂就到网上找到一篇入门的文章,觉得这篇不错,就copy下来并添加了读书笔计以红字标记,感激写此文章的人.许多开发人员觉得BPEL很神秘,不知道

由于工作需要,接手别人用bpel写的工作流程序,一点都不懂就到网上找到一篇入门的文章 ,觉得这篇不错,就copy下来并添加了读书笔计以红字标记,感激写此文章的人.

许多开发人员觉得BPEL很神秘,不知道到底是什么意思。主要是因为它是根据很抽象的基于WSDL的Web Service再定义一些抽象执行的流程。

  其实BPEL一点都不神秘,是一个很简单的东西。

  首先谈一下BPEL和WSDL的区别,WSDL只是定义接口参数,不会定义如何实现接口,而BPEL不仅有自己的接口定义(也是一个WSDL文件,包括输入参数、方法操作名、返回参数),BPEL会定义如何调用其他服务的接口来实现自己的接口。简单地说,BPEL通过流程编程将各种接口组合在一起,其目的在于提供一个“集成了各种接口”的接口。

  首先BPEL会有一个起点和终点。

  1、它的起点就是“receive”,也就是接收它自己接口的输入参数。

  2、它的终点就是“reply”,也就是得到它自己接口的返回参数。

  整个BPEL就是定义如何通过它的接口输入参数,调用其他外部服务的接口,得到其接口的返回参数。

  它最重要的是两个定义:

  1、一个是赋值命令(Assign/Copy),通过赋值命令将某一变量值赋给所要调用的接口的输入参数。

  2、另一个是调用命令(Invoke),通过Invoke命令来调用外部服务。

  另外一个比较重要的就是条件命令(Case Condition),根据变量的不同来定义各种条件,然后根据各种条件来调用不同的服务。这些变量可以来自于输入参数,也可以来自于调用外部服务的结果。作为BPEL运行环境的一个重要功能就是能够保存并查询到这些变量。

  用Java实例模拟BPEL的创建过程

  这里用一个简单的实例来进一步说明BPEL的基本思想和核心本质,并用Java实例来模拟BPEL的创建过程。

  首先假定已经有了两个Web Service,一个为“加法服务”,专门处理两个数相加,名为AddService;另外一个为“减法服务”,专门处理两个数相减,名为SubtractService。

  现在有一个新的需求,需要将上面两个Web Service集成起来,也就是需要创建一个新的服务,称为“运算服务”,名为CaculatorService,它有一个运算类型的参数,当运算类型为“加法”时,调用加法服务,当运算类型为“减法”时,调用减法服务。

  看到这里,读者可能会想,直接写一个Java程序,调用者两个Web Service不就可以了吗?笔者的回答是:直接用Java编程当然可以,事实上现在大家就是这么做的。但是Java本质上是一种具体的程序语言,只能运行于JVM的Java运行环境,不是一种抽象性的通用的标准语言,而BPEL是一种标准化的执行语言,如何能够真正运行BPEL不是它所关心的事情,它还需要各个厂商去开发自己的BPEL运行环境,尽管各个厂商所开发的BPEL的运行环境可能会不一样,但是同一个BPEL所开发的程序,应该可以运行于这些不同的BPEL运行环境,得到的结果应该是一样的。就像Web Service的WSDL文件一样,它只管如何定义服务、服务接口、服务操作、服务参数等,如何具体实现Web Service不是WSDL所要关心的事情。

下面继续前面的实例,两个Service都会有自己的WSDL定义。下面用实际的Java语言来类似地描述一下,以便于理解。

  下面的AddService .java相当于AddService.wsdl(用Java的Interface可能更贴切一点,用Java的class可以说明得更详细一点)。

Public class AddService{
Public double add(double addParameter1, double addParameter2) {
Double addResposne;
addResposne = addParameter1 +addParameter2;
// WSDL 不会定义具体如何实现,
//此处只是说明如何实现操作
Return addResponse;
}
}

下面的SubstractService .java相当SubstractService.wsdl。

Public class SubstractService{
Public double substract(double substractParameter1, double substractParameter2) {
 Double substractResposne = substractParameter1 - substractParameter2;
 Return substractResposne;
}
}

  下面用Java模拟BPEL的创建过程。

  首先需要创建BPEL的接口,下面用CaculatorBPELInterface.java来说明,它将有3个参数,其中paramter1和paramter2是需要运算的两个数,第3个参数processType表示运算的类型。

Public Interface CaculatorBPELInterface{
Public double caculatorProcess(double parameter1, double parameter2, String processType) ;
}

  下面将创建一个Java实现类,说明如何对应于BPEL的创建过程(许多语句(如一些变量定义和赋值定义)对Java来说是不必要的;为了模拟BPEL的创建过程,让Java开发人员更好地把握BPEL的创建过程,相应地加入了这些程序语句)。

Public class CaculatorBPELImple implements CaculatorBPELInterface {
Public double caculatorProcess (double parameter1, double parameter2, String processType) {
//步骤1:定义所要调用的外部类(相当于定义BPEL里面partnerLink)
AddService addServer = new AddService();
SubstractService substractSevice = new SubstractService();
/*步骤2:定义输入和输出变量(相当于定义BPEL里面变量variable)
定义的变量如下:
● BPEL接口的输入和输出变量
● 所要调用的外部类的接口方法的输入和输出变量 */
//定义BPEL接口的输入变量
Double caculatorProcessParameter1Request;
Double caculatorProcessParameter2Request;
Double caculatorProcessTypeRequest;
//定义BPEL接口的输出变量
Double caculatorProcessResponse;
//定义加法服务的输入变量
Double addParameter1Request;
Double addParameter2Request;
//定义加法服务的输出变量
Double addResponse;
//定义减法服务的输入变量
Double substractParameter1Request;
Double substractParameter2Request;
//定义减法服务的输出变量
Double substractParameter1Response;
//***将请求参数赋值给BPEL接口的输入变量 (相当于BPEL的receive)
caculatorProcessParameter1Request = parameter1;
caculatorProcessParameter2Request= parameter2;
Double caculatorProcessTypeRequest= processType;
//步骤3:定义条件,并调用外部接口
If (caculatorProcessTypeRequest.equals.(“add”’)
// (相当于BPEL的switch/condition/case)
{
//**下面将调用加法服务
//将接口请求变量传给加法服务的请求变量 (相当于BPEL的assign/copy)
addParameter1Request = caculatorProcessParameter1Request;
addParameter2Request = caculatorProcessParameter2Request;
//调用addService的接口 (相当于BPEL的Invoke)
addRespOnse= addServer.add(addParameter1Request, addParameter2Request);
//将addResponse赋值给BPEL接口的输出变量 (相当于BPEL的assign/copy)
caculatorProcessRespOnse= addResponse;
} else //(相当于BPEL的 condition/otherwise)
{
//将接口请求变量传给减法服务的请求变量 (相当于BPEL的assign/copy)
substractParameter1Request = caculatorProcessParameter1Request;
substractParameter2Request = caculatorProcessParameter2Request;
//调用substractService的接口 (相当于BPEL的invoke)
substractRespOnse=
substractServer.substract(substractParameter1Request, substractParameter2Request);
//将substractResponse赋值给BPEL接口的输出变量(相当于BPEL的assign/copy)
caculatorProcessRespOnse= substractResponse;
}
Return caculatorProcessResponse; //相当于BPEL的reply
}
}

  用实例概述BPEL的创建过程

上面已经用Java模拟了BPEL的创建过程。下面将基于同样的实例,用描述性的WSDL和BPEL来实现其创建过程,使读者对BPEL能有一个整体性的掌握。

  假设已经有了前面的加法服务和减法服务的WSDL文件(仅仅有wsdl文件是不够的,我的意思是要有这二个webservice服务才行),加法服务为AddService.wsdl,减法服务为Substract.wsdl,它们的主要内容如下所示:

  AddService.wsdl

  |――getRequest (请求消息)

  |――addParameter1(double)

  |――addParameter2(double)

  |――getResponse(返回消息)

  |――addResponse(double)

  |――addServcie(portType接口)

  |――add(operation接口操作)

  |――AddService(service 服务名称)

  substractService.wsdl

  |――getRequest(请求消息)

  |――subtractParameter1(double)

  |――subtractParameter2(double)

  |――getResponse(返回消息)

  |――substractResponse(double)

  |――substractService(portType接口)

  |――substract(operation接口操作)

  |――SubstractService(服务名称)

  下面需要为BPEL创建一个服务接口(这个服务接口不知道是不是bpel框架本身自带的还是要用户自己建立,得实践一下),caculator.wsdl如下:

  caculatorService.wsdl

  |――getRequest(请求消息)

  |――parameter1(double)

  |――parameter2(double)

  |――processType (String)

  |――getResponse(返回消息)

  |――caculatorProcessResponse(double)

  |――caculatorService(portType接口)

  |――caculatorPorcess(operation接口操作)

  |――CaculatorService(service 服务名称)

  下面介绍创建BPEL的基本过程,即caculatorServiceProcess.bpel(下面只是说明BPEL的创建过程,没有完全按照BPEL的语法,具体的BPEL语法和BPEL编程实例后面会详细介绍)。

1)创建变量<bpel:variables>

  所定义的变量包括:

  1、BPEL接口的输入和输出变量。

  2、所要调用的外部服务partnerLink的接口操作的输入和输出变量。

<bpel:variables>
<!—BPEL流程的请求变量和返回变量 -->
variable name="request-bpel" messageType采用caculatorService/getRequest
variable name="response-bpel" messageType采用caculatorService/getResponse

(caculatorService为webservice服务名,request-bpel为变量名,getRequest为输入变量,getResponse为返回结果,不太明确返回结果为复杂数据类型如何操作)
<!—加法服务的请求变量和返回变量 -->
variable name="request-add" messageType采用addService/getRequest
variable name="response-add" messageType采用addService/getResponse
<!—减法服务请求变量和返回变量 -->
variable name="request-substract" messageType采用substractService/getRequest
variable name="response-substract" messageType采用substractService/getResponse
</bpel:variables>

  BPEL定义变量的方式与Java是不一样的,主要因为BPEL所调用的WSDL是XML语言上面的所定义的变量并不是对应一个具体的值,它实际上对应的是一个数据结构。

  如caculatorService/getRequest 对应的是caculatorService.wsdl下面的

(下面这段话很重要,后面会用到)  

getRequest

  |――parameter1(double)

  |――parameter2 (double)

  |――processType (String)

  也就是说getRequest下面的所有参数都包含进去了。

  2)创建接收<bpel:receive>

<bpel:receive name="request" partnerLink=" CaculatorService "
portType=" caculatorService " operation=" caculatorPorcess "
variable=" request-bpel " >

Receive是整个BPEL的起点,所定义的变量request-bpel从服务请求中得到赋值,整个后面的业务过程将以这个请求变量作为触发点。(把服务请求中的参数赋值给request-bpel变量,就是在上面定义的变量,用于下面调用其它webservice做输入参数)

  3)创建条件<bpel:switch/case>

  程序将根据不同的条件调用不同的服务,所以先要设立各种条件:

<bpel:switch>
<bpel:case
cOndition="getVariableData('request-bpel','payload','getRequest/processType'>= 'add' >

(getVariableData方法为bpel自带的方法,从这里可以看出request-bpel变量为变量集合,也就是caculatorService.wsdl文件里定义的所有变量集合,payload不知道是什么意思,可能是内部定义好的,不知道有没有其它参数,getRequest表明为服务请求参数,在一个webservice里还有一个是返回参数,processType为wsdl文件里定义众多参数中的一个参数)
… 调用加法服务
</bpel:case>

  上面的程序表示在request-bpel的变量中取出路径为getRequest/ processType所对应的变量值,如果满足这个值为“add”的条件时,可以在里面加入程序,完成相应的任务。

<bpel:otherwise>
…… 调用减法服务
<bpel:otherwise>

  如果上面的所有条件都不满足时,可以在里面加入程序,完成默认的任务。

  4)给所要调用的服务的请求变量赋值<bpel:assign/copy>

  为了调用外部服务,先要给外部服务赋值:

<bpel:assign>
<bpel:copy>
<bpel:from variable="request-bpel" part="payload" query="/getRequest/parameter1" />
<bpel:to variable="request-add" part="payload" query="/getRequest /addParameter1" />
</bpel:copy>
</bpel:assign>

(把bpel:from里的变量值赋给bpel:to里的变量值,注意后面的参数parameter1和addParameter1)

  上面表示将BPEL过程所收到的初始变量赋给加法服务的请求变量。

  5)调用外部服务<bpel:invoke>

(这里写着调用外服务,感觉上面创建接收<bpel:receive>就为内部服务,不知道是不是这样的)

<bpel:invoke name="addService" partnerLink="AddService"
portType="addService" operation="add"
inputVariable=" request-add"
outputVariable="response-add" />

(本文章可能少了写了一步,哪就是创建partnerLink节点)

  上面将会调用加法服务AddSerivce,其中request-add为输入变量。

  6)将服务的结果赋给BPEL的返回变量<bpel:assign/copy>

  在完成了外部服务的调用之后,就可以将外部服务的输出结果赋给BPEL流程的返回变量。文法同步骤4。

  7)调用<bpel:reply>

  调用BPEL的reply命令,将BPEL流程的返回变量返回给服务请求者。

<bpel:reply name="response" partnerLink="CaculatorService"
portType=" caculatorService" operation="caculatorPorcess"
variable=" response-bpel" />(注意这里用的是variable)

  这里比较一下步骤2的<bpel:receive>和步骤6的<bpel:reply>,可以看到它们的partnerLink的名字、portType的名字、operation的名字都是一样的。它们是调用的同一个服务下面的同一个接口操作,只是两个命令的变量不一样。<bpel:receive>是收到请求消息的变量值,<bpel:reply>是将响应变量的结果返回给服务请求者。

  事实上,BPEL运行环境执行<bpel:receive>后,就在等待<bpel:reply>的返回结果。

  上面通过实例介绍了BPEL的基本创建过程,有了这些基本的BPEL整体创建思路后,就可以为更好地理解一些具体的语法打下了基础。


推荐阅读
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 本文详细探讨了Java中的24种设计模式及其应用,并介绍了七大面向对象设计原则。通过创建型、结构型和行为型模式的分类,帮助开发者更好地理解和应用这些模式,提升代码质量和可维护性。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • 在金融和会计领域,准确无误地填写票据和结算凭证至关重要。这些文件不仅是支付结算和现金收付的重要依据,还直接关系到交易的安全性和准确性。本文介绍了一种使用C语言实现小写金额转换为大写金额的方法,确保数据的标准化和规范化。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 作为一名新手,您可能会在初次尝试使用Eclipse进行Struts开发时遇到一些挑战。本文将为您提供详细的指导和解决方案,帮助您克服常见的配置和操作难题。 ... [详细]
  • ImmutableX Poised to Pioneer Web3 Gaming Revolution
    ImmutableX is set to spearhead the evolution of Web3 gaming, with its innovative technologies and strategic partnerships driving significant advancements in the industry. ... [详细]
  • 本文详细介绍了Java中org.w3c.dom.Text类的splitText()方法,通过多个代码示例展示了其实际应用。该方法用于将文本节点在指定位置拆分为两个节点,并保持在文档树中。 ... [详细]
  • MySQL 数据库迁移指南:从本地到远程及磁盘间迁移
    本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ... [详细]
  • 本文探讨了如何在不重新加载URL的情况下,触发WebView的PictureListener.onNewPicture()方法,以实现页面的重新绘制或渲染。 ... [详细]
author-avatar
鱼和鱼还有鱼3_Mh_qet
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有