Drools Fusion持续时间和时间戳,为什么它不起作用?

时间:2012-02-15 15:49:29

标签: java jboss drools drools-fusion event-stream

我是Drools应用程序的新手,最重要的是Drools融合。在我的办公室,我们正在开发一个独立的复杂事件处理应用程序。主要要求之一是计算每个事件的开始时间,频率,结束时间和持续时间的可能性。我们正在测试Drools Fusion这样做,我们做了这个不起作用的例子。在这个例子中,我们尝试计算持续时间。另外,我们无法计算事件时间戳,现在我们使用System.currentTimeMillis()解决了这个问题。

也许Drools不是一个好的框架,我们必须改变我们的选择?

Sample.drl

import it.ipiu.other.SElDroolsTest.Message;
declare Message
 @role(event)
 @timestamp(time)
 @duration(howMuch)
end

rule "Message"
    when
        Message() from entry-point "entry"
    then
        System.out.println("a message!!!");
end

和示例类

package it.ipiu.other;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseConfiguration;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.common.EventFactHandle;
import org.drools.conf.EventProcessingOption;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.KnowledgeSessionConfiguration;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.conf.ClockTypeOption;
import org.drools.runtime.rule.FactHandle;
import org.drools.runtime.rule.WorkingMemoryEntryPoint;
import org.drools.time.SessionClock;
import org.drools.time.impl.PseudoClockScheduler;

/**
 * This is a sample class to launch a rule.
 */
public class SElDroolsTest {

    public static final void main(String[] args) {
        try {
            // load up the knowledge base
            KnowledgeBase kbase = readKnowledgeBase();
            KnowledgeSessionConfiguration sessionConfiguration = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
            sessionConfiguration.setOption(ClockTypeOption.get("pseudo"));

            StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(sessionConfiguration, null);
            KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");

            PseudoClockScheduler sessionClock = ksession.getSessionClock(); // !!!
            // go !
            Message message = new Message();
            message.setMessage("Hello World");
            message.setStatus(Message.HELLO);
            message.setTime(System.currentTimeMillis());

            WorkingMemoryEntryPoint entryPoint = ksession.getWorkingMemoryEntryPoint("entry");

            sessionClock.advanceTime(1, TimeUnit.HOURS);

            EventFactHandle factHandle = (EventFactHandle) entryPoint.insert(message);

            sessionClock.advanceTime(1, TimeUnit.HOURS);

            int fireAllRules = ksession.fireAllRules();
            System.out.println("FACT : startTimeStamp " +  factHandle.getStartTimestamp());
            System.out.println("FACT : duration " +  factHandle.getDuration());
            System.out.println("FIRED : " + fireAllRules);
            System.out.println("TIME STAMP " + message.getTime()); 
            System.out.println("TIME DURATION " + message.getHowMuch()); 
            logger.close();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    private static KnowledgeBase readKnowledgeBase() throws Exception {
        KnowledgeBaseConfiguration configuration = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
        configuration.setOption(EventProcessingOption.STREAM);
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newClassPathResource("Sample.drl"), ResourceType.DRL);
        KnowledgeBuilderErrors errors = kbuilder.getErrors();
        if (errors.size() > 0) {
            for (KnowledgeBuilderError error : errors) {
                System.err.println(error);
            }
            throw new IllegalArgumentException("Could not parse knowledge.");
        }

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(/*configuration*/);
        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
        return kbase;
    }

    public static class Message {

        public static final int HELLO = 0;
        public static final int GOODBYE = 1;
        private Long time = new Long(0);
        private Long howMuch = new Long(0);


        public Long getHowMuch() {
            return howMuch;
        }

        public void setHowMuch(Long howMuch) {
            this.howMuch = howMuch;
        }

        public Long getTime() {
            return time;
        }

        public void setTime(Long time) {
            this.time = time;
        }

        private String message;

        private int status;

        public String getMessage() {
            return this.message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public int getStatus() {
            return this.status;
        }

        public void setStatus(int status) {
            this.status = status;
        }

    }

}

2 个答案:

答案 0 :(得分:3)

我认为您在使用Drools Fusion时存在一些误解。我将尝试澄清其中一些:

  • 我不确定你的意思是“计算每个事件的开始时间,频率,结束时间,持续时间”。 CEP产品通常允许应用程序监听事件,通过匹配这些事件并将它们与其他数据相关联来检测模式,并在检测到这些模式时做出反应。因此,您可以检测事件并计算其频率,但开始时间,持续时间(和结束时间)是事件本身的一部分,而不是引擎提出的事件。当然,引擎可以将原子事件关联到复杂的事件中,在这种情况下,它会为复杂事件分配持续时间等内容,但它仍然是应用程序逻辑,而不是引擎做魔术。

  • Drools以两种模式工作:批处理(称为CLOUD模式,如事件云)和实时模式(称为STREAM模式,如事件流)。时间流仅在STREAM(实时)模式下有意义。您注释掉了STREAM模式的配置,因此您在应用程序中使用时钟执行的所有操作都将被忽略:

    KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(/ configuration /);

  • 您的代码正在配置引擎以使用伪时钟,但您正在使用计算机时钟为System.currentTimeMillis()的事件分配时间戳。您的应用程序需要保持一致:要么使用实时时钟,要么使用伪时钟。

  • 次要修复:您应该使用公共接口SessionPseudoClock而不是内部实现类PseudoClockScheduler。内部类EventFactHandle也是如此,我假设您只是用于测试,因为您的应用程序永远不需要使用它。

  • 最后,我不确定您要通过此示例尝试实现的目标。您的消息类时间戳和持续时间将从类属性中读取,因为您的示例告诉引擎:

    声明消息     @Role(事件)     @timestamp(时间)     @duration(howMuch) 端

Drools不会故意改变属性(如howMuch),如果这是你期望的那样。

我建议您再看看Drools Fusion文档并加入Drools邮件列表。人们在那里非常有帮助,可以帮助您解决任何可能的后续问题。

答案 1 :(得分:0)

自1979年以来有关规则,速率算法和AI的论文以来,Drools似乎被设计为计算机的实现。这就是为什么有许多功能可以反映不同应用领域的原因。尝试选择最适合您的需求。
所描述的需求可以通过顺序逻辑事件(描述当前系统状态的事实)来实现。

使用stateful session是因为您需要会话来反映系统状态。
使用steam processing mode是因为您需要时间观念。

考虑rule.drl中的电话示例
还有junit test,反映了逻辑规范

如果需要events,请使用temporal reasoning之类的其他功能。