最近我正在研究一个drools项目,我遇到了一些问题,我需要一些帮助。 在我的项目中,我通过使用URLClassLoader在运行时访问jar.Here是代码:
Object object=null;
Class myclass=null;
URL jarPath=null;
try{
jarPath=new File("lib/Billing.jar").toURI().toURL();
URLClassLoader loader = new URLClassLoader(new URL[] { jarPath },ClassLoader.getSystemClassLoader());
ruleclass = loader.loadClass("dynamicclasses.Billing");
object = ruleclass.newInstance();
}
catch (Exception e) {e.printStackTrace}
获取类实例后,我将设置值并将对象传递给我的drools类
new DroolsClass().fireRules(object);
drools类包含以下代码:
public class DroolsClass {
public void fireRules(Object object){
try {
KnowledgeBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
ksession.insert(object);
ksession.fireAllRules();
logger.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
private static KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newFileResource("./rulefiles/testing.drl"), ResourceType.DRL);
KnowledgeBuilderErrors errors = kbuilder.getErrors();
// ------ some code
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
return kbase;
}
接下来我有一个drl文件testing.drl,该文件存在于directoty文件中,它访问了Billing.jar中存在的相同类dynamicclasses.Billing
这是drl文件内容:
import dynamicclasses.Billing;
rule "rule 3"
salience 10
dialect "mvel"
no-loop true
when
m : Billing(bplan=="plan1")
then
System.out.println("You have opted for plan1");
end
我遇到的问题是jar,即Billing.jar在运行时更新drl文件,即testing.drl 无法访问更新的jar。
我正在努力做以下事情。
1)我将在运行时创建jar并在需要时更新它。 2)我将在运行时创建一个drl文件,它将导入jar中存在的类,即dynamicclasses.Billing
我可以使用URLClassLoader访问我的java类中更新的jar内容。但是一旦我将对象传递给我的drools类,我得到以下异常
Unable to resolve ObjectType 'Billing' : [Rule name='rule 3']
Error importing : 'dynamicclasses.Billing'
java.lang.IllegalArgumentException: Could not parse knowledge.
如果我重启我的应用程序,我没有异常,因为jar已经存在,但是对象似乎没有传递给drl而且我没有得到任何结果。
我对代码进行了以下更改:
URLClassLoader loader = new URLClassLoader(new URL[] { jarPath },this.getClass().getClassLoader());
这里我最初得到了同样的例外。但是在我重新启动我的应用程序之后它运行正常并且规则被触发了,我将得到结果。
但是,如果我更新jar,它将只访问以前的内容。
因此很清楚,drl文件无法在更新后进行初始访问。 有什么方法可以让它发挥作用吗?
感谢。
答案 0 :(得分:2)
谢谢:)最后我能够解决这个问题。您需要将自定义类加载器不仅传递给KnowledgeBuilderConfiguration,还要传递给KnowledgeBaseConfiguration,以使您的知识库能够了解您的自定义类加载器。
private static KnowledgeBase readKnowledgeBase(ClassLoader loader) throws Exception {
KnowledgeBuilderConfiguration kBuilderConfiguration = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(null, loader);
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(kBuilderConfiguration);
KnowledgeBaseConfiguration kbaseConfig = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(null, loader);
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;
}
答案 1 :(得分:1)
您可以尝试使用KnowledgeBuilderConfiguration传递KnowledgeBuilder的类加载器。
ClassLoader loader = new URLClassLoader(
new URL[] { jarPath },
ClassLoader.getSystemClassLoader());
KnowledgeBuilderConfiguration kBuilderConfiguration
= KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(null, loader);
KnowledgeBuilder kbuilder
= KnowledgeBuilderFactory.newKnowledgeBuilder(kBuilderConfiguration);
答案 2 :(得分:0)
对于Drool 6.5.0,可以通过以下方式添加类加载器:
kieServices = KieServices.Factory.get();
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
kieFileSystem.write("./rulefiles/testing.drl", drl);
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem, loader);
kieBuilder.buildAll();
KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId(),
pluginCtxObject.getClass().getClassLoader());
StatelessKieSession statelessKieSession = kieContainer.getKieBase().newStatelessKieSession();
statelessKieSession.execute(object);