Не используйте Drools с версии 3, но попытайтесь помочь в любом случае. Когда вы загружаете класс таким образом (динамически, во время выполнения, независимо от того, используете ли вы, например, Class.forName() или Jodd), загруженное имя класса просто недоступно для явного использования в коде. Я считаю, что мы можем упростить вашу проблему с помощью следующего SUDO-кода, где вы первый загрузится класс, а затем попытаться использовать его имя:
defineClass('Tire.class');
Tire tire = new Tire();
Это, очевидно, не работает, так как тип шин не доступен во время компиляции : компилятор не знает, какой тип вы собираетесь загрузить во время выполнения.
Что будет работать, чтобы иметь шину, реализующую какой-либо интерфейс (например, VehiclePart). Итак, вы можете использовать следующий Судо-код:
Class tireClass = defineClass('Tire.class');
VehiclePart tire = tireClass.newInstance();
System.out.println(tire.getPartName()); // prints 'tire' for example
Тогда, возможно, вы можете построить свои Drools правило через интерфейс VehiclePart и имущества getPartName().
Добавление
выше имеют смысл только тогда, когда интерфейс охватывает все свойства динамически загружаемого класса. В большинстве случаев это недействительное решение: динамически загруженные классы просто не разделяют свойства. Итак, вот еще один подход.
Вместо использования явной загрузки классов эту проблему можно решить, «расширив» путь класса classloader. Будьте осторожны, это хак!
В Джодд, есть метод: ClassLoaderUtil.addFileToClassPath(), который может добавить файл или путь к загрузчику классов в среде выполнения. Итак, вот шаги, которые сработали для меня:
1) Поместите все динамически созданные классы в некоторую корневую папку с учетом их пакетов. Например, допустим, мы хотим использовать класс jodd.samples.TestBean, который имеет два свойства: номер (int) и значение (строка). Затем нам нужно поставить этот класс в папку root/jodd/samples.
2) После построения всех динамических классов, расширить путь загрузчиков классов:
ClassLoaderUtil.addFileToClassPath("root", ClassLoader.getSystemClassLoader());
3) класс нагрузки и создать его перед созданием KnowledgeBuilder:
Class testBeanClass = Class.forName("jodd.samples.TestBean");
Object testBean = testBeanClass.newInstance();
4) На данный момент вы можете использовать BeanUtils (от Джодда, например :) для управления свойствами экземпляра testBean
5) Создайте материал Drools и добавьте вставку testBean в сеанс:
knowledgeSession.insert(testBean);
6) Используйте его в правиле файла:
import jodd.samples.TestBean;
rule "xxx"
when
$t: TestBean(number == 173)
then
System.out.println("!!!");
end
Это работает для меня. Обратите внимание, что на шаге 2 вы можете попробовать использовать другой загрузчик классов, но вам может понадобиться передать его в KnowledgeBuilderFactory через KnowledgeBuilderConfiguration (то есть PackageBuilderConfiguration).
Другое решение
Другим решением является просто скопировать все свойства объекта на карте, и иметь дело с картой в файлах правил. Таким образом, вы можете использовать что-то вроде этого на шаге 4:
Map map = new HashMap();
BeanTool.copy(testBean, map);
, а затем (шаг # 5) добавить карту в Drools контекст вместо экземпляра компонента. В этом случае было бы лучше использовать метод defineClass() для явного определения каждого класса.
Я пробовал писать «import datatypes.Tire» в файле правил. (типы данных - это пакет, в котором должен быть класс шины). Теперь вместо того, чтобы говорить, не может разрешить шину, он говорит, что Tire не может быть разрешен для типа. Поэтому я интерпретирую это как то, что Tire решается на пакет вместо типа и поэтому не может быть импортирован. Почему это может быть? –