Cách tạo Uber JAR (Fat JAR) bằng SBT trong IntelliJ IDEA?


90

Tôi đang sử dụng SBT (trong IntelliJ IDEA) để xây dựng một dự án Scala đơn giản.

Tôi muốn biết cách đơn giản nhất để tạo tệp Uber JAR (còn gọi là Fat JAR, Super JAR).

Tôi hiện đang sử dụng SBT nhưng khi gửi tệp JAR của mình tới Apache Spark, tôi gặp lỗi sau:

Ngoại lệ trong chuỗi "main" java.lang.SecurityException: Thông báo tệp chữ ký không hợp lệ cho các thuộc tính chính của Tệp kê khai

Hoặc lỗi này trong thời gian biên dịch:

java.lang.RuntimeException: debuplicate: nội dung tệp khác nhau được tìm thấy trong phần sau:
PATH \ DEPENDENCY.jar: META-INF / DEPENDENCIES
PATH \ DEPENDENCY.jar: META-INF / MANIFEST.MF

vẻ như đó là do một số phụ thuộc của tôi bao gồm tệp chữ ký (META-INF) cần được xóa trong tệp Uber JAR cuối cùng.

Tôi đã cố gắng sử dụng plugin sbt-assembly như vậy:

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

Khi tôi nhấp vào " Tạo phần mềm ... " trong IntelliJ IDEA, tôi nhận được tệp JAR. Nhưng cuối cùng tôi cũng mắc cùng một lỗi ...

Tôi mới sử dụng SBT và chưa thử nghiệm nhiều với IntelliJ IDE.

Cảm ơn.


2
Theo âm thanh của những thứ bạn có thể cần lọc ra các META-INFtệp - một bài đăng trên blog có thể hữu ích: janschulte.wordpress.com/2014/03/20/…
Sean Vieira

Câu trả lời:


144

Cuối cùng, tôi hoàn toàn bỏ qua việc sử dụng IntelliJ IDEA để tránh tạo ra tiếng ồn trong hiểu biết toàn cầu của tôi :)

Tôi bắt đầu đọc hướng dẫn SBT chính thức .

Tôi đã tạo dự án của mình với cấu trúc tệp sau:

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

Đã thêm plugin sbt-assembly vào tệp assembly.sbt của tôi . Cho phép tôi xây dựng một JAR béo:

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

Build.sbt tối thiểu của tôi trông giống như sau:

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

Lưu ý : Có % "provided"nghĩa là không bao gồm sự phụ thuộc trong JAR chất béo cuối cùng (những thư viện đó đã được đưa vào công nhân của tôi)

Lưu ý : Loại bỏ META-INF lấy cảm hứng từ người trả lời này .

Lưu ý : Ý nghĩa của %%%

Bây giờ tôi có thể xây dựng JAR béo của mình bằng cách sử dụng SBT ( cách cài đặt nó ) bằng cách chạy lệnh sau trong thư mục gốc / my-project của tôi :

sbt assembly

JAR béo của tôi hiện nằm trong thư mục được tạo / đích mới :

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

Hy vọng rằng sẽ giúp một ai đó khác.


Đối với những người muốn giả lập SBT trong IntelliJ IDE: Làm thế nào để chạy các tác vụ lắp ráp sbt từ bên trong IntelliJ IDEA?


2
Đề xuất của Java / Maven về [vấn đề loại trừ Spark khỏi uber-jar khỏi Databricks databricks.gitbooks.io/databricks-spark-knowledge-base/content/…
JimLohse


1
Lý do hủy bỏ META-INF cũ là gì?
qed

2
Lưu ý:% "được cung cấp" có nghĩa là không bao gồm sự phụ thuộc trong JAR chất béo cuối cùng là cái đã giúp tôi!
Jayasagar

ngạc nhiên nghiêm túc rằng đây là chỉ cắm sẵn - thậm chí không chính thức, và không làm việc ngay cả trên phiên bản SBT
Abhinandan Dubey

40

Quy trình 3 bước để xây dựng Uber JAR / Fat JAR trong Ý tưởng IntelliJ:

Uber JAR / Fat JAR : Tệp JAR có tất cả các phụ thuộc vào dải thư viện bên ngoài trong đó.

  1. Thêm plugin SBT Assembly trong IntelliJ Idea

    Đường dẫn sbt của plugin

    Đi tới tệp ProjectName / project / target / plugins.sbt và thêm dòng nàyaddSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")

  2. Thêm chiến lược Hợp nhất, Loại bỏ và Không Thêm trong build.sbt

    Xây dựng đường dẫn sbt

    Tới ProjectName / build.sbt tập tin và thêm Chiến lược Bao bì của một JAR Uber

    Chiến lược Hợp nhất: Nếu có xung đột trong hai gói về phiên bản thư viện thì gói nào sẽ được đóng gói trong Uber JAR.
    Chiến lược loại bỏ : Để xóa một số tệp khỏi thư viện mà bạn không muốn đóng gói trong Uber JAR.
    Không thêm chiến lược: Không thêm một số gói vào Uber JAR.
    Ví dụ: spark-coresẽ có mặt tại Cụm Spark của bạn. Vì vậy, chúng tôi không nên đóng gói điều này trong Uber JAR

    Chiến lược Hợp nhất và Chiến lược Loại bỏ Mã cơ bản:

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

    Vì vậy, bạn đang yêu cầu loại bỏ các tệp META-INF bằng lệnh này MergeStrategy.discardvà đối với phần còn lại của các tệp bạn đang sử dụng lần xuất hiện đầu tiên của tệp thư viện nếu có bất kỳ xung đột nào bằng cách sử dụng lệnh này MergeStrategy.first.

    Không thêm mã cơ bản chiến lược:

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

    Nếu chúng tôi không muốn thêm spark-core vào tệp Uber JAR của mình vì nó đã có sẵn trên trình bán hàng của chúng tôi, vì vậy chúng tôi sẽ thêm phần % "provided"phụ thuộc vào thư viện ở cuối nó.

  3. Xây dựng Uber JAR với tất cả các phụ thuộc của nó

    sbtassembly

    Trong loại thiết bị đầu cuối sbt assemblyđể xây dựng gói


Thì đấy !!! Uber JAR được xây dựng. JAR sẽ có trong ProjectName / target / scala-XX

JarBuilt


16

Thêm dòng sau vào dự án / plugins.sbt của bạn

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

Thêm phần sau vào build.sbt của bạn

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
}

Chiến lược hợp nhất Assembly được sử dụng để giải quyết các xung đột xảy ra khi tạo fat jar.


1
Bạn có thể tạo Jar béo bằng cách chạy "sbt assembly" trong bảng điều khiển
ARMV 17/02/15

2
cho phiên bản scala 2.11.8 (phiên bản SBT: 0.13.12) đặt addSbtPlugin ("com.eed3si9n"% "sbt-assembly"% "0.12.0") trong project / assembly.sbt
ARMV 27/10/16
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.