首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Drools API混淆

Drools API混淆
EN

Stack Overflow用户
提问于 2018-01-18 15:07:34
回答 1查看 2.8K关注 0票数 3

我试图为我们从头构建的验证服务(通过Spring构建)评估JBoss Drools,但是我在理解和区分存在的多个API时遇到了一些困难。

我的第一次尝试是一种相当简单的方法,或多或少是直接从网络教程中获得的,但它起了作用。使用drools 6.0.1的单个依赖项,我可以使用以下代码获得一个RuleBase:

代码语言:javascript
复制
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是:

代码语言:javascript
复制
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的摘录,它已经比第一种方法要大得多,尽管我不确定我实际需要哪些库(这里的正式文档并不非常有用):

代码语言:javascript
复制
    <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实现这个功能的建议,并尝试了这一点:

代码语言:javascript
复制
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最喜欢的方法。

  • 是否有一种方法可以编程地使用Drools7.x构建类似于上面示例的KnowledgeBase?
  • 我应该使用哪个API?有非反对的图书馆吗?
  • 为了让项目运行,我实际上需要哪些依赖项?

我总是可以只使用第一个示例,但是更新的Drools不再可能这样做,我希望避免依赖旧库。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-18 15:54:07

这应该适用于7.x的任何Drools版本:

代码语言:javascript
复制
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最后一个类路径设置,基本类路径设置应该是这样(没有任何保证--作为指导原则):

代码语言:javascript
复制
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"
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48324384

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档