Seam和Drools融合示例

发布者:    |       Seam

Drools Fusion 是负责将事件处理能力添加到Drools5平台的模块。它定义了一系列目标来支持复杂事件处理

  • 以第一类公民的身份支持具有适当语义的事件。
  • 允许检测、关联、聚合和组合事件。
  • 支持事件流的处理。
  • 支持时间约束以模拟事件之间的时间关系。
  • 支持有趣事件的滑动窗口。
  • 支持会话范围的统一时钟。
  • 支持复杂事件处理用例所需的事件量。
  • 支持(重新)活跃规则。
  • 支持事件输入到引擎(管道)的适配器。

Seam与Drools5的集成旨在提供与Drools5融合的完全集成,并提供Seam特定的便捷方式与Fusion模块交互。

为了展示这个集成的示例,我们将再次处理Numberguess示例。这个Numberguess示例通过一个游戏来描述,用户有九次机会猜测1到100之间的随机数。每次猜测都会触发一个页面流程,进而调用Drools做出决策(赢、输或继续猜测),直到猜到正确数字或达到九次机会,游戏结束。

对于Fusion示例,我们将稍微改变一下游戏。用户不再是猜九次,而是有一分钟的时间猜测正确数字。那么让我们开始吧。

1. 将Fusion集成到我们的Numberguess示例中的第一个更改是对规则本身。GameCount规则是变更的焦点,需要查看。

rule GameCount
   when
   	  gameStart : GameStart() from entry-point "Guess Stream" 
	  Guess( time after[1m,*] gameStart.time ) from entry-point "Guess Stream" 
   then
      decision.setOutcome("lose");
      game.setMessage("Game time of 1 minute exceeded.");
end

规则谓词模式匹配以下条件为真。

存在一个类型为 GameStart 的事件,该事件来自 猜数流 入口点(入口点对于 Drools 来说是事实数据进入的一个门户,你可以在文档 中了解更多关于此的信息)。

并且

b) 存在一个类型为 Guess 的事件,其与 GameStart 事件的时间差超过一分钟(这基本上意味着如果用户在游戏开始后 1 分钟内做出猜测)。

如果匹配到这个模式,我们将游戏决策设置为 失败,并向用户提供适当的消息,说明他们为何输掉游戏。

2. 现在我们已经有了规则,我们回到了 Seam 代码中,需要将其全部组合在一起。像往常一样,首先我们需要在 components.xml 中声明我们的 KnowledgeBase。

<drools:knowledge-base name="kbase" knowledge-builder-config="kbuilderconfig.properties" knowledge-base-config="kbaseconfig.properties">
    	<drools:rule-resources>
    		<value>classpath;numberguesscep.drl;DRL</value>
    	</drools:rule-resources>	
    	<drools:event-listeners>
    		<value>org.drools.event.knowledgebase.DefaultKnowledgeBaseEventListener</value>
    	</drools:event-listeners>
    </drools:knowledge-base>

注意属性 knowledge-base-config 指向 kbaseconfig.properties。Drools 有两种处理模式,即 CLOUD 和 STREAM。CLOUD 处理模式是默认处理模式,对于所有 Drools 用户来说应该很熟悉。STEAM 处理模式是在应用程序需要处理事件流时使用的模式,这是我们示例所需要的,我们通过在属性文件中定义属性 drools.eventProcessingMode 并将其设置为 stream 来告诉引擎我们要使用它。

完成此操作后,我们需要创建 StatefulKnowledgeSession

<drools:stateful-knowledge-session name="ksession" knowledge-base="#{kbase}" knowledge-session-config="ksessionconfig.properties"
    audit-log="/home/tsurdilo/Desktop/ksessionlogs/ksession">
    	<drools:event-listeners>
    		<value>org.drools.event.rule.DebugAgendaEventListener</value>
    		<value>org.drools.event.rule.DebugWorkingMemoryEventListener</value>
    	</drools:event-listeners>
</drools:stateful-knowledge-session>

注意属性 knowledge-session-config 指向 ksessionconfig.properties。Drools Fusion 默认提供两种时钟实现,即实时时钟和伪时钟。伪时钟用于测试,而实时时钟在内部使用系统时钟,这是我们示例所需要的。我们通过在属性文件中将属性 drools.clockType 设置为 realtime 来设置它。

如果你到现在还在阅读,你应该记得在我们的 GameCount 规则 中,我们说我们的事件来自 猜数流 入口点。所以现在我们需要定义这个入口点,我们将把所有的用户猜测事件喂入这个入口点。

<drools:working-memory-entry-point name="guessEntryPoint" 
       ksession="#{ksession}" entry-point-name="Guess Stream"/>    

WorkingMemoryEntryPoint 组件是我们为 Seam 与 Fusion 集成添加的,它提供了一个方便的方式来获取 Drools 入口点。

接下来需要做的就是将所有这些内容整合到我们的 页面流程定义 中。

<decision name="drools">
      <handler class="org.jboss.seam.drools.KnowledgeDecisionHandler">
         <workingMemoryName>ksession</workingMemoryName>
         <entryPointName>guessEntryPoint</entryPointName>
         <assertObjects>
            <element>#{gameStart}</element>
            <element>#{guess}</element>
         </assertObjects>
      </handler>
....

这里的新功能是能够将入口点传递给 KnowledgeDecisionHandler,后者知道如何将事件插入到这个入口点。目前我正在努力为 KnowledgeDecisionHandler 添加对多个入口点的支持,这在有多个事件流同时向规则引擎提供事件时非常有用。

就这样,用户现在有一分钟的时间来猜测正确的数字...并且它使用 Drools Fusion :)


回到顶部