Add new rule file to an existing knowledge session

与世无争的帅哥 提交于 2019-12-11 03:42:45

问题


I want to add a new rule-file (or modify an already existing one) to an existing KieSession dynamically at runtime.

I found an answer regarding this and tried the solution mentioned there, but got a runtime exception.

The code used is as follows:

Driver.java:

package app1;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.Message;
import org.kie.api.builder.ReleaseId;
import org.kie.api.builder.Results;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class Driver {

  public static final void main(String[] args) {
    try {
      KieServices kieServices = KieServices.Factory.get();
      KieFileSystem kfs = kieServices.newKieFileSystem();

      String ruleFilePath = "src/main/resources/rules/ruleFile1.drl";
      FileInputStream fis = null;
      try {
        fis = new FileInputStream(ruleFilePath);
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      }
      kfs = kfs.write(ruleFilePath, kieServices.getResources().newInputStreamResource(fis));

      KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
      Results results = kieBuilder.getResults();
      if (results.hasMessages(Message.Level.ERROR)) {
        System.out.println("~~ERROR~~:");
        System.out.println(results.getMessages());
        throw new IllegalStateException("### errors ###");
      }

      ReleaseId releaseId1 = kieServices.newReleaseId("org.default", "artifact", "1.0.0-SNAPSHOT");
      KieContainer kieContainer = kieServices.newKieContainer(releaseId1);
      KieBase kieBase = kieContainer.newKieBase(kieServices.newKieBaseConfiguration());

      KieSession kSession = kieBase.newKieSession();
      String s = "hello";
      kSession.insert(s);
      kSession.fireAllRules();

      // I edit the rule file manually at this point.
      System.out.println("Waiting");
      Thread.sleep(5000);

      ReleaseId releaseId2 = kieServices.newReleaseId("org.default", "artifact", "1.0.1-SNAPSHOT");
      kieContainer.updateToVersion(releaseId2);
      kSession.fireAllRules();

      System.out.println("Bye");
    } catch (Throwable t) {
      t.printStackTrace();
    }
  }
}

ruleFile1.drl:

package app1;

rule "rule1"
when
    s: String()
then
    System.out.println("In rule - " + drools.getRule().getName());
    System.out.println("s = " + s);
end

The output I get is this:

In rule - rule1
s = hello
Waiting
java.lang.NullPointerException
  at org.drools.compiler.kie.util.ChangeSetBuilder.build(ChangeSetBuilder.java:53)
  at org.drools.compiler.kie.builder.impl.KieContainerImpl.update(KieContainerImpl.java:129)
  at org.drools.compiler.kie.builder.impl.KieContainerImpl.updateToVersion(KieContainerImpl.java:106)
  at app1.Driver.main(Driver.java:54)

I also read this code and noticed that it was using some code like this to add new rule-file dynamically to a KieSession:

KnowledgeBase kbase = SerializationHelper.serializeObject( loadKnowledgeBase( "test_Dynamic1.drl" ) );
Collection<KnowledgePackage> kpkgs = SerializationHelper.serializeObject( loadKnowledgePackages( "test_Dynamic2.drl" ) );
kbase.addKnowledgePackages(kpkgs);

but the problem is that KnowledgeBase is an internal API and not exposed to the end-users.

I am using Drools 6.2.0.

EDIT:

I've discovered that maybe KieScanner can be used to achieve what I want. But I am unable to find a proper example describing the use of KieScanner for either adding a new rule file or replacing an already existing one.

This answer contains some useful information, but I am not able to understand it properly. Also, I would prefer in-memory jars.

来源:https://stackoverflow.com/questions/40803008/add-new-rule-file-to-an-existing-knowledge-session

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!