我正在编写一个简单的实用程序,它读取 XML 文件,将它们的节点转换为 POJO,将它们加载到 Drools 的 WM 中,最后对它们应用一些规则。您可以在我的GitHub 个人资料上找到整个项目。不幸的是,尽管我付出了所有努力,我还是无法让 Drools “喜欢”在运行时编译的任何类实例。我看到很多人在使用 ClassLoader 时也遇到了问题,所以我怀疑这可能是它的错……我准备了一个最小的工作示例供您尝试,它可以在GitHub和下面的此处获得。它需要一些仅在GitHub 上MemoryFileManager
可用的其他小文件(MemoryJavaClassObject
和)MemoryJavaFileObject
为简洁起见。为了正常工作,此示例要求您的 JVM 是 JDK >= 6,并且您tools.jar
的. 示例如下:classes.jar
classpath
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,Exception in thread "main" java.lang.NoClassDefFoundError: Object (wrong name: Person)
即使没有规则明确依赖Person
s,我也会得到一个。现在,我稍微调查了一下这个异常,我意识到当在Drools 使用的类Person
中找不到给定的类 ( )时,它会被触发。ClassLoader
因此,我通过添加一个配置来更改我的代码,该配置引用了ClassLoader
用于编译和实例化HAL
theKnowledgeBuilder
和 的相同配置KnowledgeBase
,但是我可能做错了什么,因为我仍然得到相同的异常。
您知道为什么会发生这种情况以及如何解决它吗?提前谢谢了!