IntelliJ IDEAでSBTを使用してUber JAR(Fat JAR)を構築する方法は?
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
それは、 のように見える これは、私の依存関係の一部に、最終的なUber 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で[Build Artifact ...]をクリックすると、IDEA JARファイルが取得されます。しかし、私は同じエラーになります...
私はSBTを初めて使用しますが、IntelliJ IDEをあまり試していません。
ありがとう。
最後に、IntelliJ IDEAの使用を完全にスキップして、グローバルな理解におけるノイズの生成を回避します:)
公式のSBTチュートリアル を読み始めました。
次のファイル構造でプロジェクトを作成しました。
my-project/project/Assembly.sbt
my-project/src/main/scala/myPackage/MyMainObject.scala
my-project/build.sbt
Assembly.sbtファイルに sbt-Assemblyplugin を追加しました。太い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の破棄 このanswserに触発された 。
これで、/ 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タスクを実行する方法?
IntelliJ IdeaでUber JAR/Fat JARを構築するための3ステップのプロセス:
Uber JAR/Fat JAR:すべての外部ライブラリ依存関係を含むJARファイル。
IntelliJ IdeaにSBT Assemblyプラグインを追加する
ProjectName/project/target/plugins.sbtファイルに移動し、この行を追加します
addSbtPlugin("com.eed3si9n" % "sbt-Assembly" % "0.12.0")
Build.sbtにMerge、DiscardおよびDo Not Add戦略を追加する
ProjectName/build.sbtファイルに移動し、Uber JARのパッケージング戦略を追加します。
マージ戦略:ライブラリのバージョンに関する2つのパッケージに競合がある場合、どちらを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 }
したがって、このコマンド
MergeStrategy.discard
を使用してMETA-INFファイルを破棄し、残りのファイルについては、競合がある場合にライブラリファイルの最初の出現を取得するように求めています。このコマンドを使用してMergeStrategy.first
。戦略基本コードを追加しないでください:
libraryDependencies += "org.Apache.spark" %% "spark-core" % "1.4.1" %"provided"
すでにclutserにあるため、スパークコアをUber JARファイルに追加したくない場合は、ライブラリ依存関係の最後に
% "provided"
を追加します。ターミナルで、パッケージを構築するための
sbt Assembly
と入力します
ボイラ!!! Uber JARが構築されます。 JARはProjectName/target/scala-XXにあります
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
}
アセンブリのマージ戦略は、ファットjarの作成時に発生した競合を解決するために使用されます。