如何有效地使用SBT,Spark和"提供"依赖性?

时间:2016-04-05 21:58:19

标签: intellij-idea apache-spark sbt sbt-assembly

我在Scala中构建Apache Spark应用程序,并且我使用SBT来构建它。事情就是这样:

  1. 当我在IntelliJ IDEA下开发时,我希望Spark依赖项包含在类路径中(我用主类启动常规应用程序)
  2. 当我打包应用程序时(感谢sbt-assembly)插件,我希望Spark依赖项包含在我的胖JAR中
  3. 当我通过sbt test运行单元测试时,我希望Spark依赖项包含在类路径中(与#1相同,但来自SBT)
  4. 为匹配约束#2,我将Spark依赖关系声明为provided

    libraryDependencies ++= Seq(
      "org.apache.spark" %% "spark-streaming" % sparkVersion % "provided",
      ...
    )
    

    然后,sbt-assembly's documentation建议添加以下行以包含单元测试的依赖项(约束#3):

    run in Compile <<= Defaults.runTask(fullClasspath in Compile, mainClass in (Compile, run), runner in (Compile, run))
    

    这使得约束#1没有被完全填充,即我无法在IntelliJ IDEA中运行应用程序,因为没有拾取Spark依赖项。

    使用Maven,我使用特定的配置文件来构建超级JAR。这样,我将Spark依赖关系声明为主要配置文件(IDE和单元测试)的常规依赖关系,同时将它们声明为胖{JAR打包'provided。见https://github.com/aseigneurin/kafka-sandbox/blob/master/pom.xml

    使用SBT实现这一目标的最佳方法是什么?

8 个答案:

答案 0 :(得分:15)

(用我从另一个频道得到的答案回答我自己的问题......)

为了能够从IntelliJ IDEA运行Spark应用程序,您只需在(Get-ChildItem c:\temp -Name) -replace '_.*' | Group-Object -NoElement 目录中创建一个主类( src/test/scala ,而不是{{1} })。 IntelliJ将获取test依赖项。

main

感谢Matthieu Blanc指出这一点。

答案 1 :(得分:6)

在IntelliJ配置中使用新的“包含具有“提供的”作用域的依赖关系”。

IntelliJ config with Provided scope checkbox

答案 2 :(得分:3)

您需要使IntellJ工作。

这里的主要技巧是创建另一个子项目,它将依赖于主子项目,并将在编译范围内提供所有提供的库。为此,我将以下行添加到build.sbt:

lazy val mainRunner = project.in(file("mainRunner")).dependsOn(RootProject(file("."))).settings(
  libraryDependencies ++= spark.map(_ % "compile")
)

现在我在IDEA中刷新项目并稍微更改以前的运行配置,以便它将使用新的mainRunner模块的类路径:

intellj

对我来说完美无瑕。

来源:https://github.com/JetBrains/intellij-scala/wiki/%5BSBT%5D-How-to-use-provided-libraries-in-run-configurations

答案 3 :(得分:2)

[已淘汰]查看新答案“在IntelliJ配置中使用新的'包含依赖关系”提供“范围”。答案。

添加provided依赖项以使用IntelliJ调试任务的最简单方法是:

  • 右键点击src/main/scala
  • 选择Mark Directory as...&gt; Test Sources Root

这告诉IntelliJsrc/main/scala视为一个测试文件夹,它将标记为provided的所有依赖项添加到任何运行配置(调试/运行)。

每次进行SBT刷新时,重做这些步骤,因为IntelliJ会将文件夹重置为常规源文件夹。

答案 4 :(得分:1)

基于创建另一个子项目以在本地运行项目的解决方案描述为here

基本上,您需要使用以下内容修改build.sbt文件:

lazy val sparkDependencies = Seq(
  "org.apache.spark" %% "spark-streaming" % sparkVersion
)

libraryDependencies ++= sparkDependencies.map(_ % "provided")

lazy val localRunner = project.in(file("mainRunner")).dependsOn(RootProject(file("."))).settings(
   libraryDependencies ++= sparkDependencies.map(_ % "compile")
)

然后在运行配置下使用Use classpath of module: localRunner在本地运行新子项目。

答案 5 :(得分:0)

您应该不要在SBT上查看IDEA特定设置。 首先,如果程序应该使用spark-submit运行,那么你如何在IDEA上运行它?我猜你在IDEA中独立运行,而正常通过spark-submit运行它。 如果是这种情况,请使用“文件”|“项目结构”|“库”手动添加IDEA中的spark库。您将看到从SBT列出的所有依赖项,但您可以使用+(加号)符号添加任意jar / maven工件。 这应该够了吧。

答案 6 :(得分:0)

对于运行火花作业,“提供的”依赖项的一般解决方案起作用:https://stackoverflow.com/a/21803413/1091436

然后您可以从sbt或Intellij IDEA或其他任何方式运行该应用程序。

基本上可以归结为:

run in Compile := Defaults.runTask(fullClasspath in Compile, mainClass in (Compile, run), runner in (Compile, run)).evaluated,
runMain in Compile := Defaults.runMainTask(fullClasspath in Compile, runner in(Compile, run)).evaluated

答案 7 :(得分:-1)

为什么不绕过sbt并手动将spark-core和spark-streaming作为库添加到模块依赖项中?

  • 打开“项目结构”对话框(例如⌘;)。
  • 在对话框的左侧窗格中,选择模块。
  • 在右侧窗格中,选择感兴趣的模块。
  • 在对话框的右侧,在“模块”页面上,选择“依赖关系”选项卡。
  • 在“依赖关系”选项卡上,单击“添加”,然后选择“库”。
  • 在“选择库”对话框中,从maven
  • 中选择新库
  • 找到spark-core。前org.apache.spark:spark-core_2.10:1.6.1
  • 利润

https://www.jetbrains.com/help/idea/2016.1/configuring-module-dependencies-and-libraries.html?origin=old_help#add_existing_lib