KnowledgeAgent可以用于自动将知识库写入文件,以便可以在外部使用吗?

时间:2013-02-08 09:31:58

标签: serialization resources drools knowledge-management guvnor

我正在一个小小的工作项目工作,我有以下问题:

  - 当我通过知识代理从drools读取知识包时,需要很长时间才能加载
((现在我知道构建知识库一般,特别是当从guvnor加载包时非常激烈))

  • 所以我试图将知识库序列化到位于系统本地的文件上 - 一方面是因为从本地文件加载kBase要快得多 - 另一方面,我可以将知识库用于其他应用程序。问题是,在第一次使用KnowledgeAgent加载知识库时,代理会自动更新基础。
    但是:当Base更新时,我的本地文件也不会更新 所以我想知道如何从KnowledgeAgent处理/获取changeNotification,以便我可以调用一个方法来序列化我的知识库?


    这有可能吗?基本上我只是想更新我的本地知识库文件,每当有人在州长编辑规则时,我的本地文件总是最新的。


    如果不可能,或者一个非常糟糕的解决方案,建议/最好的方法是什么?


    请忍受我的英语和问题本身,如果你不能真正弄清楚我想要完成什么,或者我的请求实际上不是一个好的解决方案,或者问题本身是多余的,对于java而言,这是一个相当新的问题,当涉及到滴料。

下面是代码:

public class 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;
 }

}


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

1 个答案:

答案 0 :(得分: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()),而不是您应用中的引用。

希望它有所帮助,