我们有一个Java应用程序,在Weblogic上部署了不同的模块。我们在不同的模块上使用drools并尝试通过将它定义为枚举类来使初始化KieContainer的类成为单例。
但是,当我们处于生产环境(通过ear文件部署应用程序)时,似乎有不同的ClassLoader初始化此类,我们得到以下异常:
null java.lang.IllegalStateException: There's already another KieContainer created from a different ClassLoader;
at org.drools.compiler.kie.builder.impl.KieServicesImpl.getKieClasspathContainer(KieServicesImpl.java:88);
at org.drools.compiler.kie.builder.impl.KieServicesImpl.getKieClasspathContainer(KieServicesImpl.java:73);
您对如何解决这个问题有任何建议吗?
答案 0 :(得分:2)
我们在不同的环境中遇到了同样的问题(Kafka,Weld SE)。虽然反直觉,但仍在调用
// Answer the cuurent container if it exists else create a new container
KieServices.Factory.get().getKieClasspathContainer();
<强>不强>
// Always create a new container
KieServices.Factory.get().newKieClasspathContainer();
为我们解决了大部分问题。
此外,在容器超出范围之前,请务必调用:
KieServices.Factory.get().getKieClasspathContainer().dispose();
这将从Drools全局单例中释放容器及其资源。
我们在Maven中运行单元测试也遇到了问题,因为Surefire插件默认情况下不会为每个测试重新创建一个JVM,而Drools假定每个JVM调用只创建一个全局单例实例。通过让Surefire在每次测试中重新创建一个干净的JVM环境来解决这个问题。调整你的 的pom.xml 通过添加
<reuseForks>false</reuseForks>
到你的Surefire配置。例如:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>default-test</id>
<configuration>
<reuseForks>false</reuseForks>
</configuration>
</execution>
</executions>
</plugin>
此外,您可以考虑为每个Java EE模块分配自己的KieContainer
KieContainer getKieClasspathContainer(String containerId);
这将允许每个Java EE模块的生命周期与每个Drools容器模块的生命周期同步。
答案 1 :(得分:0)
drools代码检查您指定的类加载器和当前实例this.getClass()。getClassLoader()是否相同,如果不正确,则KieContainer的错误已经存在eror。如果不指定类加载器,则它使用Thread.currentThread()。getContextClassLoader(),在某些情况下,它与this.getClass()。getClassLoader()不同。简单的解决方法是使用 KieServices.Factory.get()。getKieClasspathContainer(this.getClass()。getClassLoader())