Как динамически перезагрузить правила, используя уже объявленные типы фактов? - PullRequest
0 голосов
/ 16 августа 2011

Я столкнулся с проблемой при попытке перезагрузить правила динамически.Начнем с контекста: у нас есть файлы DRL, которые содержат в общей сложности 10000 правил и различных типов.Поскольку процесс компиляции и повторного развертывания правил начинает длиться долго (более пары минут), мы хотели бы скомпилировать и повторно развернуть ТОЛЬКО измененное правило.

Чтобы быть DRL-совместимым, мы должны объявитьв DRL для повторного развертывания измененного правила И всех используемых типов.

Наша проблема заключается в том, что типы, объявленные в новом DRL, не объединяются с уже развернутыми типами, поэтому новые правила не активируются при сопоставлении этих типов.

При просмотре объекта ReteoRuleBase я обнаружил, что список TypeDeclaration содержит два класса с именем «Item», и именно поэтому правило перед развертыванием не соответствует нужному объекту.

Во-первых, моймодульный тест, раскрывающий способ развертывания и повторного развертывания:

    @Test
public void test_hot_deploy() throws FileNotFoundException {
    File drl1 = new File("src/test/resources/essai-drools/hot-deploy-1.drl"); 
    Resource resource1 = ResourceFactory.newInputStreamResource(new FileInputStream(drl1));

    File drl2 = new File("src/test/resources/essai-drools/hot-deploy-2.drl"); 
    Resource resource2 = ResourceFactory.newInputStreamResource(new FileInputStream(drl2));

    KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    builder.add(resource1, ResourceType.DRL);
    KnowledgeBase kb = builder.newKnowledgeBase();
    StatefulKnowledgeSession session = kb.newStatefulKnowledgeSession();
    int fired = session.fireAllRules();
    Assert.assertEquals(2, fired);

            System.out.println("--- redeploy ---");

    KnowledgeBuilder builder2 = KnowledgeBuilderFactory.newKnowledgeBuilder();
    builder2.add(resource2, ResourceType.DRL);
    kb.addKnowledgePackages(builder2.getKnowledgePackages());

    session = kb.newStatefulKnowledgeSession();
    fired = session.fireAllRules();
    Assert.assertEquals(2, fired);
}

Исходный DRL (первый развернутый):

package test;
declare Item
value : String
end
rule "insertion"
when
then
    Item $item = new Item();
    $item.setValue("A");
    insert($item);
    System.out.println("Object A inserted");
end
rule "modification"
when    
    $item: Item(value == "A")
then
    $item.setValue("B");
    update($item);
    System.out.println("Object A -> B");
end

Повторно развернутый DRL:

package test;
declare Item
    value : String
end
rule "modification"
when    
    $item : Item(value == "A")
then
    $item.setValue("C");
    update($item);
    System.out.println("Object A -> C");
end

Вывод:

Object A inserted
Object A -> B
--- redeploy ---
Object A inserted

Отсутствующий вывод (как вы видите, правило повторного развертывания не было выполнено)

Object A -> C

Любое представление о том, как мы могли бы справиться с этимтипа, которые не сливаются?

Надеюсь, у вас есть идея, я здесь для простой информации.

1 Ответ

1 голос
/ 01 сентября 2011

Начиная с версии 5.2, Drools не поддерживает повторное развертывание объявлений типов. Причина в том, что в Java класс определяется с помощью classloader + class. Когда объявление типа развернуто, для него потребуется обновить загрузчик классов, эффективно создав новый загрузчик классов. Как вы заметили, все существующие правила будут по-прежнему ожидать старый classloader + class и не будут соответствовать новому classloader + class.

Итак, я предлагаю вам, если вам нужно выполнить горячее повторное развертывание правил, хранить объявления типов в отдельном файле DRL и только повторно развертывать файлы правил. Кроме того, вы можете создавать новые правила на лету или извлекать измененные правила из файла и только повторно развертывать их.

...