流口水 API 混乱
Drools API confusion
我正在尝试评估 JBoss Drools 以用于我们从头开始构建的验证服务(通过 Spring Boot),但我在理解和区分多个 API 存在。
我的第一次尝试是一种相当简单的方法,或多或少直接从网络教程中获取,但它奏效了。使用 drools-core 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),然后插入对象并触发我的规则。
然而,我已经读到 here 这种方法似乎已被弃用,而且我不想将过时版本的 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>
当我使用其他实现时,我的知识库被标记为已弃用,这似乎是一个明显的提示,不再使用它。
然后我发现了另一个关于如何使用 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 的依赖项。但是,我似乎仍在使用已弃用的库来构建我的 KnowledgeBase/KieBase/RuleBase。此外,API 似乎随着每次迭代变得越来越冗长。
问题是,我需要对上面的代码做些什么或进行哪些更改才能让它与 Drools 7 一起工作? API 似乎已经完全改变了,我宁愿不在我的 META-INF 中使用 kmodule.xml 文件,这似乎是 JBoss 最喜欢的方法。
- 有没有办法以编程方式构建我的知识库,类似于我上面使用 Drools 的示例 7.x?
- 我应该使用哪个 API?是否有任何未弃用的库?
- 为了使项目达到 运行,我实际需要哪些依赖项?
我总是可以只使用第一个示例,但是对于较新的 Drools APIs 来说这不再可能了,我想避免依赖旧库。
这应该适用于 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 Final,基本的类路径设置如下(没有任何保证 - 仅作为指南):
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"
我正在尝试评估 JBoss Drools 以用于我们从头开始构建的验证服务(通过 Spring Boot),但我在理解和区分多个 API 存在。
我的第一次尝试是一种相当简单的方法,或多或少直接从网络教程中获取,但它奏效了。使用 drools-core 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),然后插入对象并触发我的规则。 然而,我已经读到 here 这种方法似乎已被弃用,而且我不想将过时版本的 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>
当我使用其他实现时,我的知识库被标记为已弃用,这似乎是一个明显的提示,不再使用它。 然后我发现了另一个关于如何使用 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 的依赖项。但是,我似乎仍在使用已弃用的库来构建我的 KnowledgeBase/KieBase/RuleBase。此外,API 似乎随着每次迭代变得越来越冗长。
问题是,我需要对上面的代码做些什么或进行哪些更改才能让它与 Drools 7 一起工作? API 似乎已经完全改变了,我宁愿不在我的 META-INF 中使用 kmodule.xml 文件,这似乎是 JBoss 最喜欢的方法。
- 有没有办法以编程方式构建我的知识库,类似于我上面使用 Drools 的示例 7.x?
- 我应该使用哪个 API?是否有任何未弃用的库?
- 为了使项目达到 运行,我实际需要哪些依赖项?
我总是可以只使用第一个示例,但是对于较新的 Drools APIs 来说这不再可能了,我想避免依赖旧库。
这应该适用于 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 Final,基本的类路径设置如下(没有任何保证 - 仅作为指南):
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"