JBPM 7.52动态编译GDST时Kie Builder无法解析ObjectType问题求解
JBPM 7.52动态编译GDST找不到数据对象问题解决方案
问题背景
使用JBPM Business Central Workbench 7.52版本,动态编译GDST规则表时,Kie Builder无法识别自定义数据对象,报错Unable to resolve ObjectType 'message' : [Rule name='Row 1 MsgRules']。
相关代码与资源
自定义数据对象代码
package com.stackoverflow.question1; /** This class was automatically generated by the data modeler tool. */ public class message implements java.io.Serializable { static final long serialVersionUID = 1L; private java.lang.String status; private java.lang.String name; private java.lang.String message; public message() {} public message(java.lang.String status, java.lang.String name, java.lang.String message) { this.status = status; this.name = name; this.message = message; } public java.lang.String getStatus() { return this.status; } public void setStatus(java.lang.String status) { this.status = status; } public java.lang.String getName() { return this.name; } public void setName(java.lang.String name) { this.name = name; } public java.lang.String getMessage() { return this.message; } public void setMessage(java.lang.String message) { this.message = message; } }
GDST规则表对应生成的DRL代码
package com.stackoverflow.question1; //from row number: 1 //Name was null rule "Row 1 MsgRules" dialect "mvel" when MSG : message( name == null ) then modify( MSG ) { setMessage( "Name was null" ) } end //from row number: 2 //Name was not null rule "Row 2 MsgRules" dialect "mvel" when MSG : message( name != null ) then modify( MSG ) { setMessage( "Name was not null" ) } end
原编译代码
public static KieContainer loadGdstIntoContainer( String gdstFileName) { logger.info("KieUtilities:loadKieContainer - Started"); try { KieServices kieServices = KieServices.Factory.get(); KieFileSystem kieFileSystem = kieServices.newKieFileSystem(); //URL resource = KieUtilities.class.getClassLoader().getResource("BaseClaim.class"); //kieFileSystem.write(ResourceFactory.newUrlResource(resource)); kieFileSystem.write(ResourceFactory.newClassPathResource("MsgRules.gdst")); KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem); kieBuilder.buildAll(); if (kieBuilder.getResults().hasMessages(Message.Level.ERROR)) { throw new RuntimeException("Build Errors:\n" + kieBuilder.getResults().toString()); } KieRepository kieRepository = kieServices.getRepository(); KieContainer kieContainer = kieServices.newKieContainer(kieRepository.getDefaultReleaseId()); logger.info("KieUtilities:loadKieContainer - Finished"); return kieContainer; } catch(Exception ex) { logger.info("KieUtilities:loadKieContainer - Failed"); logger.info(ex.getLocalizedMessage()); throw ex; } }
之前尝试的无效修复
URL resource = KieUtilities.class.getClassLoader().getResource("message.class"); kieFileSystem.write(ResourceFactory.newUrlResource(resource));
修复方案
错误原因
之前的修复无效有两个核心问题:
- KieBuilder编译规则时需要目标类在指定的类加载路径中,直接将
.class文件写入KieFileSystem根路径,不符合Kie的资源路径规范,无法被识别 - 类文件没有按照包结构存放,
com.stackoverflow.question1.message对应的路径应该是com/stackoverflow/question1/message.class,直接放根路径找不到对应类。
三种可行修复方式,按实现难度从低到高排序:
方式一:指定KieBuilder使用当前上下文类加载器(最便捷)
只要你的message类已经在当前项目的类路径中,不需要额外写入类文件到KieFileSystem,只需要在创建KieBuilder时传入当前线程的上下文类加载器即可,修改代码如下:
// 将原来创建KieBuilder的代码替换为下面这行 KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem, Thread.currentThread().getContextClassLoader());
方式二:将数据对象Java源文件写入KieFileSystem一起编译
如果需要完全从零构建,不依赖当前类路径的类,可以把message.java源文件按包路径写入KieFileSystem,让KieBuilder先编译Java类再编译规则:
// 写入Java源文件,注意路径对应包结构 kieFileSystem.write("src/main/java/com/stackoverflow/question1/message.java", ResourceFactory.newClassPathResource("message.java")); // 再写入GDST规则文件 kieFileSystem.write(ResourceFactory.newClassPathResource("MsgRules.gdst"));
方式三:修正class文件写入路径
如果你一定要使用已经编译好的.class文件,修改写入时的路径即可:
URL resource = KieUtilities.class.getClassLoader().getResource("com/stackoverflow/question1/message.class"); kieFileSystem.write("classes/com/stackoverflow/question1/message.class", ResourceFactory.newUrlResource(resource));
内容的提问来源于stack exchange,提问作者vscoder
相关产品推荐
相关产品推荐

