Как сделать доступ к файлу drools drl обновленным jar во время выполнения - PullRequest
3 голосов
/ 17 мая 2011

Недавно я работал над проектом drools, где столкнулся с определенными проблемами и мне нужна помощь.В моем проекте я получаю доступ к jar во время выполнения, используя URLClassLoader. Вот код:

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, который присутствует в директории файла и который обращается к тому же классу dynamicclasses.Billing, которыйприсутствует в Billing.jar

Вот содержимое файла 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.не может получить доступ к обновленному банку.

Следующие вещи, которые я пытаюсь сделать.

1) Я создам банку во время выполнения и обновлю ее при необходимости.2) Я создам файл drl во время выполнения, который будет импортировать класс, присутствующий в jar, т.е. dynamicclasses.Billing

Я могу получить доступ к обновленному содержимому jar в своем классе java с помощью URLClassLoader. Но как только я передамобъект моего класса 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());

Здесь я получаю то же исключение изначально.Но после перезапуска приложения оно работает нормально, и правило срабатывает, и я получу результат.

Но опять же, если я обновлю банку, он получит доступ только к предыдущему содержимому.

Так что егоПонятно, что файл drl не может получить доступ к банку изначально или даже после обновления.Есть ли способ, чтобы я мог заставить его работать?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 06 июня 2011

Спасибо :) Наконец-то я могу решить эту проблему. Вам нужно передать свой пользовательский загрузчик классов не только в 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 голос
/ 20 мая 2011

Вы можете попробовать передать загрузчик классов для KnowledgeBuilder с помощью KnowledgeBuilderConfiguration.

ClassLoader loader = new URLClassLoader(
    new URL[] { jarPath },
    ClassLoader.getSystemClassLoader());
KnowledgeBuilderConfiguration kBuilderConfiguration 
    = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(null, loader);
KnowledgeBuilder kbuilder 
    = KnowledgeBuilderFactory.newKnowledgeBuilder(kBuilderConfiguration);
0 голосов
/ 22 марта 2017

Для Drool 6.5.0, Class Loader может быть добавлен с помощью:

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);
...