我正在使用sbt程序集生成我的项目的fat jar。然后,当尝试运行我的jar文件时,我在这一行得到一个空指针:
val kieServices: KieServices = KieServices.Factory.get
val kieContainer: KieContainer = kieServices.getKieClasspathContainer
我已经尝试添加一个kie.conf
,但这没有帮助。我不使用maven或pom文件等。我正在使用scala sbt。
运行drools的最新版本。
build.sbt:
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / scalaVersion := "2.13.10"
lazy val root = (project in file("."))
.settings(
name := "untitled",
libraryDependencies ++= Seq(
"org.drools" % "drools-core" % "8.31.1.Final",
"org.drools" % "drools-compiler" % "8.31.1.Final",
"org.drools" % "drools-decisiontables" % "8.31.1.Final",
"org.drools" % "drools-mvel" % "8.31.1.Final",
"org.drools" % "drools-model-compiler" % "8.31.1.Final",
"org.kie" % "kie-api" % "8.31.1.Final"
),
resolvers in Global ++= Seq(
"Sbt plugins" at "https://dl.bintray.com/sbt/sbt-plugin-releases",
),
Compile / packageBin / mainClass := Some("src.Main"),
Compile / run / mainClass := Some("src.Main")
)
.settings(
assembly / assemblyJarName := "myJar.jar",
assembly / assemblyMergeStrategy := {
case PathList("META-INF", xs@_*) => MergeStrategy.discard
case _ => MergeStrategy.first
},
)
项目/plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0")
src/main/scala/src/main。Scala(抱歉不是抱歉):
package src
import org.kie.api.KieServices
import org.kie.api.runtime.KieContainer
object Main extends App {
val kieServices: KieServices = KieServices.Factory.get
val kieContainer: KieContainer = kieServices.getKieClasspathContainer
}
调试显示
import scala.jdk.CollectionConverters._
ServiceLoader.load(classOf[KieServices], classOf[KieServices].getClassLoader)
.asScala.size
在执行sbt run
时为1,在执行java -jar myJar.jar
时为0。
在前一种情况下,KieServices.Factory.get
返回org.drools.compiler.kie.builder.impl.KieServicesImpl@...some...hashcode...
,但在后一种情况下,它返回null
。
尝试添加内容为
的文件src/main/resources/META-INF/services/org.kie.api.KieServices
org.drools.compiler.kie.builder.impl.KieServicesImpl
还有一个问题是,与sbt package
相反,sbt assembly
从汇编jar中缺少这个文件。因此,尝试解压缩myJar.jar
,手动将此文件作为myJar.jar/META-INF/services/org.kie.api.KieServices
并将jar压缩回来(myJar.jar/META-INF/MANIFEST.MF
应该存在,但myJar.jar/META-INF/services
可能缺失:https://github.com/sbt/sbt-assembly/issues/11)
java.util.ServiceLoader.load()函数无用,只返回空结果
如何在"META-INF/services"使用Maven的JAR文件夹
由于
而从汇编jar中丢失assembly / assemblyMergeStrategy := {
case PathList("META-INF", xs@_*) => MergeStrategy.discard
在你的build.sbt
。所以修改策略:
assembly / assemblyMergeStrategy := {
case PathList("META-INF", "services", "org.kie.api.KieServices") => MergeStrategy.concat
case PathList("META-INF", xs@_*) => MergeStrategy.discard
case _ => MergeStrategy.first
}
和service文件将被包含在assembly jar中。
实际上,服务文件已经存在于依赖项中:~/.cache/coursier/v1/https/repo1.maven.org/maven2/org/drools/drools-compiler/8.31.1.Final/drools-compiler-8.31.1.Final.jar:META-INF/services/org.kie.api.KieServices
所以你不应该手动添加,只需要执行case PathList("META-INF", "services", "org.kie.api.KieServices") => MergeStrategy.concat
。
drools-compiler-8.31.1.Final.jar:META-INF/services/
中有不同的服务文件,所以要小心case PathList("META-INF", xs@_*) => MergeStrategy.discard
,如果你忽略了服务文件,以后可能会有更多的问题。
试
assembly / assemblyMergeStrategy := {
case PathList("META-INF", "services", xs@_*) => MergeStrategy.concat
case PathList("META-INF", xs@_*) => MergeStrategy.discard
case _ => MergeStrategy.first
}