Я использую 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/ЗАВИСИМОСТИ
PATH\DEPENDENCY.jar: META-INF/MANIFEST.MF
Он выглядит как, потому что некоторые из моих зависимостей включают файлы подписи (META-INF), которые необходимо удалить в финальном файле Uber JAR.
Я попытался использовать плагин 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"
)
)
Когда я нажимаю "Build Artifact..." в IntelliJ IDEA, я получаю файл JAR. Но в итоге я получаю ту же ошибку...
Я новичок в SBT и не очень экспериментировал с IntelliJ IDE.
Спасибо.
Ответ 1
Наконец, я полностью пропускаю использование IntelliJ IDEA, чтобы избежать генерации шума в моем глобальном понимании:)
Я начал читать официальный официальный учебник SBT.
Я создал свой проект со следующей структурой:
my-project/project/assembly.sbt
my-project/src/main/scala/myPackage/MyMainObject.scala
my-project/build.sbt
Добавлен sbt-assembly plugin в мой файл 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")
)
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
}
}
Примечание. % "provided"
означает не включать зависимость в конечный жирный JAR (эти библиотеки уже включены в мои рабочие)
Примечание: META-INF отбрасывает вдохновленный этим анонсом.
Примечание: значение %
и %%
Теперь я могу построить свой полный JAR, используя SBT (как установить его), выполнив следующую команду в моем /my- project:
sbt assembly
Мой толстый JAR теперь находится в новой сгенерированной папке /target:
/my-project/target/scala-2.11/my-project-assembly-1.0.jar
Надеюсь, что это поможет кому-то другому.
Для тех, кто хочет внедрить SBT в IntelliJ IDE: Как запустить задачи сборки sbt из IntelliJ IDEA?
Ответ 2
3 Шаг процесса для сборки JAR JAR/FAT JAR в IntelliJ Идея:
Uber JAR/Fat JAR: файл JAR, имеющий все внешние зависимости между библиотеками.
-
Добавление плагина сборки SBT в Idea IntelliJ
![Плагин sbt Path]()
Перейдите в файл ProjectName/project/target/plugins.sbt и добавьте эту строку addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
-
Добавление слияния, удаления и не добавления стратегии в build.sbt
![Build sbt Path]()
Перейдите в файл ProjectName/build.sbt и добавьте Стратегию упаковки Uber JAR
Стратегия слияния: Если в двух пакетах имеется конфликтная информация о версии библиотеки, то какая из них будет упакована в 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, так как он уже находится на нашем clutser, поэтому мы добавляем % "provided"
в конце его зависимости от библиотеки.
-
Строительство Uber JAR со всеми его зависимостями
![sbtassembly]()
В терминальном типе sbt assembly
для создания пакета
Вуаля!!! Uber JAR построен. JAR будет в ProjectName/target/scala -XX
![JarBuilt]()
Ответ 3
Добавьте в проект следующую строку /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
}
Стратегия слияния сборки используется для разрешения конфликтов, возникающих при создании контейнера с жиром.