我试图为我们从头构建的验证服务(通过Spring构建)评估JBoss Drools,但是我在理解和区分存在的多个API时遇到了一些困难。
我的第一次尝试是一种相当简单的方法,或多或少是直接从网络教程中获得的,但它起了作用。使用drools 6.0.1的单个依赖项,我可以使用以下代码获得一个RuleBase:
public static RuleBase readRule(String ruleFile) throws Exception {
// read in the source
Reader source = new InputStreamReader(RuleUtils.class.getClassLoader().getResourceAsStream("rules/" + ruleFile));
PackageBuilder builder = new PackageBuilder();
// this will parse and compile in one step
builder.addPackageFromDrl(source);
//check for errors
if (builder.hasErrors()) {
System.out.println(builder.getErrors().toString());
}
// get the compiled package (which is serializable)
Package pkg = builder.getPackage();
// add the package to a rulebase (deploy the rule package).
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage(pkg);
return ruleBase;
}使用该RuleBase,我可以创建一个新的有状态会话(WorkingMemory),然后插入对象并触发规则。然而,我读过这里,这种方法似乎是不可取的,而且我也不希望在一个闪亮的新项目中使用过时的Drools版本(6.0.1相对于当前的7.5.0版本)。
在许多教程中非常常见的另一个API是:
public static RuleBase readRule(String ruleFile) throws Exception {
// read in the source
Reader source = new InputStreamReader(RuleUtils.class.getClassLoader().getResourceAsStream("rules/" + ruleFile));
KnowledgeBuilder kBuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
// this will parse and compile in one step
kBuilder.add(ResourceFactory.newReaderResource(source), ResourceType.DRL);
//check for errors
if (kBuilder.hasErrors()) {
System.out.println(kBuilder.getErrors().toString());
}
// get the compiled package (which is serializable)
Collection<KnowledgePackage> pkgs = kBuilder.getKnowledgePackages();
// add the package to a rulebase (deploy the rule package).
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(pkgs);
return kbase;
}但这就是混乱开始的地方。所有这些类似乎都可以在两个单独的库(org.drools和org.kie.internal)中使用。使用org.drools,我无法让上面的代码工作--我总是有一个java.lang.ClassNotFoundException: org.drools.builder.impl.KnowledgeBuilderFactoryServiceImpl --我不知道我可能错过了哪个库。这是我的pom.xml的摘录,它已经比第一种方法要大得多,尽管我不确定我实际需要哪些库(这里的正式文档并不非常有用):
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-api</artifactId>
<version>5.1.1</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-internal</artifactId>
<version>7.5.0.Final</version>
</dependency>当我使用其他实现时,我的KnowledgeBase被标记为弃用,这似乎是不再使用该实现的一个明显提示。然后,我发现了另一个关于如何使用Drools 6.x实现这个功能的建议,并尝试了这一点:
public static KieBase readRuleKie(String ruleFile) throws Exception {
// read in the source
Reader source = new InputStreamReader(RuleUtils.class.getClassLoader().getResourceAsStream("rules/" + ruleFile));
// Get access to Drools services
KieServices services = KieServices.Factory.get();
// Obtain a new empty virtual file system
KieFileSystem fileSystem = services.newKieFileSystem();
// Load a DRL resource from src/main/resources into the virtual file system
String location = "/rules/" + ruleFile;
InputStream stream = RuleUtils.class.getClassLoader().getResourceAsStream("rules/" + ruleFile);
Resource resource = ResourceFactory.newInputStreamResource(stream);
fileSystem.write("src/main/resources" + location, resource);
// Convert the files in the virtual file system into a builder
KieBuilder builder = services.newKieBuilder(fileSystem).buildAll();
// Check for errors, print them and stop if any
Results results = builder.getResults();
if (results.hasMessages(Message.Level.ERROR)) {
System.out.println(results.getMessages());
}
// Create a new kie base out of a repository and a container
KieRepository repository = services.getRepository();
KieContainer container = services.newKieContainer(repository.getDefaultReleaseId());
KieBase base = container.getKieBase();
return base;
}现在,这实际上起作用了,但在我的项目中添加1.4.10版本中的XStream依赖项之前,情况并非如此。但是,我似乎在使用废弃的库来构建我的知识库/KieBase/RuleBase。而且,随着每次迭代,API似乎变得越来越冗长。
问题是,我需要做什么或者修改上面的代码,这样我就可以让它使用Drools 7了?API似乎已经完全改变了,我不希望在元INF中使用kmodule.xml文件,这似乎是JBoss最喜欢的方法。
我总是可以只使用第一个示例,但是更新的Drools不再可能这样做,我希望避免依赖旧库。
发布于 2018-01-18 15:54:07
这应该适用于7.x的任何Drools版本:
private KieSession kieSession;
public void build() throws Exception {
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = kieServices.newKieFileSystem();
FileInputStream fis = new FileInputStream( "simple/simple.drl" );
kfs.write( "src/main/resources/simple.drl",
kieServices.getResources().newInputStreamResource( fis ) );
KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ).buildAll();
Results results = kieBuilder.getResults();
if( results.hasMessages( Message.Level.ERROR ) ){
System.out.println( results.getMessages() );
throw new IllegalStateException( "### errors ###" );
}
KieContainer kieContainer =
kieServices.newKieContainer( kieServices.getRepository().getDefaultReleaseId() );
KieBase kieBase = kieContainer.getKieBase();
kieSession = kieBase.newKieSession();
}考虑到您需要选择将多个资源加载到kfs中,需要一个可以响应错误并需要序列化创建的KieBase的机会的点,这并不是很糟糕。
至于库,请检查分发包包含哪些内容并进行相应的操作。对于7.3.0最后一个类路径设置,基本类路径设置应该是这样(没有任何保证--作为指导原则):
root=/extra/drools-distribution-7.3.0.Final/binaries
tag=7.3.0.Final
export CLASSPATH=".:$root/drools-core-${tag}.jar:$root/kie-api-${tag}.jar:$root/kie-internal-${tag}.jar:$root/knowledge-internal-api-${tag}.jar:$root/drools-compiler-${tag}.jar:$root/antlr-runtime-3.5.2.jar:$root/ecj-4.4.2.jar:$root/mvel2-2.3.0.Final.jar:/extra/quartz-1.8.3/quartz-1.8.3.jar:$root/drools-decisiontables-${tag}.jar:$root/drools-templates-${tag}.jar:$root/protobuf-java-2.6.0.jar:$root/slf4j-api-1.7.7.jar:$root/xstream-1.4.9.jar:$SLF4J"https://stackoverflow.com/questions/48324384
复制相似问题