Drools 7-关于与推断的事实相关的事件的推理

时间:2018-11-08 17:58:00

标签: drools fusion

我们正在开发一个资源预订系统,在该系统中,我们将获得在任意时间(从5分钟到2小时不等)内预订资源的请求。没有预定义的插槽。

我们尝试使用Drools(Fusion)ver。 7.12.0.Final,编写规则以确保新的预订请求不会覆盖已确认的现有请求。

为达到上述目的,我们创建了以下两个对象:

declare ReservationRequest
    @role ( event )
    @duration (reservationDuration )
    @timestamp ( pickupTime )

    id                  : int
    pickupTime          : Date
    reservationDuration : long   
    reserved            : String
    deliveryEnd     : Date
end

declare Reservation
    reservation             : ReservationRequest
end

'ReservationRequest'被视为事件,因此我们可以使用时间运算符来评估新请求不与已确认的请求重叠(捕获为推断的“ Reservation”事实。

我们编写了以下规则来检查重叠部分并插入相应的“保留”事实:

rule "Ensure no overlaped reservations using inferred facts"
    enabled true

    when
        reservationRequest : ReservationRequest( )
        not Reservation ( reservation == reservationRequest )
        reservations : Reservation() 
        not ReservationRequest( this overlaps reservations.reservation )
        not ReservationRequest( this overlappedby reservations.reservation  )
        not ReservationRequest( this includes reservations.reservation  )
    then
        insert( new Reservation ( reservationRequest ) );
 end

不幸的是,如果WM中存在“保留”事实,则上述规则将无法运行。我收到以下错误:

  java.lang.RuntimeException: Conversion to long not supported from com.sample.ReservationRequest
    at org.drools.core.base.extractors.BaseObjectClassFieldReader.getLongValue(BaseObjectClassFieldReader.java:133)
    at org.drools.core.base.ClassFieldReader.getLongValue(ClassFieldReader.java:198)
    at org.drools.core.rule.VariableRestriction$TemporalVariableContextEntry.updateFromTuple(VariableRestriction.java:641)
    at org.drools.core.common.SingleBetaConstraints.updateFromTuple(SingleBetaConstraints.java:116)
    at org.drools.core.phreak.PhreakNotNode.doLeftInserts(PhreakNotNode.java:108)
    at org.drools.core.phreak.PhreakNotNode.doNode(PhreakNotNode.java:85)
    at org.drools.core.phreak.RuleNetworkEvaluator.switchOnDoBetaNode(RuleNetworkEvaluator.java:571)
    at org.drools.core.phreak.RuleNetworkEvaluator.evalBetaNode(RuleNetworkEvaluator.java:552)
    at org.drools.core.phreak.RuleNetworkEvaluator.evalNode(RuleNetworkEvaluator.java:379)
    at org.drools.core.phreak.RuleNetworkEvaluator.innerEval(RuleNetworkEvaluator.java:339)
    at org.drools.core.phreak.RuleNetworkEvaluator.outerEval(RuleNetworkEvaluator.java:175)
    at org.drools.core.phreak.RuleNetworkEvaluator.evaluateNetwork(RuleNetworkEvaluator.java:133)
    at org.drools.core.phreak.RuleExecutor.reEvaluateNetwork(RuleExecutor.java:212)
    at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:87)
    at org.drools.core.concurrent.AbstractRuleEvaluator.internalEvaluateAndFire(AbstractRuleEvaluator.java:34)
    at org.drools.core.concurrent.SequentialRuleEvaluator.evaluateAndFire(SequentialRuleEvaluator.java:43)
    at org.drools.core.common.DefaultAgenda.fireLoop(DefaultAgenda.java:1067)
    at org.drools.core.common.DefaultAgenda.internalFireAllRules(DefaultAgenda.java:1014)
    at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1006)
    at org.drools.core.impl.StatefulKnowledgeSessionImpl.internalFireAllRules(StatefulKnowledgeSessionImpl.java:1337)
    at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1328)
    at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1312)
    at com.sample.DroolsTest.main(DroolsTest.java:24)

在其他情况下,我们已广泛使用推断的事实,但这是我们第一次将其与事件一起使用。因此,我们不确定是否支持此功能(根据相关事件推断事实)。

如果不支持此功能,那么“保存”所需事件的最佳方法是什么,同时允许其他事件从WM撤出/撤回。我们可以使用“标志”标记要保留的事件,但如果可能的话,我们希望避免使用这种方法。

谢谢

2 个答案:

答案 0 :(得分:0)

我非常喜欢Drools,为什么不创建带有start_datetime和end_datetime以及“ before insert on”触发器的SQL表,该触发器检查插入的值是否不与任何现有(已确认)值重叠在数据库中。如果触发器在插入过程中引发异常,则可以捕获它,并且知道存在重叠。

答案 1 :(得分:0)

我建议在变量名称前添加$号,这样您可以更好地区分字段和变量。

如果将方法boolean isOverlap(ReservationRequest)添加到ReservationRequest类中,则可以编写如下内容:

when
    $reservationRequest : ReservationRequest( )
    not Reservation ( this.reservation.isOverlap($reservationRequest) )
then
    insert( new Reservation ( $reservationRequest ) );

这应该足够了。我还强烈建议您在引用ReservationRequest时使用变量名“ reservationRequest”,这非常令人困惑。