背景
为了提供代码的可维护性,项目组选择了drools规则引擎,想将代码中规则的部分抽出来。
然而,写的代码在test测试通过之后,导出Jar包执行却报错了。报错信息如下:
builder.add(ResourceFactory.newFileResource(f), ResourceType.DRL);
空指针异常
问题定位
在读源码,并按步实现之后,发现是 serviceInstance.get(KieResources.class);
返回结果为null。
//builder.add(ResourceFactory.newFileResource(f), ResourceType.DRL);
ServiceRegistry serviceInstance = ServiceRegistry.getInstance();
//service对象为null
KieResources service = serviceInstance.get(KieResources.class);
Resource resource = service.newFileSystemResource(f);
builder.add(resource,ResourceType.DRL);
在初步排查环境问题、参数问题之后,确认是打包问题的可能性比较大。我使用的是idea编辑器,maven项目。有两种打包工具,一种是idea自带,一种是maven打包,都试了下,还是不行。
开始漫长地Google之旅,比较相关的帖子如下:
1 kieservices-factory-get-returns-null
2 unning-drools-as-a-fat-jarcompile-drools-into-jar
异常原因
大致原因是所需依赖项 drools-core,drools-complie下均有同名kie.conf配置文件,加载的策略导致部分配置信息丢失。
drools-core kie.conf
org.kie.api.io.KieResources = org.drools.core.io.impl.ResourceFactoryServiceImpl
org.kie.api.marshalling.KieMarshallers = org.drools.core.marshalling.impl.MarshallerProviderImpl
org.kie.api.concurrent.KieExecutors = org.drools.core.concurrent.ExecutorProviderImpl
drools-complie kie.conf
org.kie.api.KieServices = org.drools.compiler.kie.builder.impl.KieServicesImpl
org.kie.internal.builder.KnowledgeBuilderFactoryService = org.drools.compiler.builder.impl.KnowledgeBuilderFactoryServiceImpl
解决方案
方法1. 修改源码下的配置文件,重新打Jar包引用
方法2. 修改打包的配置文件
方法2比较简单,重点说吧。
将此插件配置信息加入pom.xml。该插件的主要作用就是对于多个第三方包 META-INF 下同名的配置文件使用追加方式加载。
至此,这个bug正式修复完毕,花了一天时间。
唉,人生苦短,为啥不用Python
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/kie.conf</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>