Comment créer un Uber JAR (Fat JAR) en utilisant SBT dans IntelliJ IDEA?


90

J'utilise SBT (dans IntelliJ IDEA) pour créer un projet Scala simple.

Je voudrais savoir quel est le moyen le plus simple de créer un fichier Uber JAR (aka Fat JAR, Super JAR).

J'utilise actuellement SBT mais lorsque je soumets mon fichier JAR à Apache Spark, j'obtiens l'erreur suivante:

Exception dans le thread "main" java.lang.SecurityException: résumé du fichier de signature non valide pour les attributs principaux du manifeste

Ou cette erreur lors de la compilation:

java.lang.RuntimeException: dédupliquer: contenu de fichier différent trouvé dans ce qui suit:
PATH \ DEPENDENCY.jar: META-INF / DEPENDENCIES
PATH \ DEPENDENCY.jar: META-INF / MANIFEST.MF

On dirait que c'est parce que certaines de mes dépendances incluent des fichiers de signature (META-INF) qui doivent être supprimés dans le fichier JAR Uber final.

J'ai essayé d'utiliser le plugin sbt-assembly comme ça:

/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"
    )
  )

Lorsque je clique sur " Construire un artefact ... " dans IntelliJ IDEA, j'obtiens un fichier JAR. Mais je me retrouve avec la même erreur ...

Je suis nouveau sur SBT et pas très expérimenté avec IntelliJ IDE.

Merci.


2
Au son des choses, vous devrez peut-être filtrer les META-INFfichiers - un article de blog qui pourrait vous aider: janschulte.wordpress.com/2014/03/20/…
Sean Vieira

Réponses:


144

Enfin, j'oublie totalement d'utiliser IntelliJ IDEA pour éviter de générer du bruit dans ma compréhension globale :)

J'ai commencé à lire le tutoriel officiel SBT .

J'ai créé mon projet avec la structure de fichiers suivante:

my-project/project/assembly.sbt
my-project/src/main/scala/myPackage/MyMainObject.scala
my-project/build.sbt

Ajout du plugin sbt-assembly dans mon fichier assembly.sbt . Me permettant de construire un gros JAR:

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")

Mon build.sbt minimal ressemble à:

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
   }
}

Remarque : le % "provided"moyen de ne pas inclure la dépendance dans le fat JAR final (ces bibliothèques sont déjà incluses dans mes workers)

Remarque : suppression de META-INF inspirée de ce répondeur .

Remarque : Signification de %et%%

Maintenant, je peux créer mon gros JAR en utilisant SBT ( comment l'installer ) en exécutant la commande suivante dans le dossier racine de mon / my-project :

sbt assembly

Mon gros JAR se trouve maintenant dans le nouveau dossier généré / cible :

/my-project/target/scala-2.11/my-project-assembly-1.0.jar

J'espère que cela aide quelqu'un d'autre.


Pour ceux qui souhaitent intégrer SBT dans IntelliJ IDE: comment exécuter des tâches d'assemblage sbt à partir d'IntelliJ IDEA?


2
Suggestion Java / Maven sur le [problème d'exclusion de Spark des uber-jars de Databricks databricks.gitbooks.io/databricks-spark-knowledge-base/content/…
JimLohse


1
Quelle est la raison de la suppression de l'ancien META-INF?
qed

2
Note: Le% "fourni" signifie ne pas inclure la dépendance dans le fat JAR final, c'est celui qui m'a aidé!
Jayasagar du

sérieusement surpris que ce soit le seul plugin disponible - même pas officiel, et ne fonctionne même pas avec les versions sbt
Abhinandan Dubey

40

Processus en 3 étapes pour créer Uber JAR / Fat JAR dans IntelliJ Idea:

Uber JAR / Fat JAR : fichier JAR contenant toutes les dépendances externes de libraray.

  1. Ajout du plugin SBT Assembly dans IntelliJ Idea

    Chemin du plugin sbt

    Accédez au fichier ProjectName / project / target / plugins.sbt et ajoutez cette ligneaddSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")

  2. Ajout d'une stratégie de fusion, de rejet et de ne pas ajouter dans build.sbt

    Construire le chemin sbt

    Aller à fichier ProjectName / build.sbt et ajoutez la stratégie d'empaquetage d'un JAR Uber

    Stratégie de fusion: s'il y a conflit entre deux packages concernant une version de bibliothèque, lequel emballer dans Uber JAR.
    Stratégie de suppression : pour supprimer certains fichiers de la bibliothèque que vous ne souhaitez pas empaqueter dans Uber JAR.
    N'ajoutez pas de stratégie: n'ajoutez pas de package à Uber JAR.
    Par exemple: spark-coresera déjà présent sur votre Spark Cluster, nous ne devons donc pas emballer cela dans Uber JAR

    Code de base de stratégie de fusion et de stratégie de rejet:

    assemblyMergeStrategy in assembly := { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case x => MergeStrategy.first }

    Vous demandez donc de supprimer les fichiers META-INF en utilisant cette commande MergeStrategy.discardet pour le reste des fichiers que vous prenez le première occurrence du fichier de bibliothèque en cas de conflit en utilisant cette commande MergeStrategy.first.

    N'ajoutez pas de code de base de stratégie:

    libraryDependencies += "org.apache.spark" %% "spark-core" % "1.4.1" %"provided"

    Si nous ne voulons pas ajouter le spark-core à notre fichier JAR Uber car il sera déjà sur notre clutser, nous ajoutons donc le % "provided" dépendance de bibliothèque à la fin.

  3. Construire Uber JAR avec toutes ses dépendances

    assemblage

    En type de terminal sbt assembly pour la construction du package


Voila !!! Uber JAR est construit. JAR sera dans ProjectName / target / scala-XX

JarBuilt


16

Ajoutez la ligne suivante à votre projet / plugins.sbt

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")

Ajoutez ce qui suit à votre 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 stratégie de fusion d'assembly est utilisée pour résoudre les conflits survenus lors de la création du fat pot.


1
Vous pouvez créer de gros Jar en exécutant "sbt assembly" dans la console
ARMV

2
pour scala version 2.11.8 (version SBT: 0.13.12), mettez addSbtPlugin ("com.eed3si9n"% "sbt-assembly"% "0.12.0") dans project / assembly.sbt
ARMV
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.