0

我是 Drools 应用程序的新手,尤其是 Drools fusion。在我的办公室里,我们正在开发一个独立的复杂事件处理应用程序。主要要求之一是计算每个事件的开始时间、频率、结束时间、持续时间的可能性。我们正在测试 Drools Fusion 这样做,我们制作了这个不起作用的例子。在此示例中,我们尝试计算持续时间。作为旁注,我们无法计算事件时间戳,现在我们使用 System.currentTimeMillis() 解决。

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

示例.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;
        }

    }

}
4

1 回答 1

3

I think there are a few misconceptions in your use of Drools Fusion. I will try to clarify a few of them:

  • I am not sure what you mean by "calculate starting time, frequency, end time, duration of each event". CEP products in general allow an application to listen to events, detect patterns by matching those events and correlating them and other data, and react when those patterns are detected. So, you can detect events and calculate their frequency, but starting time, duration (and end time) are part of the events themselves, not something the engine comes up with. Of course the engine can correlate atomic events into complex events and in this case it will assign things like duration to the complex event, but it is still application logic, not the engine doing magic.

  • Drools works in two modes: batch (called CLOUD mode, as in cloud of events) and real time mode (called STREAM mode, as in streams of events). Time flow only makes sense in STREAM (real time) mode. You commented out the configuration of the STREAM mode, and so everything you are doing with a clock in your application is ignored:

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

  • Your code is configuring the engine to use the pseudo-clock, but you are using the machine clock to assign timestamps to your events with System.currentTimeMillis(). Your application needs to be consistent: either you use a real time clock or you use the pseudo-clock.

  • Minor fix: you should use the public interface SessionPseudoClock instead of the internal implementation class PseudoClockScheduler. Same thing with the internal class EventFactHandle that I assume you are using just for the test as your application should never need to use that.

  • Finally, I am not sure what you are trying to achieve with this example. Your message class timestamp and duration will be read from the class attributes as your example tells the engine to:

    declare Message @role(event) @timestamp(time) @duration(howMuch) end

Drools will not deliberately change attributes (like howMuch) if that is what you were expecting.

I suggest you take another look at the Drools Fusion documentation and join the Drools mailing list. People are very helpful there and can help you with any follow up questions you might have.

于 2012-02-15T18:53:32.233 回答