我正试图从一个使用sbt assembly
生成的胖罐子中运行一个基于drools(和KieServices)的项目。
[main] INFO org.drools.compiler.kie.builder.impl.ClasspathKieProject - Found kmodule: jar:file:/.../myJar.jar!/META-INF/kmodule.xml
[main] ERROR org.drools.compiler.kie.builder.impl.ClasspathKieProject - Unable to build index of kmodule.xml url=jar:file:/.../myJar.jar/META-INF/kmodule.xml
You're trying to perform a xml related operation without the necessary xml support for drools. Please add the module org.drools:drools-xml-support to your classpath.
[main] ERROR org.drools.compiler.kie.builder.impl.KieContainerImpl - Unknown KieSession name: DroolDummyKS
此错误由以下代码触发,最后一行具体说明:
val kieServices: KieServices = KieServices.Factory.get
val kieContainer: KieContainer = kieServices.getKieClasspathContainer
// Apply the correct kie session from the ./resources/META-INF/kmodule.xml configuration
val kieSession: KieSession = kieContainer.newKieSession("DroolDummyKS")
项目是Scala SBT项目(Java 11作为编译器)
我无法复制Unable to build index of kmodule.xml
。只有kieContainer.newKieSession("DroolDummyKS")
为汇编jar(java -jar myJar.jar
)返回null
,而sbt run
则返回KieSession[0]
。
注意,它写在你的错误:
请将模块
org.drools:drools-xml-support
添加到类路径中
在build.sbt
:中做两件事
-
添加到
libraryDependencies
"org.drools" % "drools-xml-support" % "8.31.1.Final"
和
-
在汇编策略中忽略
kmodule.xml
(这样kmodule.xml
就包含在汇编jar中),例如使用singleOrError
(不确定级联对xml
是否有意义,与服务文件相反,我们要确保它是您的kmodule.xml
,否则它会抛出)assembly / assemblyMergeStrategy := { case PathList("META-INF", "services", xs@_*) => MergeStrategy.concat case PathList("META-INF", "kmodule.xml") => MergeStrategy.singleOrError case PathList("META-INF", xs@_*) => MergeStrategy.discard case _ => MergeStrategy.first }
更新使用
assembly / assemblyMergeStrategy := {
case _ => MergeStrategy.singleOrError
}
您可以检查哪些文件有重复项。
您应该添加依赖项"org.drools" % "drools-xml-support" % "8.31.1.Final"
,正如我之前建议的那样。否则,即使对于CCD_ 17也存在NPE我看到你在更新中添加了它
您应该删除文件src/main/resources/META-INF/services/org.kie.api.KieServices
。无论如何,它存在于依赖drools-compiler-8.31.1.Final.jar
中。
尝试忽略尽可能少的的策略
assembly / assemblyMergeStrategy := {
case xs if xs.endsWith("LICENSE") => MergeStrategy.discard
case xs if xs.endsWith("LICENSE.txt") => MergeStrategy.discard
case xs if xs.endsWith("INDEX.LIST") => MergeStrategy.discard
case xs if xs.endsWith("MANIFEST.MF") => MergeStrategy.discard
case xs if xs.endsWith("NOTICE") => MergeStrategy.discard
case xs if xs.endsWith("NOTICE.txt") => MergeStrategy.discard
case xs if xs.endsWith("module-info.class") => MergeStrategy.discard
case PathList("META-INF", "services", "org.apache.poi.sl.draw.ImageRenderer") => MergeStrategy.filterDistinctLines
case PathList("META-INF", "services", "org.apache.poi.ss.usermodel.WorkbookProvider") => MergeStrategy.filterDistinctLines
case PathList("META-INF", "services", "org.apache.poi.extractor.ExtractorProvider") => MergeStrategy.filterDistinctLines
case PathList("META-INF", "services", "org.drools.wiring.api.ComponentsSupplier") => MergeStrategy.filterDistinctLines
case _ => MergeStrategy.singleOrError
}
然后应解决重复问题。
filterDistinctLines
类似于concat
,只是没有添加相同的行。
该策略可以简化
assembly / assemblyMergeStrategy := {
case xs if Seq(
"LICENSE",
"LICENSE.txt",
"INDEX.LIST",
"MANIFEST.MF",
"NOTICE",
"NOTICE.txt",
"module-info.class"
).exists(xs.endsWith) => MergeStrategy.discard
case PathList("META-INF", "services", xs@_*) => MergeStrategy.filterDistinctLines
case _ => MergeStrategy.singleOrError
}
更新2。我查找了最新NPE 的原因
Exception in thread "main" java.lang.NullPointerException:
Cannot invoke
"org.drools.compiler.compiler.Dialect.getId()"
because the return value of
"org.drools.compiler.rule.builder.RuleBuildContext.getDialect()"
is null
事实证明,这个东西在一个依赖项的文件META-INF/kie.default.properties.conf
中。因此,额外忽略就足够了
assembly / assemblyMergeStrategy := {
case x if x.endsWith("module-info.class") => MergeStrategy.discard
case PathList("META-INF", "services", xs@_*) => MergeStrategy.concat
case PathList("META-INF", "kmodule.xml") => MergeStrategy.singleOrError
case PathList("META-INF", "kie.default.properties.conf") => MergeStrategy.singleOrError
case PathList("META-INF", xs@_*) => MergeStrategy.discard
case _ => MergeStrategy.first
}
但我们的主要结论应该是,忽略整个META-INF
可能是危险的。可能还有一些其他文件对某些依赖关系很重要。也许现在没有NPE,但有些问题可能会推迟。
事实证明,默认的组装策略
assembly / assemblyMergeStrategy := MergeStrategy.defaultMergeStrategy
或
assembly / assemblyMergeStrategy := {
case x =>
val oldStrategy = (ThisBuild / assemblyMergeStrategy).value
oldStrategy(x)
}
或(见此处)
val defaultMergeStrategy: String => MergeStrategy = {
case x if Assembly.isConfigFile(x) =>
MergeStrategy.concat
case PathList(ps @ _*) if Assembly.isReadme(ps.last) || Assembly.isLicenseFile(ps.last) =>
MergeStrategy.rename
case PathList("META-INF", xs @ _*) =>
(xs map {_.toLowerCase}) match {
case ("manifest.mf" :: Nil) | ("index.list" :: Nil) | ("dependencies" :: Nil) =>
MergeStrategy.discard
case ps @ (x :: xs) if ps.last.endsWith(".sf") || ps.last.endsWith(".dsa") =>
MergeStrategy.discard
case "plexus" :: xs =>
MergeStrategy.discard
case "services" :: xs =>
MergeStrategy.filterDistinctLines
case ("spring.schemas" :: Nil) | ("spring.handlers" :: Nil) =>
MergeStrategy.filterDistinctLines
case _ => MergeStrategy.deduplicate
}
case _ => MergeStrategy.deduplicate
}
这项工作做得很好。您只需要忽略另外的文件module-info.class
。所以你可以更喜欢
assembly / assemblyMergeStrategy := {
case x if x.endsWith("module-info.class") => MergeStrategy.discard
case x =>
val oldStrategy = (ThisBuild / assemblyMergeStrategy).value
oldStrategy(x)
}
https://github.com/ThijmenL98/DroolsMCVE/pull/1