Как создать 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: недействительный дайджест файла подписи для основных атрибутов манифеста

Или эта ошибка во время компиляции:

java.lang.RuntimeException: deduplicate: различное содержимое файла, обнаруженное в следующем:
PATH \ DEPENDENCY.jar: META-INF / DEPENDENCIES
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 / my-project :

sbt assembly

Мой толстый JAR теперь находится в новой сгенерированной / целевой папке:

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

Надеюсь, это поможет кому-то другому.


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

Ив М.
источник
2
Предложение Java / Maven по [проблеме исключения Spark из uber-jar из Databricks databricks.gitbooks.io/databricks-spark-knowledge-base/content/…
JimLohse
5
Правильная ссылка @JimLohse
Зик Фаст,
1
В чем причина отказа от старого META-INF?
Qed 01
2
Примечание:% "provided" означает, что зависимость не включается в окончательный JAR-файл. Это тот, который мне помог!
Jayasagar
серьезно удивлен, что это единственный доступный плагин - даже не официальный и даже не работает с версиями
sbt
40

Трехэтапный процесс создания Uber JAR / Fat JAR в IntelliJ Idea:

Uber JAR / Fat JAR : JAR-файл, в котором есть все внешние зависимости libraray.

  1. Добавление подключаемого модуля SBT Assembly в IntelliJ Idea

    Плагин sbt Path

    Перейдите в файл ProjectName / project / target / plugins.sbt и добавьте эту строкуaddSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")

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

    Создать путь к sbt

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

    Стратегия слияния: если в двух пакетах есть конфликт из-за версии библиотеки, то какую из них упаковать в Uber JAR.
    Стратегия сброса: удалить из библиотеки некоторые файлы, которые вы не хотите упаковывать в Uber JAR.
    Не добавлять стратегию: не добавлять какой-либо пакет в Uber JAR.
    Например: spark-coreуже будет присутствовать в вашем кластере Spark, поэтому мы не должны упаковывать его в 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, поскольку он уже находится в нашем clutser, мы добавляем % "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
}

Стратегия объединения сборок используется для разрешения конфликтов, возникших при создании толстой банки.

ARMV
источник
1
Вы можете создать толстый Jar, запустив "sbt assembly" в консоли
ARMV
2
для scala версии 2.11.8 (версия SBT: 0.13.12) поместите addSbtPlugin ("com.eed3si9n"% "sbt-assembly"% "0.12.0") в project / assembly.sbt
ARMV