The question: why is it ignoring the MergeStrategy.first?
I've made a minor application within the Play Framework using version 2.3.8
According to the official documentation you can add the line addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
to the plugin.sbt and add a few (see code below) to use the activator assembly
command.
This seems to be working but there is a deduplicate conflict. This happens strangely with the file ServerWithStop.class. In the build.sbt there is an assembleMergeStrategy for this class. This is an exact copy of the official documentation.
case "play/core/server/ServerWithStop.class" => MergeStrategy.first
case other => (assemblyMergeStrategy in assembly).value(other)
I've added a few lines that I found to fix the spring.tooling deduplicates (which can be found again in the full sbt). I understand the principles; its hashing SHA-1 to compare the classes then merge according to the behaviour, I understand that it doesn't understand what to do with the duplicates that seem to be different with ServerWithStop.class.
What I dont understand (and thus the question): why is it ignoring the MergeStrategy.first?
-
build.sbt
name := """MovieRequest"""
version := "1.0"
lazy val root = (project in file(".")).enablePlugins(PlayJava)
scalaVersion := "2.11.1"
libraryDependencies ++= Seq(
javaJdbc,
javaEbean,
cache,
javaWs,
"mysql" % "mysql-connector-java" % "5.1.35"
)
mainClass in assembly := Some("play.core.server.NettyServer")
fullClasspath in assembly += Attributed.blank(PlayKeys.playPackageAssets.value)
assemblyExcludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
cp filter {x => x.data.getName.matches("sbt.*") || x.data.getName.matches(".*macros.*")}
}
// Exclude commons-logging because it conflicts with the jcl-over-slf4j
libraryDependencies ~= { _ map {
case m if m.organization == "com.typesafe.play" =>
m.exclude("commons-logging", "commons-logging")
case m => m
}}
assemblyMergeStrategy in assembly := {
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 "spring.tooling" :: xs =>
MergeStrategy.discard
case "services" :: xs =>
MergeStrategy.filterDistinctLines
case ("spring.schemas" :: Nil) | ("spring.handlers" :: Nil) =>
MergeStrategy.filterDistinctLines
case _ => MergeStrategy.deduplicate
}
case "asm-license.txt" | "overview.html" => MergeStrategy.discard
// Take the first ServerWithStop because it's packaged into two jars
case "play/core/server/ServerWithStop.class" => MergeStrategy.first
case other => (assemblyMergeStrategy in assembly).value(other)
}
dist
command? playframework.com/documentation/2.3.x/ProductionDist – Microhenrydist
produces different output; it creates a ZIP file, whereassbt assembly
creates a fat JAR that you can run usingjava -jar my_filename.jar
. – Fremitus