我想向现有的规则文件添加一个新的规则文件(或修改现有的规则文件)KieSession
在运行时动态地。
我找到了一个answer https://stackoverflow.com/a/22208775/1925388关于这一点并尝试了那里提到的解决方案,但遇到了运行时异常。
使用的代码如下:
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
我得到的输出是这样的:
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)
我也读过这段代码 https://github.com/droolsjbpm/drools/blob/master/drools-compiler/src/test/java/org/drools/compiler/integrationtests/DynamicRulesTest.java并注意到它正在使用类似这样的代码将新的规则文件动态添加到KieSession
:
KnowledgeBase kbase = SerializationHelper.serializeObject( loadKnowledgeBase( "test_Dynamic1.drl" ) );
Collection<KnowledgePackage> kpkgs = SerializationHelper.serializeObject( loadKnowledgePackages( "test_Dynamic2.drl" ) );
kbase.addKnowledgePackages(kpkgs);
但问题是KnowledgeBase
是内部 API,不向最终用户公开。
我正在使用 Drools 6.2.0。
EDIT:
我发现也许KieScanner
可以用来实现我想要的。
但我无法找到描述使用的正确示例KieScanner
用于添加新的规则文件或替换现有的规则文件。
这个答案 https://stackoverflow.com/a/38530777/1925388包含一些有用的信息,但我无法正确理解它。另外,我更喜欢内存罐子。