Estoy usando SBT (dentro de IntelliJ IDEA) para construir un proyecto Scala simple.
Me gustaría saber cuál es la forma más sencilla de crear un archivo JAR de Uber (también conocido como Fat JAR, Super JAR).
Actualmente estoy usando SBT pero cuando envío mi archivo JAR a Apache Spark , aparece el siguiente error:
Excepción en el hilo "principal" java.lang.SecurityException: resumen de archivo de firma no válido para los atributos principales del manifiesto
O este error durante el tiempo de compilación:
java.lang.RuntimeException: deduplicate: diferentes contenidos de archivos encontrados en lo siguiente:
PATH \ DEPENDENCY.jar: META-INF / DEPENDENCIES
PATH \ DEPENDENCY.jar: META-INF / MANIFEST.MF
Se parece que se debe a que algunos de mis dependencias incluyen archivos de firma (META-INF) que debe ser eliminado en el archivo final JAR Uber.
Traté de usar el complemento sbt-assembly así:
/project/assembly.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
/project/plugins.sbt
logLevel := Level.Warn
/build.sbt
lazy val commonSettings = Seq(
name := "Spark-Test"
version := "1.0"
scalaVersion := "2.11.4"
)
lazy val app = (project in file("app")).
settings(commonSettings: _*).
settings(
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "1.2.0",
"org.apache.spark" %% "spark-streaming" % "1.2.0",
"org.apache.spark" % "spark-streaming-twitter_2.10" % "1.2.0"
)
)
Cuando hago clic en " Build Artifact ... " en IntelliJ IDEA, obtengo un archivo JAR. Pero termino con el mismo error ...
Soy nuevo en SBT y no tengo mucha experiencia con IntelliJ IDE.
Gracias.
META-INF
archivos, una publicación de blog que podría ayudar: janschulte.wordpress.com/2014/03/20/…Respuestas:
Finalmente, omito totalmente el uso de IntelliJ IDEA para evitar generar ruido en mi comprensión global :)
Empecé a leer el tutorial oficial de SBT .
Creé mi proyecto con la siguiente estructura de archivos:
Se ha añadido el SBT-ensamblaje de plugins en mi assembly.sbt archivo. Permitiéndome construir un JAR gordo:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
Mi build.sbt mínimo se ve así:
lazy val root = (project in file(".")). settings( name := "my-project", version := "1.0", scalaVersion := "2.11.4", mainClass in Compile := Some("myPackage.MyMainObject") ) val sparkVersion = "1.2.0" libraryDependencies ++= Seq( "org.apache.spark" %% "spark-core" % sparkVersion % "provided", "org.apache.spark" %% "spark-streaming" % sparkVersion % "provided", "org.apache.spark" %% "spark-streaming-twitter" % sparkVersion ) // META-INF discarding mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) => { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case x => MergeStrategy.first } }
Nota : Los
% "provided"
medios para no incluir la dependencia en el JAR fat final (esas bibliotecas ya están incluidas en mis trabajadores)Nota : Descarte de META-INF inspirado en esta respuesta .
Nota : Significado de
%
y%%
Ahora puedo construir mi fat JAR usando SBT ( cómo instalarlo ) ejecutando el siguiente comando en mi carpeta raíz / my-project :
Mi fat JAR ahora se encuentra en la nueva carpeta generada / target :
/my-project/target/scala-2.11/my-project-assembly-1.0.jar
Espero que ayude a alguien más.
Para aquellos que desean incrustar SBT dentro de IntelliJ IDE: ¿Cómo ejecutar tareas de ensamblaje de sbt desde IntelliJ IDEA?
fuente
Proceso de 3 pasos para construir Uber JAR / Fat JAR en IntelliJ Idea:
Uber JAR / Fat JAR : archivo JAR que tiene todas las dependencias de libraray externas.
Agregar el complemento SBT Assembly en IntelliJ Idea
Vaya al archivo ProjectName / project / target / plugins.sbt y agregue esta línea
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
Adición de la estrategia Combinar, Descartar y No agregar en build.sbt
Vaya al archivo ProjectName / build.sbt y agregue la estrategia para empaquetar un JAR de Uber
Fusionar estrategia: si hay un conflicto en dos paquetes sobre una versión de la biblioteca, entonces cuál empacar en Uber JAR.
Descartar estrategia: para eliminar algunos archivos de la biblioteca que no desea empaquetar en Uber JAR.
No agregue estrategia: no agregue ningún paquete a Uber JAR.
Por ejemplo:
spark-core
ya estará presente en su Spark Cluster, así que no debemos empaquetar esto en Uber JARCódigo básico de estrategia de fusión y estrategia de descarte:
assemblyMergeStrategy in assembly := { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case x => MergeStrategy.first }
Por lo tanto, está pidiendo descartar los archivos META-INF usando este comando
MergeStrategy.discard
y para el resto de los archivos está tomando la primera aparición del archivo de biblioteca si hay algún conflicto al usar este comandoMergeStrategy.first
.No agregue el código básico de la estrategia:
libraryDependencies += "org.apache.spark" %% "spark-core" % "1.4.1" %"provided"
Si no queremos agregar el spark-core a nuestro archivo JAR de Uber, ya que ya estará en nuestro clutser, entonces agregaremos la
% "provided"
dependencia de biblioteca al final.Construyendo Uber JAR con todas sus dependencias
En tipo de terminal
sbt assembly
para construir el paqueteVoila !!! Uber JAR está construido. JAR estará en ProjectName / target / scala-XX
fuente
Agregue la siguiente línea a su proyecto / plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
Agregue lo siguiente a su build.sbt
mainClass in assembly := some("package.MainClass") assemblyJarName := "desired_jar_name_after_assembly.jar" val meta = """META.INF(.)*""".r assemblyMergeStrategy in assembly := { case PathList("javax", "servlet", xs @ _*) => MergeStrategy.first case PathList(ps @ _*) if ps.last endsWith ".html" => MergeStrategy.first case n if n.startsWith("reference.conf") => MergeStrategy.concat case n if n.endsWith(".conf") => MergeStrategy.concat case meta(_) => MergeStrategy.discard case x => MergeStrategy.first }
La estrategia de fusión de ensamblajes se utiliza para resolver los conflictos que se produjeron al crear fat jar.
fuente