XML 파일을 읽고 노드를 POJO로 변환 한 다음 Drools의 WM로로드하고 마지막으로 적용하는 간단한 유틸리티를 작성합니다. 그들에게 어떤 규칙들. 내 GitHub profile에서 전체 프로젝트를 찾을 수 있습니다. 불행히도, 모든 노력에도 불구하고 Drools는 런타임에 컴파일 된 클래스의 인스턴스를 "좋아"하게 만들 수 없었습니다. 나는 많은 사람들이 ClassLoader에 문제가있는 것을 보았습니다. 그래서 그것의 잘못이라고 생각합니다 ... 최소 작업 예제은 시도 할 수 있습니다.이 파일은 GitHub과 아래에 있습니다. 다른 작은 파일 (MemoryFileManager
, MemoryJavaClassObject
및 MemoryJavaFileObject
)이 필요하며 간결성을 위해 GitHub에서만 사용할 수 있습니다. 제대로 작동하려면 JVM이 JDK> = 6이고 classpath
에 tools.jar
또는 classes.jar
이 있어야합니다.Drools 5.6.0으로 ClassLoader를 공유하여 런타임에 클래스의 메모리 내 컴파일 가능
public class Example {
/**
* @param args
*/
public static void main(String[] args) {
// Setting the strings that we are going to use...
String name = "Person";
String content = "public class " + name + " {\n";
content += " private String name;\n";
content += " public Person() {\n";
content += " }\n";
content += " public Person(String name) {\n";
content += " this.name = name;\n";
content += " }\n";
content += " public String getName() {\n";
content += " return name;\n";
content += " }\n";
content += " public void setName(String name) {\n";
content += " this.name = name;\n";
content += " }\n";
content += " @Override\n";
content += " public String toString() {\n";
content += " return \"Hello, \" + name + \"!\";\n";
content += " }\n";
content += "}\n";
String value = "HAL";
String rules = "rule \"Alive\"\n";
rules += "when\n";
rules += "then\n";
rules += " System.out.println(\"I'm alive!\")\n";
rules += "end\n";
rules += "\n";
rules += "rule \"Print\"\n";
rules += "when\n";
rules += " $o: Object()\n";
rules += "then\n";
rules += " System.out.println(\"DRL> \" + $o.toString())\n";
rules += "end\n";
// Compiling the given class in memory
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
JavaFileManager manager = new MemoryFileManager(compiler.getStandardFileManager(null, null, null));
ClassLoader classLoader = manager.getClassLoader(null);
List<JavaFileObject> files = new ArrayList<JavaFileObject>();
files.add(new MemoryJavaFileObject(name, content));
compiler.getTask(null, manager, null, null, null, files).call();
try {
// Instantiate and set the new class
Class<?> person = classLoader.loadClass(name);
Method method = person.getMethod("setName", String.class);
Object instance = person.newInstance();
method.invoke(instance, value);
System.out.println(instance);
System.out.println("We get a salutation, so Person is now a compiled class in memory loaded by the given ClassLoader.");
// Use the same instance in Drools (by means of the shared ClassLoader)
KnowledgeBuilderConfiguration config1 = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(null, classLoader);
KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder(config1);
builder.add(ResourceFactory.newByteArrayResource(rules.getBytes()), ResourceType.DRL);
if (builder.hasErrors()) {
for (KnowledgeBuilderError error : builder.getErrors())
System.out.println(error.toString());
System.exit(-1);
}
KnowledgeBaseConfiguration config2 = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(null, classLoader);
KnowledgeBase base = KnowledgeBaseFactory.newKnowledgeBase(config2);
base.addKnowledgePackages(builder.getKnowledgePackages());
StatefulKnowledgeSession session = base.newStatefulKnowledgeSession();
session.insert(instance);
session.fireAllRules();
} catch (ClassNotFoundException e) {
System.out.println("Class not found!");
} catch (IllegalAccessException e) {
System.out.println("Illegal access!");
} catch (InstantiationException e) {
System.out.println("Instantiation!");
} catch (NoSuchMethodException e) {
System.out.println("No such method!");
} catch (InvocationTargetException e) {
System.out.println("Invocation target!");
}
System.out.println("Done.");
}
}
내가 예제를 실행하면, 나는 다음과 같은 출력을 얻을 :
Hello, HAL!
We get a salutation, so Person is now a compiled class in memory loaded by the given ClassLoader.
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Exception in thread "main" java.lang.NoClassDefFoundError: Object (wrong name: Person)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at bragaglia.skimmer.core.MemoryFileManager$1.findClass(MemoryFileManager.java:33)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:340)
at org.drools.util.CompositeClassLoader$CachingLoader.load(CompositeClassLoader.java:258)
at org.drools.util.CompositeClassLoader$CachingLoader.load(CompositeClassLoader.java:237)
at org.drools.util.CompositeClassLoader.loadClass(CompositeClassLoader.java:88)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.drools.base.ClassTypeResolver.resolveType(ClassTypeResolver.java:155)
at org.drools.rule.builder.PatternBuilder.build(PatternBuilder.java:174)
at org.drools.rule.builder.PatternBuilder.build(PatternBuilder.java:135)
at org.drools.rule.builder.GroupElementBuilder.build(GroupElementBuilder.java:67)
at org.drools.rule.builder.RuleBuilder.build(RuleBuilder.java:85)
at org.drools.compiler.PackageBuilder.addRule(PackageBuilder.java:3230)
at org.drools.compiler.PackageBuilder.compileRules(PackageBuilder.java:1038)
at org.drools.compiler.PackageBuilder.compileAllRules(PackageBuilder.java:946)
at org.drools.compiler.PackageBuilder.addPackage(PackageBuilder.java:938)
at org.drools.compiler.PackageBuilder.addPackageFromDrl(PackageBuilder.java:470)
at org.drools.compiler.PackageBuilder.addKnowledgeResource(PackageBuilder.java:698)
at org.drools.builder.impl.KnowledgeBuilderImpl.add(KnowledgeBuilderImpl.java:51)
at org.drools.builder.impl.KnowledgeBuilderImpl.add(KnowledgeBuilderImpl.java:40)
at bragaglia.skimmer.core.Example.main(Example.java:91)
당신이 볼 수 있듯이, Person
클래스가 성공적으로 메모리에 컴파일 인스턴스화를 (을 참조 예는이 다음이다 출력에서 메시지 Hello, HAL!
), 그러나 WM에 추가하면 어떤 규칙도 명시 적으로 Person
에 의존하지 않아도 Exception in thread "main" java.lang.NoClassDefFoundError: Object (wrong name: Person)
이됩니다. 이제 예외를 조금 조사한 결과, 주어진 클래스 (Person
)가 Drools에 의해 사용 된 ClassLoader
안에 없으면 해고된다는 것을 깨달았습니다. 따라서 ClassLoader
을 HAL
과 KnowledgeBuilder
및 KnowledgeBase
모두에 컴파일하고 인스턴스화하는 데 사용 된 참조와 함께 구성을 추가했지만 동일한 예외가 발생했기 때문에 문제가 발생할 수 있습니다.
왜 이런 일이 발생하고 어떻게 해결할 수 있는지 알고 있습니까? 미리 많은 감사드립니다!