I'm generating a fat jar of my project using sbt assembly. Then, when trying to run my jar file, i get a nullpointer on this line:
val kieServices: KieServices = KieServices.Factory.get
val kieContainer: KieContainer = kieServices.getKieClasspathContainer
I've already tried adding a kie.conf, but this does not help. I am not using maven or a pom file etc. And am using scala sbt.
Running drools' latest version.
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
},
)
project/plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0")
src/main/scala/src/Main.scala (sorry not sorry):
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
}
CodePudding user response:
Debugging shows that
import scala.jdk.CollectionConverters._
ServiceLoader.load(classOf[KieServices], classOf[KieServices].getClassLoader)
.asScala.size
is 1 when I do sbt run but 0 when I do java -jar myJar.jar.
In the former case KieServices.Factory.get returns org.drools.compiler.kie.builder.impl.KieServicesImpl@...some...hashcode... but in the latter case it returns null.
Try to add a file src/main/resources/META-INF/services/org.kie.api.KieServices with content
org.drools.compiler.kie.builder.impl.KieServicesImpl
One more issue is that, on contrary to sbt package, sbt assembly is missing this file from the assembly jar. So try to unpack myJar.jar, put manually this file as myJar.jar/META-INF/services/org.kie.api.KieServices and zip the jar back (myJar.jar/META-INF/MANIFEST.MF should exist but myJar.jar/META-INF/services is probably missing: https://github.com/sbt/sbt-assembly/issues/11)
java.util.ServiceLoader.load() function is useless and only returns empty result
How to include a config file in the "META-INF/services" folder of a JAR using Maven
It's missing from assembly jar because of
assembly / assemblyMergeStrategy := {
case PathList("META-INF", xs@_*) => MergeStrategy.discard
in your build.sbt. So modify the strategy:
assembly / assemblyMergeStrategy := {
case PathList("META-INF", "services", "org.kie.api.KieServices") => MergeStrategy.concat
case PathList("META-INF", xs@_*) => MergeStrategy.discard
case _ => MergeStrategy.first
}
and service file will be included into assembly jar.
Actually, the service file already exists in the dependency: ~/.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
So you shouldn't add it manually, just do case PathList("META-INF", "services", "org.kie.api.KieServices") => MergeStrategy.concat.
There are different service files in drools-compiler-8.31.1.Final.jar:META-INF/services/ so be careful with case PathList("META-INF", xs@_*) => MergeStrategy.discard, it's possible you'll have more problems later if you ignore service files.
Try
assembly / assemblyMergeStrategy := {
case PathList("META-INF", "services", xs@_*) => MergeStrategy.concat
case PathList("META-INF", xs@_*) => MergeStrategy.discard
case _ => MergeStrategy.first
}
