I couldn't reproduce Unable to build index of kmodule.xml
. Just kieContainer.newKieSession("DroolDummyKS")
returns null
for assembly jar (java -jar myJar.jar
), on contrary to sbt run
, where it returns KieSession[0]
.
Notice that it's written in your error:
Please add the module org.drools:drools-xml-support
to your classpath
Do two things in build.sbt
:
and
unignore kmodule.xml
in assembly strategy (so that kmodule.xml
is included into assembly jar), for example with singleOrError
(not sure that concatenation makes sense for xml
on contrary to service files, we're making sure that it's your kmodule.xml
being included, otherwise it throws)
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
}
Update. With
assembly / assemblyMergeStrategy := {
case _ => MergeStrategy.singleOrError
}
you can check what files have duplicates.
You should add the dependency "org.drools" % "drools-xml-support" % "8.31.1.Final"
as I adviced earlier. Otherwise there is NPE even for sbt run
. I see that you added it in update.
You should remove the file src/main/resources/META-INF/services/org.kie.api.KieServices
. Anyway it's present in the dependency drools-compiler-8.31.1.Final.jar
.
Try the strategy ignoring as less as possible
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
}
Duplicates should be resolved then.
filterDistinctLines
is similar to concat
, just not adding the same lines.
The strategy can be simplified
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
}
Update 2. I looked for reasons of the latest 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
It turns out that the thing was in the file META-INF/kie.default.properties.conf
of one of dependencies. So it was enough to additionally unignore it
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
}
But the main conclusion for us should be that ignoring the whole META-INF
can be dangerous. There can be some other files there that are important for some of dependencies. Maybe now there is no NPE but some issues can be later.
It turns out that the default assembly strategy
assembly / assemblyMergeStrategy := MergeStrategy.defaultMergeStrategy
or
assembly / assemblyMergeStrategy := {
case x =>
val oldStrategy = (ThisBuild / assemblyMergeStrategy).value
oldStrategy(x)
}
or (see here)
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
}
does the work pretty well. You just had to ignore additionally files module-info.class
. So you can prefer
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