如何在IntelliJ IDEA中使用SBT构建Uber JAR(Fat JAR)?


90

我正在使用SBT(在IntelliJ IDEA中)构建一个简单的Scala项目。

我想知道构建Uber JAR文件(又名Fat JAR,Super JAR)的最简单方法是什么。

我目前正在使用SBT,但是当我将JAR文件提交给Apache Spark时,出现以下错误:

线程“主”中的异常java.lang.SecurityException:清单主要属性的无效签名文件摘要

或在编译期间出现此错误:

java.lang.RuntimeException:重复数据删除:在以下文件中找到了不同的文件内容:
PATH \ DEPENDENCY.jar:META-INF / DEPENDENCIES
PATH \ DEPENDENCY.jar:META-INF / MANIFEST.MF

看起来像那是因为我的一些依赖包括需要在尤伯杯决赛JAR文件被删除签名文件(META-INF)。

我试图像这样使用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中单击“ Build Artifact ... ”时,我得到一个JAR文件。但是我最终遇到了同样的错误...

我是SBT的新手,还没有对IntelliJ IDE进行过尝试。

谢谢。


2
听起来可能需要过滤掉META-INF文件-一篇可能有用的
Sean Vieira

Answers:


144

最后,我完全跳过使用IntelliJ IDEA以避免在我的全局理解中产生噪音:)

我开始阅读官方的SBT教程

我使用以下文件结构创建了我的项目:

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

在我的assembly.sbt文件中添加了sbt-assembly 插件。让我建立一个胖的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丢弃受此答案的启发

注意%和的含义%%

现在,可以通过在/ my-project根文件夹中运行以下命令,使用SBT(如何安装)来构建胖JAR :

sbt assembly

我的胖JAR现在位于新生成的/ target文件夹中:

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

希望对别人有帮助。


对于那些想在IntelliJ IDE中嵌入SBT的人:如何从IntelliJ IDEA中运行sbt-assembly任务?


2
从尤伯杯罐子不包括火花的[问题的Java / Maven的建议从Databricks databricks.gitbooks.io/databricks-spark-knowledge-base/content/...
JimLohse


1
丢弃旧的META-INF的原因是什么?
2016年

2
注意:%“提供”表示不将依赖项包括在最终的胖JAR中,这对我有帮助!
Jayasagar

认真惊讶,这是唯一的插件可用-即使不是官方的,并不会在SBT版本甚至工作
Abhinandan杜贝

40

在IntelliJ Idea中构建Uber JAR / Fat JAR的三步过程:

Uber JAR / Fat JAR:具有所有外部libraray依赖项的JAR文件。

  1. 在IntelliJ Idea中添加SBT Assembly插件

    插件sbt路径

    转到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 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"

    如果我们不想将spark-core添加到我们的Uber JAR文件中,因为它已经在我们的clutser中了,那么我们将% "provided"在它的末尾添加库依赖项。

  3. 使用所有依赖项构建Uber JAR

    sbtassembly

    在终端类型中sbt assembly用于构建包装


瞧!已建立Uber JAR。JAR将位于ProjectName / target / scala-XX中

JarBuilt


16

将以下行添加到您的project / 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
}

Assembly合并策略用于解决创建胖子罐时发生的冲突。


1
您可以通过在控制台中运行“ sbt程序集”来创建胖子Jar
ARMV

2
对于scala版本2.11.8(SBT版本:0.13.12)在项目/assembly.sbt中放入addSbtPlugin(“ com.eed3si9n”%“ sbt-assembly”%“ 0.12.0”)
ARMV
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.