0

我正在做一个小小的drools项目,我遇到了以下问题:

-当我通过knowledgeAgent从drools读取知识包时,加载需要很长时间
((现在我知道一般来说构建知识库,尤其是在从guvnor非常激烈))

  • 所以我试图将知识库序列化为位于系统本地的文件
    - 一方面因为从本地文件加载 kBase 要快得多
    - 另一方面,我可以将知识库用于其他应用程序
    的问题是,在第一次使用知识代理加载知识库时,代理会自动更新

    基础但是:当基础更新时,我的本地文件也不会更新
    所以我想知道如何从我的 KnowledgeAgent 处理/获取 changeNotification 以便我可以调用一个方法来序列化我的 KnowledgeBase ?


    这有可能吗?基本上我只想更新我的本地知识库文件,每次有人在州长中编辑规则,以便我的本地文件始终是最新的。


    如果这是不可能的,或者一开始是一个非常糟糕的解决方案,那么推荐/最好的方法是什么?


    请忍受我的英语和问题本身,如果你不能真正弄清楚我想要完成什么,或者我的要求实际上不是一个好的解决方案,或者问题本身是多余的,我对 java 相当陌生,而且在谈到流口水。

下面是代码:

公共类 DroolsConnection {

private static KnowledgeAgent kAgent;
private static KnowledgeBase  kAgentBase;

public DroolsConnection(){
     ResourceFactory.getResourceChangeNotifierService().start();
     ResourceFactory.getResourceChangeScannerService() .start();

} 

public KnowledgeBase readKnowledgeBase( ) throws Exception {

     kAgent     = KnowledgeAgentFactory.newKnowledgeAgent("guvnorAgent");
     kAgent      .applyChangeSet( ResourceFactory.newFileResource(CHANGESET_PATH));
     kAgent.monitorResourceChangeEvents(true);

     kAgentBase = kAgent.getKnowledgeBase();
     serializeKnowledgeBase(kAgentBase);
     return kAgentBase;

   }


 public List<EvaluationObject> runAgainstRules( List<EvaluationObject> objectsToEvaluate,
                                                KnowledgeBase kBase ) throws Exception{

    StatefulKnowledgeSession knowSession = kBase.newStatefulKnowledgeSession();
    KnowledgeRuntimeLogger knowLogger    = KnowledgeRuntimeLoggerFactory.newFileLogger(knowSession, "logger");

    for ( EvaluationObject o : objectsToEvaluate ){
        knowSession.insert( o );
    }

    knowSession.fireAllRules();
    knowLogger .close();
    knowSession.dispose();
    return objectsToEvaluate;
 }


 public KnowledgeBase serializeKnowledgeBase(KnowledgeBase kBase) throws IOException{

        OutputStream outStream = new FileOutputStream( SERIALIZE_BASE_PATH );
        ObjectOutputStream oos = new ObjectOutputStream( outStream );
        oos.writeObject        ( kBase );
        oos.close();
        return kBase;
 }


 public KnowledgeBase loadFromSerializedKnowledgeBase() throws Exception {

        KnowledgeBase kBase   = KnowledgeBaseFactory.newKnowledgeBase(); 
        InputStream is        = new FileInputStream( SERIALIZE_BASE_PATH );
        ObjectInputStream ois = new ObjectInputStream( is );
        kBase                 = (KnowledgeBase) ois.readObject();
        ois.close();
        return kBase;
 }

}


提前感谢您的帮助!
最好的问候,
马连科

4

1 回答 1

0

为了保持本地 kbase 更新,您可以使用 KnowledgeAgentEventListener 来了解其内部 kbase 何时更新:

    kagent.addEventListener( new KnowledgeAgentEventListener() {

        public void beforeChangeSetApplied(BeforeChangeSetAppliedEvent event) {
        }

        public synchronized void afterChangeSetApplied(AfterChangeSetAppliedEvent event) {
        }

        public void beforeChangeSetProcessed(BeforeChangeSetProcessedEvent event) {
        }

        public void afterChangeSetProcessed(AfterChangeSetProcessedEvent event) {
        }

        public void beforeResourceProcessed(BeforeResourceProcessedEvent event) {
        }

        public void afterResourceProcessed(AfterResourceProcessedEvent event) {
        }

        public void knowledgeBaseUpdated(KnowledgeBaseUpdatedEvent event) {
            //THIS IS THE EVENT YOU ARE INTERESTED IN 
        }

        public void resourceCompilationFailed(ResourceCompilationFailedEvent event) {               
        }
    } );

不过,您仍然需要处理本地 kbase 上的并发访问。

顺便说一句,由于您没有使用“newInstance”配置选项,因此每次应用变更集时,代理都会创建一个新的 kbase 实例。因此,请确保序列化 kagent 的内部 kbase (kagent.getKnowledgeBase()),而不是应用程序中的引用。

希望能帮助到你,

于 2013-02-09T11:01:57.590 回答