【问题标题】:DRL not resolve dynamically loaded classDRL 无法解析动态加载的类
【发布时间】:2014-09-04 05:22:40
【问题描述】:

我正在使用 drools 6 包为我的应用程序构建和运行 drl 文件。它与静态类一起工作正常。但是,当我在规则中使用动态类时,它会抛出错误

规则编译错误:[Rule name='rule 1'] com/sample/Rule_rule_11982550347.java (2:28) :只能导入一个类型。 com.chainsys.csapp.dynaclass.vo.SupplierdivVO 解析为一个包

即使我已经在知识库中加载了我的类加载器。以下是我的代码。

package com.echain.handler;

import java.sql.SQLException;
import java.util.List;

import org.kie.api.KieBaseConfiguration;
import org.kie.api.KieServices;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.KnowledgeBase;
import org.kie.internal.KnowledgeBaseFactory;
import org.kie.internal.builder.KnowledgeBuilder;
import org.kie.internal.builder.KnowledgeBuilderConfiguration;
import org.kie.internal.builder.KnowledgeBuilderError;
import org.kie.internal.builder.KnowledgeBuilderErrors;
import org.kie.internal.builder.KnowledgeBuilderFactory;
import org.kie.internal.io.ResourceFactory;

import com.chainsys.dynui.handler.DynamicFormHandler;
import com.chainsys.dynui.vo.PageEntityVO;
import com.chainsys.dynui.vo.PageInfoVO;
import com.chainsys.fwk.exception.BaseFrameworkException;
import com.chainsys.fwk.util.ChainsysReflection;
import com.chainsys.fwk.util.DynamicClassLoader;
import com.echain.vo.Message;

public class Testing {

public static void main(String[] args) throws Exception {
    // TODO Auto-generated method stub
    Testing test = new Testing();
    test.fire();
}

@SuppressWarnings("deprecation")
private void fire() throws Exception {
    DynamicClassLoader loader = getClassLoader("Supplier");
    KnowledgeBase kBase = readKnowledgeBase(loader);
    KieSession kSession = kBase.newKieSession();
    KieServices kService = KieServices.Factory.get();

    kSession.setGlobal("out", System.out);

    kSession.insert(createMessage(kService.getKieClasspathContainer(loader)));
    kSession.insert(new Message("Pravin", "Hi"));
    kSession.fireAllRules();
    kSession.dispose();

}

public KnowledgeBase readKnowledgeBase(ClassLoader loader) throws Exception {

    KnowledgeBuilderConfiguration kBuilderConfiguration =
        KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(null, loader);
    System.out.println(kBuilderConfiguration);
    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(kBuilderConfiguration);

    KieBaseConfiguration kbaseConfig = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(null, loader);

    kbuilder.add(ResourceFactory.newByteArrayResource(getRule().getBytes()), ResourceType.DRL);
    // kbuilder.add(ResourceFactory.newFileResource("./rulefiles/testing.drl"), ResourceType.DRL);
    KnowledgeBuilderErrors errors = kbuilder.getErrors();

    if (errors.size() > 0) {
        for (KnowledgeBuilderError error : errors)
            System.err.println(error);
        throw new IllegalArgumentException("Could not parse knowledge.");
    }

    KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(kbaseConfig);
    kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
    return kbase;
}

private String getRule() {
    StringBuffer ruleContent = new StringBuffer();
    ruleContent.append("package com.sample\n\n");
    ruleContent.append("import com.chainsys.csapp.dynaclass.vo.SupplierdivVO;\n\n");
    ruleContent.append("import com.echain.vo.Message\n\n");
    ruleContent.append("global java.io.PrintStream out \n\n");
    ruleContent.append("rule \"rule 1\" when \n");
    ruleContent.append(" m : Message( ) \n");// SupplierdivVO(test1==\"welc\")
    ruleContent.append("then \n");
    ruleContent.append("out.println(\"hello\");");
    ruleContent.append("end\n");
    return ruleContent.toString();
}

private Object createMessage(KieContainer kContainer) {
    Object o = null;
    try {
        Class<?> cl = kContainer.getClassLoader().loadClass("com.chainsys.csapp.dynaclass.vo.SupplierdivVO");
        o = cl.newInstance();
        ChainsysReflection.setProperty(o, "test1", "welc");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return o;
}

public DynamicClassLoader getClassLoader(String pageName) throws BaseFrameworkException, SQLException,
    ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException {

    DynamicFormHandler handler = new DynamicFormHandler();
    PageInfoVO infoVO = handler.getPageInfoVO(pageName, 1);

    List<PageEntityVO> eVO = infoVO.getPageEntityList();

    DynamicClassLoader classLoader = new DynamicClassLoader(eVO);

    return classLoader;
}

}

【问题讨论】:

  • 我希望您的课程 SupplierDivVO 是公开的。您也可以尝试将类文件保存在同一个包中,即 com.echain.handler
  • 感谢@jsjunkie。实际上我正在尝试使用仅在运行时可用的动态类。所以我使用自定义类加载器到知识库配置。上面的代码将适用于静态类。
  • 可能我还没有弄清楚,但我认为您正在 getRule() 方法中创建动态类,该方法又会导入 SupplierDivVO。我想有类加载器问题。你可以用 Class.forname() 加载你的类而不是导入吗?如果您找到解决方案,请告诉我们任何情况。
  • 也许尝试将对象转换为“消息”?

标签: java drools dynamic-class-loaders


【解决方案1】:

始终传递用于创建知识库的 URL 类加载器。因为 drools 会将 URL 类加载器类加载到它的工作内存中。

  public KnowledgeBase newKBase(URLClassLoader loader) {

    KnowledgeBuilderConfiguration kbuilderConfig =
        KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(null, loader);
    // Create the agent using the builder configuration
    KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
    KnowledgeBaseConfiguration kbaseConfig = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(null, loader);
    KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(kbaseConfig);
    KnowledgeAgent kagent =
        KnowledgeAgentFactory.newKnowledgeAgent(knowledgeAgentName, kbase, aconf, kbuilderConfig);
    kbase = kagent.getKnowledgeBase();
    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(kbuilderConfig);

    addRules(kbuilder);
    KnowledgeBuilderErrors errors = kbuilder.getErrors();

    if (errors.size() > 0) {
        for (KnowledgeBuilderError error : errors)
            System.err.println(error);
        throw new IllegalArgumentException("Could not parse knowledge.");
    }

    kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());

    return kbase;
}

上述方法将加载规则而不会抛出错误。

【讨论】:

  • KnowledgeAgent 在 Drools 7 及以后版本中不存在。 Drools 7.12.0 是否有上述等效项?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-28
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
相关资源
最近更新 更多