Как эффективно работать с SBT, Spark и "предоставленными" зависимостями?
Я создаю приложение Apache Spark в Scala, и я использую SBT для его создания. Вот что:
- когда я разрабатываю IntelliJ IDEA, я хочу, чтобы зависимости Spark были включены в путь к классам (я запускаю регулярное приложение с основным классом)
- когда я упаковываю приложение (благодаря плагину sbt-assembly), я не хочу, чтобы зависимости Spark были включены в мой полный JAR
- когда я запускаю модульные тесты через
sbt test
, я хочу, чтобы зависимости Spark включались в путь к классам (такой же, как # 1, но из SBT).
Чтобы сопоставить ограничение # 2, я объявляю зависимости Spark как provided
:
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-streaming" % sparkVersion % "provided",
...
)
Затем документация по сборке sbt предлагает добавить следующую строку для включения зависимостей для модульных тестов (ограничение # 3):
run in Compile <<= Defaults.runTask(fullClasspath in Compile, mainClass in (Compile, run), runner in (Compile, run))
Это оставляет меня с ограничением # 1 не заполненным, т.е. я не могу запустить приложение в IntelliJ IDEA, поскольку зависимости Spark не подхватываются.
С Maven я использовал конкретный профиль для создания UBER JAR. Таким образом, я объявлял зависимости Spark как регулярные зависимости для основного профиля (IDE и модульные тесты), объявляя их как provided
для полной упаковки JAR. См. https://github.com/aseigneurin/kafka-sandbox/blob/master/pom.xml
Каков наилучший способ добиться этого с помощью SBT?
Ответы
Ответ 1
(Отвечая на мой вопрос с ответом, полученным с другого канала...)
Чтобы иметь возможность запускать приложение Spark из IntelliJ IDEA, вам просто нужно создать основной класс в каталоге src/test/scala
( test
, а не main
). IntelliJ получит зависимости provided
.
object Launch {
def main(args: Array[String]) {
Main.main(args)
}
}
Спасибо Matthieu Blanc за то, что указали это.
Ответ 2
Используйте новый "Включить зависимости с" Предоставленной "областью действия" в конфигурации IntelliJ.
![IntelliJ config with Provided scope checkbox]()
Ответ 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
Ответ 4
[Устарело] См. Новый ответ "Используйте новую" Включить зависимости с "Предоставленной областью действия" в конфигурацию IntelliJ "." ответ.
Самый простой способ добавить provided
зависимости для отладки задачи с IntelliJ
- это:
- Щелкните правой кнопкой мыши
src/main/scala
- Выберите "
Mark Directory as...
> " Test Sources Root
Это говорит IntelliJ
обрабатывать src/main/scala
как тестовую папку, для которой он добавляет все зависимости, помеченные как provided
для любого запуска конфигурации (отладка/запуск).
Каждый раз, когда вы выполняете обновление SBT, повторяйте эти шаги, поскольку IntelliJ будет сбрасывать папку в обычную исходную папку.
Ответ 5
Решение, основанное на создании другого подпроекта для локального запуска проекта, описано здесь.
В принципе, вам нужно модифицировать файл 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
в разделе "Конфигурация запуска".
Ответ 6
Вы не должны смотреть на SBT для конкретной настройки IDEA.
Прежде всего, если программа должна быть запущена с помощью spark-submit, как вы ее используете на IDEA? Я предполагаю, что вы будете работать как автономно в IDEA, пока запускаете его через искру - подчиняйтесь нормально.
Если это так, добавьте вручную библиотеки искры в IDEA, используя File | Project Structure | Libraries. Вы увидите все зависимости, перечисленные в SBT, но вы можете добавить произвольные артефакты jar/maven, используя знак + (плюс).
Это должно делать свое дело.
Ответ 7
Для запуска искровых заданий используется общее решение "предоставленных" зависимостей: fooobar.com/questions/170609/...
Это в основном сводится к этому:
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
Ответ 8
Почему бы не обойти sbt и вручную добавить искровые ядра и искровые потоки в качестве библиотек в зависимости от вашего модуля?
- Откройте диалоговое окно "Структура проекта" (например, ⌘;).
- В левой панели диалогового окна выберите "Модули".
- На панели справа выберите интересующий модуль.
- В правой части диалогового окна на странице "Модуль" выберите вкладку "Зависимости".
- На вкладке "Зависимости" нажмите "Добавить" и выберите "Библиотека".
- В диалоговом окне "Выбор библиотек" выберите новую библиотеку, из maven
- Найдите искровой стержень. Ex
org.apache.spark:spark-core_2.10:1.6.1
- Profit
https://www.jetbrains.com/help/idea/2016.1/configuring-module-dependencies-and-libraries.html?origin=old_help#add_existing_lib