简体   繁体   中英

Drools fat jar nullpointer KieServices

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
}

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM