Як створити Uber JAR (Fat JAR) за допомогою SBT в IntelliJ IDEA?


92

Я використовую SBT (в межах IntelliJ IDEA) для побудови простого проекту Scala.

Я хотів би знати, який найпростіший спосіб створити файл Uber JAR (він же Fat JAR, Super JAR).

В даний час я використовую SBT, але коли я надсилаю свій файл JAR до Apache Spark, я отримую таку помилку:

Виняток у потоці "main" java.lang.SecurityException: Недійсний дайджест файлу підпису для основних атрибутів Manifest

Або ця помилка під час компіляції:

java.lang.RuntimeException: deduplicate: різний вміст файлу знайдено у наступному:
PATH \ DEPENDENCY.jar: META-INF / DEPENDENCY
PATH \ DEPENDENCY.jar: META-INF / MANIFEST.MF

Це виглядає як це відбувається тому , що деякі з моїх залежностей включають файли сигнатур (META-INF) , який повинен бути видалений в кінцевому файлі JAR Uber.

Я намагався використовувати плагін sbt-Assembly так:

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

Коли я натискаю " Створити артефакт ... " в IntelliJ IDEA, я отримую файл JAR. Але в підсумку я отримую ту ж помилку ...

Я новачок у SBT і не дуже експериментував з IntelliJ IDE.

Дякую.


2
За звуком речей, можливо, вам доведеться відфільтрувати META-INFфайли - одна публікація в блозі, яка може допомогти: janschulte.wordpress.com/2014/03/20/…
Шон Вієйра,

Відповіді:


147

Нарешті, я повністю пропускаю використання IntelliJ IDEA, щоб уникнути шуму в моєму глобальному розумінні :)

Я почав читати офіційний підручник з SBT .

Я створив свій проект із такою структурою файлів:

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

Додано плагін sbt-Assembly у мій файл Assembly.sbt . Дозвольте мені створити жирний JAR:

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

Мій мінімальний build.sbt виглядає так:

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

Примітка : Засіб % "provided"не включати залежність у остаточний JAR жиру (ці бібліотеки вже включені до моїх працівників)

Примітка : META-INF відкидає натхнення цього відповіді .

Примітка : Значення %та%%

Тепер я можу побудувати свій жирний JAR за допомогою SBT ( як його встановити ), виконавши наступну команду в моїй кореневій папці / my-project :

sbt assembly

Мій жирний JAR тепер знаходиться в новій створеній / цільовій папці:

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

Сподіваюся, це допомагає комусь іншому.


Для тих, хто хоче підкорити SBT в IntelliJ IDE: Як запустити завдання sbt-збірки з IntelliJ IDEA?


2
Пропозиція Java / Maven щодо [проблеми виключення Spark з uber-jar з Databricks databricks.gitbooks.io/databricks-spark-knowledge-base/content/…
JimLohse,

5
Правильне посилання @JimLohse
Zeke Fast

1
У чому причина відмови від старого META-INF?
ч.т.д.

2
Примітка:% "надано" означає не включати залежність до остаточного JAR жиру - це той, який мені допоміг!
Jayasagar

серйозно здивований тим, що це єдиний доступний плагін - навіть не офіційний і навіть не працює у версіях
sbt

40

Триетапний процес побудови Uber JAR / Fat JAR в ідеї IntelliJ:

Uber JAR / Fat JAR : файл JAR, що містить усі зовнішні залежності бібліотеки.

  1. Додавання плагіна SBT Assembly в IntelliJ Idea

    Шлях плагіна sbt

    Перейдіть до файлу ProjectName / project / target / plugins.sbt і додайте цей рядокaddSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")

  2. Додавання стратегії злиття, вилучення та не додавання в build.sbt

    Побудуйте шлях sbt

    Перейдіть до файлу ProjectName / build.sbt і додайте стратегію упаковки JAR-файлів Uber

    Стратегія злиття: якщо у двох пакетах існує конфлікт щодо версії бібліотеки, то який саме упакувати в Uber JAR.
    Стратегія вилучення : видалити деякі файли з бібліотеки, які ви не хочете упаковувати в Uber JAR.
    Не додавати стратегію: Не додавати якийсь пакет до Uber JAR.
    Наприклад: spark-coreвже буде присутній у вашому Spark Cluster, тому ми не повинні упаковувати це в Uber JAR

    Об’єднайте стратегію та викиньте основний код стратегії:

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

    Отже, ви просите відкинути файли META-INF за допомогою цієї команди, MergeStrategy.discardа для інших файлів ви берете перше входження файлу бібліотеки, якщо за допомогою цієї команди виник конфлікт MergeStrategy.first.

    Не додавати основний код стратегії:

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

    Якщо ми не хочемо додавати іскровий сердечник до нашого файлу Uber JAR, оскільки він вже буде в нашому кластері, тому ми додаємо % "provided"кінцеву залежність бібліотеки.

  3. Створення Uber JAR з усіма залежностями

    sbtassembly

    Тип терміналу sbt assemblyдля створення пакета


Вуаля !!! Побудовано Uber JAR. JAR буде в ProjectName / target / scala-XX

JarBuilt


16

Додайте наступний рядок до свого проекту / plugins.sbt

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

Додайте до вашого 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
}

Стратегія злиття Асамблеї використовується для вирішення конфліктів, що виникли під час створення жирного баночки.


1
Ви можете створити жирний Jar, запустивши "sbt Assembly" у консолі
ARMV

2
для версії Scala 2.11.8 (версія SBT: 0.13.12) додайте addSbtPlugin ("com.eed3si9n"% "sbt-Assembly"% "0.12.0") у проект / Assembly.sbt
ARMV
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.