Wie erstelle ich eine Uber JAR (Fat JAR) mit SBT in IntelliJ IDEA?


89

Ich verwende SBT (innerhalb von IntelliJ IDEA), um ein einfaches Scala-Projekt zu erstellen.

Ich würde gerne wissen, was der einfachste Weg ist , eine Uber JAR- Datei (auch bekannt als Fat JAR, Super JAR) zu erstellen .

Ich verwende derzeit SBT, aber wenn ich meine JAR-Datei an Apache Spark sende , wird der folgende Fehler angezeigt :

Ausnahme im Thread "main" java.lang.SecurityException: Ungültiger Digest der Signaturdatei für Manifest-Hauptattribute

Oder dieser Fehler während der Kompilierungszeit:

java.lang.RuntimeException: deduplizieren: Unterschiedlicher Dateiinhalt im Folgenden:
PATH \ DEPENDENCY.jar: META-INF / DEPENDENCIES
PATH \ DEPENDENCY.jar: META-INF / MANIFEST.MF

Es sieht so aus, als ob einige meiner Abhängigkeiten Signaturdateien (META-INF) enthalten, die in der endgültigen Uber JAR-Datei entfernt werden müssen.

Ich habe versucht, das sbt-Assembly- Plugin folgendermaßen zu verwenden:

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

Wenn ich in IntelliJ IDEA auf " Artefakt erstellen ... " klicke, erhalte ich eine JAR-Datei. Aber am Ende habe ich den gleichen Fehler ...

Ich bin neu bei SBT und habe nicht sehr viel mit IntelliJ IDE experimentiert.

Vielen Dank.


2
Nach dem Klang der Dinge müssen Sie möglicherweise die META-INFDateien herausfiltern - ein Blog-Beitrag, der helfen könnte : janschulte.wordpress.com/2014/03/20/…
Sean Vieira

Antworten:


144

Schließlich überspringe ich die Verwendung von IntelliJ IDEA vollständig, um zu vermeiden, dass in meinem globalen Verständnis Rauschen erzeugt wird :)

Ich fing an, das offizielle SBT-Tutorial zu lesen .

Ich habe mein Projekt mit folgender Dateistruktur erstellt:

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

Hinzugefügt wird die sbt-Montage - Plugin in meiner assembly.sbt Datei. Erlaubt mir, ein fettes Glas zu bauen:

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

Meine minimale build.sbt sieht aus wie:

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

Hinweis : Das % "provided"bedeutet, die Abhängigkeit nicht in die endgültige Fat JAR aufzunehmen (diese Bibliotheken sind bereits in meinen Workern enthalten).

Hinweis : META-INF-Verwerfen, inspiriert von dieser Antwort .

Hinweis : Bedeutung von %und%%

Jetzt kann ich meine fette JAR mit SBT erstellen ( wie man sie installiert ), indem ich den folgenden Befehl in meinem / my-project- Stammordner ausführe:

sbt assembly

Meine fette JAR befindet sich jetzt im neu generierten Ordner / target :

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

Hoffe das hilft jemand anderem.


Für diejenigen, die SBT in IntelliJ IDE einbinden möchten: Wie können sbt-Assembly-Aufgaben in IntelliJ IDEA ausgeführt werden?


2
Java / Maven-Vorschlag zum [Problem des Ausschlusses von Spark aus Uber-Gläsern von Databricks databricks.gitbooks.io/databricks-spark-knowledge-base/content/…
JimLohse


1
Was ist der Grund für das Verwerfen von altem META-INF?
Qed

2
Hinweis: Das% "bereitgestellt" bedeutet, dass die Abhängigkeit nicht in die endgültige Fett-JAR aufgenommen wird. Dies hat mir geholfen!
Jayasagar

ernsthaft überrascht, dass dies das einzige verfügbare Plugin ist - nicht einmal offiziell und funktioniert nicht einmal in sbt-Versionen
Abhinandan Dubey

39

3-Schritt-Prozess zum Erstellen von Uber JAR / Fat JAR in IntelliJ Idea:

Uber JAR / Fat JAR : JAR-Datei mit allen externen Bibliotheksabhängigkeiten.

  1. Hinzufügen des SBT Assembly-Plugins in IntelliJ Idea

    Plugin sbt Pfad

    Gehen Sie zur Datei ProjectName / project / target / plugins.sbt und fügen Sie diese Zeile hinzuaddSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")

  2. Hinzufügen der Strategie "Zusammenführen", "Verwerfen" und "Nicht hinzufügen" in build.sbt

    Erstellen Sie den sbt-Pfad

    Gehen Sie zur Datei ProjectName / build.sbt und fügen Sie die Strategie für das Verpacken einer Uber-JAR hinzu

    Zusammenführungsstrategie: Wenn es in zwei Paketen Konflikte um eine Version der Bibliothek gibt, welche in Uber JAR zu packen ist.
    Strategie verwerfen: Zum Entfernen einiger Dateien aus der Bibliothek, die Sie nicht in Uber JAR packen möchten.
    Strategie nicht hinzufügen : Fügen Sie Uber JAR kein Paket hinzu.
    Zum Beispiel: spark-corewird bereits in Ihrem Spark-Cluster vorhanden sein. Daher sollten wir dies nicht in Uber JAR verpacken

    Strategie zusammenführen und Strategie verwerfen Grundlegender Code:

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

    Sie werden daher aufgefordert, META-INF-Dateien mit diesem Befehl zu verwerfen. MergeStrategy.discardFür den Rest der Dateien nehmen Sie das erste Vorkommen einer Bibliotheksdatei, wenn mit diesem Befehl ein Konflikt auftritt MergeStrategy.first.

    Fügen Sie keinen Strategie-Basiscode hinzu:

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

    Wenn wir den Spark-Core nicht zu unserer Uber-JAR-Datei hinzufügen möchten, da er sich bereits in unserem Clutser befindet, fügen wir die % "provided"Bibliotheksabhängigkeit am Ende hinzu .

  3. Erstellen von Uber JAR mit all seinen Abhängigkeiten

    sbtassembly

    Im Terminaltyp sbt assemblyzum Aufbau des Pakets


Voila !!! Uber JAR wird gebaut. JAR befindet sich in ProjectName / target / scala-XX

JarBuilt


16

Fügen Sie Ihrem Projekt / plugins.sbt die folgende Zeile hinzu

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

Fügen Sie Ihrer build.sbt Folgendes hinzu

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
}

Die Zusammenführungsstrategie für Assemblys wird verwendet, um Konflikte zu lösen, die beim Erstellen von Fat Jar aufgetreten sind.


1
Sie können Fat Jar erstellen, indem Sie "sbt Assembly" in der Konsole
ausführen

2
Für Scala Version 2.11.8 (SBT Version: 0.13.12) fügen Sie addSbtPlugin ("com.eed3si9n"% "sbt-Assembly"% "0.12.0") in project / assembly.sbt
ARMV ein
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.