直接进入正题
我们在使用开源规则引擎 Drools
的时候, 启动的时候可能会抛出如下异常:
Caused by: java.lang.ClassCastException: cn.com.chengzi.drools.domain.cofing.DroolsAutoConfiguration$1 cannot be cast to org.drools.compiler.kie.builder.impl.InternalKieModule at org.drools.compiler.kie.builder.impl.KieServicesImpl.newKieContainer(KieServicesImpl.java:184) at org.drools.compiler.kie.builder.impl.KieServicesImpl.newKieContainer(KieServicesImpl.java:172) at cn.com.chengzi.drools.domain.cofing.DroolsAutoConfiguration.kieContainer(DroolsAutoConfiguration.java:57) at cn.com.chengzi.drools.domain.cofing.DroolsAutoConfiguration$$EnhancerBySpringCGLIB$$f73b7244.CGLIB$kieContainer$2(<generated>) at cn.com.chengzi.drools.domain.cofing.DroolsAutoConfiguration$$EnhancerBySpringCGLIB$$f73b7244$$FastClassBySpringCGLIB$$c4bed561.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) at cn.com.chengzi.drools.domain.cofing.DroolsAutoConfiguration$$EnhancerBySpringCGLIB$$f73b7244.kieContainer(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ... 43 more Caused by: java.lang.ClassCastException: cn.com.chengzi.drools.domain.cofing.DroolsAutoConfiguration$1 cannot be cast to org.drools.compiler.kie.builder.impl.InternalKieModule at org.drools.compiler.kie.builder.impl.KieServicesImpl.newKieContainer(KieServicesImpl.java:184) at org.drools.compiler.kie.builder.impl.KieServicesImpl.newKieContainer(KieServicesImpl.java:172) at cn.com.chengzi.drools.domain.cofing.DroolsAutoConfiguration.kieContainer(DroolsAutoConfiguration.java:57) at cn.com.chengzi.drools.domain.cofing.DroolsAutoConfiguration$$EnhancerBySpringCGLIB$$f73b7244.CGLIB$kieContainer$2(<generated>) at cn.com.chengzi.drools.domain.cofing.DroolsAutoConfiguration$$EnhancerBySpringCGLIB$$f73b7244$$FastClassBySpringCGLIB$$c4bed561.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) at cn.com.chengzi.drools.domain.cofing.DroolsAutoConfiguration$$EnhancerBySpringCGLIB$$f73b7244.kieContainer(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ... 43 more
查看发现 KieServicesImpl
类中的 newKieContainer
发现抛出了类型转换异常:
public KieContainer newKieContainer(String containerId, ReleaseId releaseId, ClassLoader classLoader) { InternalKieModule kieModule = (InternalKieModule) getRepository().getKieModule(releaseId); if (kieModule == null) { throw new RuntimeException("Cannot find KieModule: " + releaseId); } if (classLoader == null) { classLoader = kieModule.getModuleClassLoader(); } KieProject kProject = new KieModuleKieProject( kieModule, classLoader ); if (classLoader != kProject.getClassLoader()) { // if the new kproject has a different classloader than the original one it has to be initialized kProject.init(); } if (containerId == null) { KieContainerImpl newContainer = new KieContainerImpl( UUID.randomUUID().toString(), kProject, getRepository(), releaseId ); return newContainer; } if ( kContainers.get(containerId) == null ) { KieContainerImpl newContainer = new KieContainerImpl( containerId, kProject, getRepository(), releaseId ); KieContainer check = kContainers.putIfAbsent(containerId, newContainer); if (check == null) { return newContainer; } else { newContainer.dispose(); throw new IllegalStateException("There's already another KieContainer created with the id "+containerId); } } else { throw new IllegalStateException("There's already another KieContainer created with the id "+containerId); } } public KieContainer newKieContainer(String containerId, ReleaseId releaseId, ClassLoader classLoader) { InternalKieModule kieModule = (InternalKieModule) getRepository().getKieModule(releaseId); if (kieModule == null) { throw new RuntimeException("Cannot find KieModule: " + releaseId); } if (classLoader == null) { classLoader = kieModule.getModuleClassLoader(); } KieProject kProject = new KieModuleKieProject( kieModule, classLoader ); if (classLoader != kProject.getClassLoader()) { // if the new kproject has a different classloader than the original one it has to be initialized kProject.init(); } if (containerId == null) { KieContainerImpl newContainer = new KieContainerImpl( UUID.randomUUID().toString(), kProject, getRepository(), releaseId ); return newContainer; } if ( kContainers.get(containerId) == null ) { KieContainerImpl newContainer = new KieContainerImpl( containerId, kProject, getRepository(), releaseId ); KieContainer check = kContainers.putIfAbsent(containerId, newContainer); if (check == null) { return newContainer; } else { newContainer.dispose(); throw new IllegalStateException("There's already another KieContainer created with the id "+containerId); } } else { throw new IllegalStateException("There's already another KieContainer created with the id "+containerId); } }
此为初始化 drl
文件时的异常, 说明我们的 drl
文件不规范, Drools
不能解析成功.
我仔细检查了一下:
rule "read-Reading-speed" when $rlt:ReadingLevelTest(totalWordsNum != null,totalSecondTime != null) $rl:ReadingLevel(readingSpeed == null) then $rl.setReadingSpeed($rlt.getTotalWordsNum()/$rlt.getTotalSecondTime()/60); update($rl) System.out.println("测评结果读速: " + $rl.toString()); end rule "read-Reading-speed" when $rlt:ReadingLevelTest(totalWordsNum != null,totalSecondTime != null) $rl:ReadingLevel(readingSpeed == null) then $rl.setReadingSpeed($rlt.getTotalWordsNum()/$rlt.getTotalSecondTime()/60); update($rl) System.out.println("测评结果读速: " + $rl.toString()); end
发现其实是因为在 then
中的 update($rl)
后没有用分号结尾, 加上分号运行正常.
when
后面每行表达式后面是不需要添加分号结尾的then
后面为java
代码, 每行必须使用分号结尾, 如果我们忘记了添加分号,编译器也会报错题型的, 但是有一些特例, 比如Drools
提供的方法update()
,insert
等等, 如果后面不加分号, 编译器是不会报错的, 但是运行的时候就会抛出解析失败!
标题:开源规则引擎 Drools 学习笔记 之 -- 1 cannot be cast to org.drools.compiler.kie.builder.impl.InternalKieModule
作者:chengzime
地址:https://www.chengzime.com.cn/articles/2019/09/11/1568195807017.html