Bagaimana cara membuat Uber JAR (Fat JAR) menggunakan SBT dalam IntelliJ IDEA?

92

Saya menggunakan SBT (dalam IntelliJ IDEA) untuk membangun proyek Scala sederhana.

Saya ingin tahu cara termudah untuk membuat file Uber JAR (alias Fat JAR, Super JAR).

Saya saat ini menggunakan SBT tetapi ketika saya mengirimkan file JAR saya ke Apache Spark, saya mendapatkan kesalahan berikut:

Pengecualian di thread "main" java.lang.SecurityException: Intisari file tanda tangan tidak valid untuk atribut utama Manifest

Atau kesalahan ini selama waktu kompilasi:

java.lang.RuntimeException: deduplicate: konten file berbeda ditemukan sebagai berikut:
PATH \ DEPENDENCY.jar: META-INF / DEPENDENCIES
PATH \ DEPENDENCY.jar: META-INF / MANIFEST.MF

Ini terlihat seperti itu karena beberapa dependensi saya menyertakan file tanda tangan (META-INF) yang perlu dihapus di final file JAR Uber.

Saya mencoba menggunakan plugin sbt-assembly seperti itu:

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

Ketika saya mengklik " Build Artifact ... " di IntelliJ IDEA saya mendapatkan file JAR. Tapi saya berakhir dengan kesalahan yang sama ...

Saya baru mengenal SBT dan tidak terlalu bereksperimen dengan IntelliJ IDE.

Terima kasih.

Yves M.
sumber
2
Berdasarkan hal-hal yang mungkin Anda perlukan untuk memfilter META-INFfile - satu entri blog yang mungkin membantu: janschulte.wordpress.com/2014/03/20/…
Sean Vieira

Jawaban:

147

Akhirnya saya benar-benar melewatkan penggunaan IntelliJ IDEA untuk menghindari menimbulkan kebisingan dalam pemahaman global saya :)

Saya mulai membaca tutorial SBT resmi .

Saya membuat proyek saya dengan struktur file berikut:

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

Menambahkan plugin sbt-assembly di file assembly.sbt saya . Mengizinkan saya membuat JAR yang gemuk:

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

Build.sbt minimal saya terlihat seperti:

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

Catatan : Cara % "provided"untuk tidak menyertakan dependensi di JAR lemak akhir (pustaka tersebut sudah termasuk dalam pekerja saya)

Catatan : Pembuangan META-INF terinspirasi oleh jawaban ini .

Catatan : Arti %dan%%

Sekarang saya dapat membuat JAR gemuk saya menggunakan SBT ( cara menginstalnya ) dengan menjalankan perintah berikut di folder root / my-project :

sbt assembly

JAR lemak saya sekarang terletak di folder yang dibuat / target baru :

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

Harapan yang membantu orang lain.


Bagi mereka yang ingin menanamkan SBT dalam IntelliJ IDE: Bagaimana cara menjalankan tugas sbt-assembly dari dalam IntelliJ IDEA?

Yves M.
sumber
2
Saran Java / Maven tentang [masalah mengecualikan Spark dari uber-jars dari Databricks databricks.gitbooks.io/databricks-spark-knowledge-base/content/…
JimLohse
5
Tautan @JimLohse yang tepat adalah databricks.gitbooks.io/databricks-spark-knowledge-base/content/…
Zeke Fast
1
Apa alasan untuk membuang META-INF lama?
qed
2
Catatan:% "disediakan" berarti tidak menyertakan ketergantungan di JAR lemak akhir adalah yang membantu saya!
Jayasagar
sangat terkejut bahwa ini adalah satu-satunya plugin yang tersedia - bahkan tidak resmi, dan bahkan tidak berfungsi di seluruh versi sbt
Abhinandan Dubey
40

Proses 3 Langkah Untuk Membangun Uber JAR / Fat JAR di IntelliJ Idea:

Uber JAR / Fat JAR : File JAR yang memiliki semua dependensi libraray eksternal di dalamnya.

  1. Menambahkan plugin SBT Assembly di IntelliJ Idea

    Jalur sbt plugin

    Buka file ProjectName / project / target / plugins.sbt dan tambahkan baris iniaddSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")

  2. Menambahkan Merge, Discard dan Do Not Add strategy di build.sbt

    Bangun Path sbt

    Buka file ProjectName / build.sbt dan tambahkan Strategi Pengemasan JAR Uber

    Merge Strategy: Jika ada konflik dalam dua paket tentang sebuah versi library, paket mana yang akan dikemas di Uber JAR.
    Strategi Buang: Untuk menghapus beberapa file dari perpustakaan yang tidak ingin Anda paketkan di Uber JAR.
    Jangan Tambahkan Strategi: Jangan menambahkan beberapa paket ke Uber JAR.
    Misalnya: spark-coresudah ada di Spark Cluster Anda, jadi kami tidak boleh mengemasnya di Uber JAR

    Gabungkan Kode Dasar Strategi dan Buang Strategi:

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

    Jadi, Anda meminta untuk membuang file META-INF menggunakan perintah ini MergeStrategy.discarddan untuk file lainnya yang Anda ambil adalah kejadian pertama dari file perpustakaan jika ada konflik dengan menggunakan perintah ini MergeStrategy.first.

    Jangan Tambahkan Kode Dasar Strategi:

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

    Jika kami tidak ingin menambahkan spark-core ke file Uber JAR kami karena sudah ada di clutser kami, jadi kami menambahkan % "provided"dependensi library di bagian akhir.

  3. Membangun Uber JAR dengan semua dependensinya

    sbtassembly

    Dalam tipe terminal sbt assemblyuntuk membangun paket


Voila !!! Uber JAR dibuat. JAR akan ada di ProjectName / target / scala-XX

JarBuilt

Ajay Gupta
sumber
16

Tambahkan baris berikut ke project / plugins.sbt Anda

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

Tambahkan berikut ini ke build.sbt Anda

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
}

Strategi penggabungan Assembly digunakan untuk menyelesaikan konflik yang terjadi saat membuat fat jar.

ARMV
sumber
1
Anda dapat membuat Jar gemuk dengan menjalankan "perakitan sbt" di konsol
ARMV
2
untuk scala versi 2.11.8 (versi SBT: 0.13.12) letakkan addSbtPlugin ("com.eed3si9n"% "sbt-assembly"% "0.12.0") di project / assembly.sbt
ARMV