web-dev-qa-db-fra.com

Comment construire un JAR Uber (Fat JAR) en utilisant SBT avec IntelliJ IDEA?

J'utilise SBT (dans IntelliJ IDEA) pour construire un simple projet Scala.

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

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

Exception dans le fil "principal" Java.lang.SecurityException: Résumé du fichier de signature non valide pour les attributs principaux Manifest

Ou cette erreur lors de la compilation:

Java.lang.RuntimeException: dédupliquer: le contenu du fichier est différent de ce qui suit:
PATH\DEPENDENCY.jar: META-INF/DEPENDENCIES
PATH\DEPENDENCY.jar: META-INF/MANIFEST.MF

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

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 " Créer un artefact ... " dans IntelliJ IDEA, je reçois 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.

83
Yves M.

Enfin, je saute totalement à l’utilisation d’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 fichier suivante:

_my-project/project/Assembly.sbt
my-project/src/main/scala/myPackage/MyMainObject.scala
my-project/build.sbt
_

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

_addSbtPlugin("com.eed3si9n" % "sbt-Assembly" % "0.12.0")
_

Mon minimum build.sbt ressemble à:

_lazy val root = (project in file(".")).
  settings(
    name := "my-project",
    version := "1.0",
    scalaVersion := "2.11.4",
    mainClass in Compile := Some("myPackage.MyMainObject")        
  )

libraryDependencies ++= Seq(
  "org.Apache.spark" %% "spark-core" % "1.2.0" % "provided",
  "org.Apache.spark" %% "spark-streaming" % "1.2.0" % "provided",
  "org.Apache.spark" % "spark-streaming-Twitter_2.10" % "1.2.0"
)

// META-INF discarding
mergeStrategy in Assembly <<= (mergeStrategy in Assembly) { (old) =>
   {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case x => MergeStrategy.first
   }
}
_

Note : Le % "provided" signifie ne pas inclure la dépendance dans le dernier fichier JAR (ces bibliothèques sont déjà incluses dans mes travailleurs).

Remarque : META-INF mis au rebut inspiré de ce répondeur .

Note : Signification de % et %%

Maintenant, je peux construire mon gros JAR en utilisant SBT ( comment l’installer ) en lançant la commande suivante dans my /my-project dossier racine:

_sbt Assembly
_

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

_/my-project/target/scala-2.11/my-project-Assembly-1.0.jar
_

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


Pour ceux qui souhaitent intégrer SBT dans IntelliJ IDE: Comment exécuter des tâches sbt-Assembly à partir d’IntelliJ IDEA?

133
Yves M.

Processus en 3 étapes pour construire Uber JAR/Fat JAR dans IntelliJ Idée:

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

  1. Ajout du plugin Assembly SBT dans IntelliJ Idea

    Plugin sbt Path

    Allez dans le fichier ProjectName/project/target/plugins.sbt et ajoutez cette ligne addSbtPlugin("com.eed3si9n" % "sbt-Assembly" % "0.12.0")

  2. Ajout de la stratégie de fusion, de suppression et de non-ajout dans build.sbt

    Build sbt Path

    Allez dans le fichier NomProjet/build.sbt et ajoutez la stratégie d'emballage d'un fichier JAR Uber.

    Stratégie de fusion: S'il existe un conflit dans deux packages à propos d'une version de bibliothèque, lequel choisir 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 paquet dans Uber JAR.
    Par exemple: spark-core sera déjà présent sur votre Spark Cluster.Ainsi, nous ne devrions pas emballer cela dans Uber JAR.

    Stratégie de fusion et stratégie d'élimination Code de base:

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

    Donc, vous demandez de supprimer les fichiers META-INF en utilisant cette commande MergeStrategy.discard et pour le reste des fichiers, vous prenez la première occurrence du fichier de bibliothèque en cas de conflit. en utilisant cette commande MergeStrategy.first.

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

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

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

  3. Construire Uber JAR avec toutes ses dépendances

    sbtassembly

    Dans le type de terminal sbt Assembly pour construire le paquet


Voilà! Uber JAR est construit. Le fichier JAR sera dans ProjectName/target/scala-XX

JarBuilt

38
Ajay Gupta

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'assemblage est utilisée pour résoudre les conflits survenus lors de la création de jar Fat.

16
ARMV