首页 > 解决方案 > 为 Scala 项目生成可执行 Jar

问题描述

我有一个包含多个主要方法的 scala 项目。我想生成一个胖 jar,以便我可以运行与主要方法相关的代码之一。

构建.sbt

lazy val commonSettings = Seq(
  version := "0.1-SNAPSHOT",
  organization := "my.company",
  scalaVersion := "2.11.12",
  test in assembly := {}
)

lazy val app = (project in file("app")).
  settings(commonSettings: _*).
  settings(
    mainClass in assembly := Some("my.test.Category")
  )
assemblyMergeStrategy in assembly := {
  case "reference.conf" => MergeStrategy.concat
  case "META-INF/services/org.apache.spark.sql.sources.DataSourceRegister" => MergeStrategy.concat
  case PathList("META-INF", xs@_*) => MergeStrategy.discard
  case _ => MergeStrategy.first
}

插件.sbt

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

通过这个清单文件在我的资源文件夹中成功生成。

接下来我运行sbt 程序集并成功生成可执行 jar。

当我运行 java -jar category-assembly-0.1.jar 我得到以下错误

没有主要清单属性,在 category-assembly-0.1.jar 中

我尝试了互联网上给出的许多步骤,但我不断收到此错误

更新

目前以下包含在我的 build.sbt 中。

lazy val spark: Project = project
  .in(file("./spark"))
  .settings(
    mainClass in assembly := Some("my.test.Category"),
      mainClass in (Compile, packageBin) := Some("my.test.Category"),
    mainClass in (Compile, run) := Some("my.test.Category")
  )
assemblyMergeStrategy in assembly := {
  case "reference.conf" => MergeStrategy.concat
  case "META-INF/services/org.apache.spark.sql.sources.DataSourceRegister" => MergeStrategy.concat
  case PathList("META-INF", xs@_*) => MergeStrategy.discard
  case _ => MergeStrategy.first
}

在构建工件并运行命令 sbt assembly 并尝试运行生成的 jar 后,我仍然得到相同的错误,如下所示

没有主要清单属性,在 category-assembly-0.1.jar 中

标签: scalasbtexecutable-jar

解决方案


我在 EMR 上部署时遇到了同样的问题。

将以下内容添加到 build.sbt 中的设置中就可以了。

lazy val spark: Project = project
  .in(file("./spark"))
  .settings(
     ...

     // set the main class for packaging the main jar
     mainClass in (Compile, packageBin) := Some("com.orgname.name.ClassName"),
     mainClass in (Compile, run) := Some("com.orgname.name.ClassName"),
     ...

  )

这实际上将项目中现有类的名称设置为默认 mainClass。我为 packageBin 设置并运行,所以你应该没问题。

只是不要忘记将 重命名com.orgname.name.ClassName为您的类名。

(这只是为了刷新你的记忆)

类名由<PackageName>/<ClassName>.

例如:

package com.orgname.name

object ClassName {}

推荐阅读