我是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;
}
}
}
答案 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之类的其他功能。