摘要:通过从业务逻辑中分离业务知识,业务规则为管理动态的业务逻辑提供了一个很好的解决方法。但是已经存在的大多数业务规则方法缺乏标准和互操作性。缺乏面向服务和业务规则引擎的远程可访问性,因此很难用在分布式环境中。该文章贡献了ViDRE的设计和实现,是一个基于RuleML的面向服务的规则引擎。ViDRE使得企业应用能像访问数据库一样访问业务规则,把规则暴露为Web services. ViDRE利用RuleML作为表达事实,规则和查询的通用语言。ViDRE方法一个主要的贡献就是通过不同的规则引擎分配规则和事实,因此,可以在组织内或组织间有效的分离和执行业务规则。<o:p></o:p>
1、简介<o:p></o:p>
当今商业迅速变化,组织必须能够处理市场经济的动态变化。这样的具有竞争性的商业环境需要商业应用必须具有足够的灵活性和适应性,来应付商业条件和策略的频繁变化。软件应用必须能够跟随需求的变化,因此,对于市场迅速变化的有效的响应是成功的关键因素。<o:p></o:p>
很多工业领域是高度分布的,这种组织结构也反映在IT的结构上,运行这样的业务必须具有可靠的分布式系统。很多公司利用业务规则引擎作为IT系统的一部分来管理他们的动态业务策略和规则。业务规则技术通过从应用代码中分离业务规则导致了,业务应用的发展。显示的指定策略和知识,提高了企业应用的可维护性和适应性。<o:p></o:p>
除了业务规则的应用以外,企业应用还增强面向服务体系结构来实现标准的接口,在组织内和组织间提供他们的软件服务。业务规则与面向服务体系结构的结合可以开发出更灵活更具有适应性的企业应用。<o:p></o:p>
在这篇文章中,我们讨论了当前业务规则方法由于存在一些缺陷所以没有与SOA很好的集成方法。<o:p></o:p>
第一个问题是:缺乏一个远程接口,使得分布式应用不能调用远程规则。大多数规则引擎与企业应用连接作为一个库来使用。通过规则引擎提供的适当的接口来调用规则。规则的可访问性和可重用性仅限于本地应用,虽然其他企业应用可能也需要这组规则来完成某项工作。<o:p></o:p>
第二是缺乏规则表达语言的一个标准。每个规则引擎开发者都提供了表达规则的一个用户格式,因此就出现了规则的不同表达形式。这就很难在一个企业环境中使用多种规则引擎或替换成其他的规则引擎。而且妨碍在分布式环境中使用规则引擎,其他应用和服务能够利用规则引擎作为计算实体。<o:p></o:p>
第三个问题是业务规则的执行,规则引擎之间的远程通信允许从其他规则引擎获取数据来执行推理过程,我们提出了一种分布式规则执行。当然分布式规则执行的缺乏可以看作是前两个问题的结果。<o:p></o:p>
这篇文章中描述了ViDRE的设计和实现,一个具有几个创新特点的规则引擎,解决了前面提到的问题:第一,规则驱动方法与SOA相结合,可以很容易的集成到客户应用,应用可以很容易的消费业务规则服务。第二,通过提供一个轻量级的可插入的机制来解决规则引擎之间的互操作问题,该轻量级的插件式机制规则引擎的互换对于客户应用是完全透明的。而且,我们利用了RuleML,是当前规则的一个标准,作为在几个异构的规则引擎之间互换和表达业务的通用语言。第三,执行分布业务规则,即允许在几个业务规则引擎之间执行规则。<o:p></o:p>
2,背景<o:p></o:p>
在该节中简明介绍需要的几个概念。<o:p></o:p>
业务规则:Business Rules Group定义业务规则作为定义或约束业务某些方面的陈述,试图断言业务结构或影响业务行为。业务规则方法区别于定义,事实和规则。定义和事实表达业务知识,规则则用来指导决策制定,起源于新信息或基于一定条件的动作。除此之外,查询可以从知识集中找回需要的信息。<o:p></o:p>
规则引擎构件:典型的规则引擎包括几个构建:规则集包含执行所需要的所有规则。工作存储器包含规则引擎操作所需要的数据,模式匹配决定使用规则集中的哪条规则,给工作存储器的内容。推理引擎,在一个不连续的周期中工作,用来找出当前周期中哪条规则需要被激活,<o:p></o:p>
规则标记驱动:规则标记驱动目标是提供一种标准的规则语言,并且提供一个具有互操作性的平台,集成不同的规则语言,推理系统和知识表达范例。RuleML为规则知识表达提供XML语法,在几个商业和非商业规则系统之间具有互操作性。我们扩展了RuleML的用法,作为几个异构的规则引擎之间交换规则的格式,类似于Web service领域的soap消息。规则引擎出去或进来的需求和响应都被编码到RuleML。<o:p></o:p>
Java规则引擎API。JAVA规则引擎API是Java社区在java世界中为规则引擎定义的API。JSR94规范标准化了一组基础的规则引擎操作。包括分解规则集,增加对象到推理过程,激活规则,从规则引擎中得到对象。JSR94规则的一个主要的目标是用一个简单的适配器集成不同的规则引擎到客户应用而不需要规则引擎开发者做另外的工作。该规范提供了两个主要的部分,规则管理API和规则运行时API。管理接口主要用来载入和管理规则集,运行时API利用规则会话来执行特定规则集,表达客户和特定规则引擎的连接。主要的缺点是缺乏标准的规则表达格式。<o:p></o:p>
3、ViDRE方法<o:p></o:p>
ViDRE设计的目标是通过隐藏规则的实现和执行,利用面向服务的方法访问业务规则。一个业务规则引擎被封装为称为ViDRE服务提供者(VSP)。<o:p></o:p>
由于前面提到的不同规则引擎的异构性,ViDRE的体系结构是基于JSR94的,前面提到,该API有几个缺陷,很难提供与其他应用或其他规则引擎的互操作性,而且,不允许访问远程的规则引擎。因此,ViDRE把JSR94和RuleML结合在一起。在0.9版本中面向对象版本的RuleML已经足够可以表达事实,查询以及Java对象。结合这些功能可以插入支持JSR94API标准的不同的规则引擎,而不需要改变知识或规则集。<o:p></o:p>
<v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></v:path><o:lock aspectratio="t" v:ext="edit"></o:lock></v:shapetype><v:shape id="_x0000_i1025" style="WIDTH: 513.75pt; HEIGHT: 181.5pt" type="#_x0000_t75"><v:imagedata o:title="" src="file:///C:\DOCUME~1\lovely\LOCALS~1\Temp\msohtml1\01\clip_image001.emz"></v:imagedata></v:shape><o:p></o:p>
在图1中,每个VSP提供一个通用的RuleML接口,接收有效的RuleML文档作为输入。RuleML文档包含RuleML查询和RuleML事实用于查询的评估。类似于SOAP请求,RuleML可以通过任意的传输通道发送,例如HTTP,JMS甚至SMTP。RuleML接口响应同样编码在RuleML文档中。除了通用的RuleML接口,每个服务提供者公布两个WSDL接口,用来访问客户运行时和像Web服务那样管理接口。这两个接口提供JSR94提供的功能性,允许管理和执行规则集。<o:p></o:p>
访问VSP有两种可能的方式,第一,客户利用运行时WSDL接口来为给定的业务文档或编码在RuleML中的查询激活规则。管理WSDL接口主要用来管理和维护规则集。管理和客户运行时接口的分离,在实现安全策略或访问控制时具有更好的灵活性。JSR94作为标准的API用来访问客户端的Web服务接口。一个客户库实现JSR94API,并且对程序员封装了实现细节。因此,对于终端用户来说,他所使用的规则引擎的位置和提供者都是透明的。甚至客户库还隐藏了规则表达语言,因为,JSR94运行时API只支持Java对象作为输入。<o:p></o:p>
第二,SOAP-RuleML网关提供了一种访问业务规则的方法,作为well-defined web服务。VSP能够在运行时通过管理接口发布规则或查询Web service。客户应用只要利用SOAP-RuleML网关发布的相应的WSDL文件就可以访问这些规则。<o:p></o:p>
ViDRE客户A和B利用WSDL接口直接向业务规则引擎发送RuleML查询。从Java对象到RuleML的必要的转换对于客户端是透明的,因为已经被JSR94库实现隐藏了。ViDRE 客户C利用SOAP-RuleML网关直接调用作为Web service发布的业务规则。例如,用来计算折扣的一组规则集可以发布为DiscountCalculationService到SOAP-RuleML网关,可以被作为Web service来调用。<o:p></o:p>
面向服务的方法的主要好处除了方便集成以外,还能执行分布式规则。通用的规则和查询表达语言使得规则引擎能够包含其它VSP的知识,而不需要做扩展。<o:p></o:p>
3.1ViDRE服务提供者实现<o:p></o:p>
VSP主要的任务是1)利用JSR94实现一个插件式机制;2)为创建规则会话,并执行,RuleML请求到Java对象的转换;3)提供分布式的规则执行机制。<o:p></o:p>
插件式机制使得一个特定的规则引擎基于RuleMLTransformer和ServiceProvider接口的实现。使用的接口和工厂是在服务配置文件中被指定的。ServiceProviderFactory接口是用来获取一个具体的RuleMLTransformer就像插件式规则引擎的ServiceProvider。<o:p></o:p>
服务实现的核心是RuleEngineService类。该类具有到注册的规则引擎的服务提供者API的一个引用。该API用来为注册的规则引擎创建规则运行时和规则管理接口。除此之外,它还利用具体RuleMLTransformer处理RuleML的转化。<o:p></o:p>
RuleML转换<o:p></o:p>
所有从ViDRE服务提供者出入的请求响应都被编码在RuleML中。因此服务实现必须关心RuleML到插件式将规则引擎的规则描述语言的转换。Java对象到RuleML的转换可以利用Java的反射机制。Jess到Drools的转换可以通过组合Jess到RuleML转换器和RuleML到Drools转换器来实现。因此,要想转换为特定的规则描述语言,只要写一个新的转换器就可以了。<o:p></o:p>
<v:shape id="_x0000_i1026" style="WIDTH: 459pt; HEIGHT: 153pt" type="#_x0000_t75"><v:imagedata o:title="" src="file:///C:\DOCUME~1\lovely\LOCALS~1\Temp\msohtml1\01\clip_image003.emz"></v:imagedata></v:shape><o:p></o:p>
上图描述了增加一个新的fact到ViDRE服务提供者的过程。当要执行一个客户规则会话,会话中包含的对象必须要转换成等价的RuleML表达,才能传输到服务。<o:p></o:p>
Public class Order{<o:p></o:p>
Private int id;<o:p></o:p>
Private String customerId;<o:p></o:p>
Private String product;<o:p></o:p>
Private int quantity;<o:p></o:p>
//getters and setters<o:p></o:p>
}<o:p></o:p>
当增加一个新的fact,第一步是在客户端把java fact转换为RuleML fact。例如,定义了一个Order类,通过增加对象到规则会话,可以很容易的把该fact提交给服务提供者。客户库利用Object2RuleML转换来转换该类的一个实例到等价的RuleML表达。转换成的RuleML文档结果如下:<o:p></o:p>
<Atom><o:p></o:p>
<Rel>Order</Rel><o:p></o:p>
<oid><<st1:state w:st="on">Ind</st1:state>>Icala68</<st1:place w:st="on"><st1:state w:st="on">Ind</st1:state></st1:place>></oid><o:p></o:p>
<slot><o:p></o:p>
<<st1:state w:st="on">Ind</st1:state>>id</<st1:state w:st="on"><st1:place w:st="on">Ind</st1:place></st1:state>><o:p></o:p>
<<st1:state w:st="on">Ind</st1:state>>785</<st1:state w:st="on"><st1:place w:st="on">Ind</st1:place></st1:state>><o:p></o:p>
</slot><o:p></o:p>
<slot><o:p></o:p>
<<st1:state w:st="on">Ind</st1:state>>customerId</<st1:state w:st="on"><st1:place w:st="on">Ind</st1:place></st1:state>><o:p></o:p>
<<st1:state w:st="on">Ind</st1:state>>154</<st1:state w:st="on"><st1:place w:st="on">Ind</st1:place></st1:state>><o:p></o:p>
</slot><o:p></o:p>
<slot><o:p></o:p>
<<st1:state w:st="on">Ind</st1:state>>product</<st1:state w:st="on"><st1:place w:st="on">Ind</st1:place></st1:state>><o:p></o:p>
<<st1:state w:st="on">Ind</st1:state>>Mainboard XY</<st1:state w:st="on"><st1:place w:st="on">Ind</st1:place></st1:state>><o:p></o:p>
</slot><o:p></o:p>
<slot><o:p></o:p>
<<st1:state w:st="on">Ind</st1:state>>quantity</<st1:state w:st="on"><st1:place w:st="on">Ind</st1:place></st1:state>><o:p></o:p>
<<st1:state w:st="on">Ind</st1:state>>I</<st1:state w:st="on"><st1:place w:st="on">Ind</st1:place></st1:state>><o:p></o:p>
</slot><o:p></o:p>
</Atom><o:p></o:p>
Fact的名字被标记为相关的名字,四个属性利用RuleML语法的四个同一级别的slot来标记。对于每一个对象属性,一个slot包括属性名和对性的值。属性名和值作为单个常量<Ind>来标记。对应的,表达变量的属性值标记为<Var>。在服务端,RuleML表达可以利用Object2RuleML转换器转换回对象。因此就需要一个FactProxy,因为插件式的规则引擎只能操作java对象。Java对象实例是客户端创建的,在服务端不能使用。FactProxy用来创建一个暂时的传输过来的RuleML的一个对象表达。产生的对象可以被增加到服务端的规则会话,作为规则执行周期的输入。<o:p></o:p>
服务端的转换更复杂一些,因为包括RuleML规则到具体规则引擎规则的转换。<o:p></o:p>
<Implies><o:p></o:p>
<oid><<st1:state w:st="on">Ind</st1:state>>If a computer is ordered, then order individual parts at supplier.</<st1:place w:st="on"><st1:state w:st="on">Ind</st1:state></st1:place>><o:p></o:p>