如何设置 sbt/scala/play 多模块项目,该项目将与 Intellij scala 插件一起正常工作

Posted

技术标签:

【中文标题】如何设置 sbt/scala/play 多模块项目,该项目将与 Intellij scala 插件一起正常工作【英文标题】:How to setup sbt/scala/play multi-module project which will work fine with Intellij scala plugin 【发布时间】:2019-10-17 20:31:04 【问题描述】:

我正在建立一个新的多模块项目 (sbt/scala/play/IntejjiJ),我想要两件事:

    一个多模块项目,其中包含一个带有此布局的 build.sbt 文件
project
 |_Dependencies.scala
 |_plugin.sbt
modules
 |_adapters
   |_api (Play REST API)
     |_app
     |_conf
   |_infrastructure (bare bone scala)
     |-src/main/scala
 |_application (bare bone scala)
   |_src/main/scala
 |_domain (bare bone scala)
   |_src/main/scala
 |_query (bare bone scala)
   |_src/main/scala 
build.sbt
    我希望能够使用 IntelliJ Play2 插件(运行/调试配置)

到目前为止,当我使用 Play2 运行/调试配置设置运行应用程序时出现以下错误:

[error] java.lang.RuntimeException: No main class detected.
[error]     at scala.sys.package$.error(package.scala:26)
[error] (Compile / bgRun) No main class detected.
[error] Total time: 2 s, completed Jun 1, 2019 11:21:31 PM

这是我目前所拥有的:

build.sbt

import Dependencies._

lazy val commonSettings = Seq(
  organization := "com.borkke.rally",
  version := "0.1.0-SNAPSHOT",
  scalaVersion := "2.12.8",
  scalacOptions := Seq(
    "-deprecation",
    "-feature"
  ),
  libraryDependencies ++= CommonDependencies
)


//PROJECTS
lazy val rally = project
  .in(file("."))
  .aggregate(domain,application,query,api,infrastructure)
  .settings(
    name := "rally",
    commonSettings,
    publishArtifact := false
  )

lazy val api = project
  .in(file("modules/adapter/api"))
  .enablePlugins(PlayScala)
  .dependsOn(domain,application,query,infrastructure)
  .settings(
    name := "api",
    commonSettings,
    libraryDependencies ++= ApiDependencies
  )

lazy val domain = project
  .in(file("modules/domain"))
  .settings(
    name := "domain",
    commonSettings
  )

lazy val application = project
  .in(file("modules/application"))
  .dependsOn(domain)
  .settings(
    name := "application",
    commonSettings
  )

lazy val query = project
  .in(file("modules/query"))
  .settings(
    name := "query",
    commonSettings
  )

lazy val infrastructure = project
  .in(file("modules/adapter/infrastructure"))
  .dependsOn(domain)
  .settings(
    name := "infrastructure",
    commonSettings,
    libraryDependencies ++= InfrastructureDependencies
  )

Dependencies.scala

import sbt._
import play.sbt.PlayImport._

object Dependencies 
  private val scalatest_version = "3.0.5"
  private val v2Db_version = "1.4.198"
  private val logback_version = "5.3"
  private val play_version = "2.7.2"
  private val cassandra_driver_version = "3.7.1"
  private val postgresql_driver_version = "42.2.5"
  private val kafka_client_version = "2.2.0"

  private val scalatest = "org.scalatest" %% "scalatest" % scalatest_version
  private val scalatic = "org.scalactic" %% "scalactic" % scalatest_version
  private val h2Db = "com.h2database" %% "h2" % v2Db_version
  private val logback = "net.logstash.logback" % "logstash-logback-encoder" % logback_version
  private val play = "com.typesafe.play" %% "play" % play_version
  private val cassandra_driver = "com.datastax.cassandra" % "cassandra-driver-extras" % cassandra_driver_version
  private val postgresql_driver = "org.postgresql" % "postgresql" % postgresql_driver_version
  private val kafka_client = "org.apache.kafka" %% "kafka" % kafka_client_version

  lazy val CommonDependencies = Seq(scalatic, scalatest % "test", logback, guice)

  lazy val InfrastructureDependencies = Seq(cassandra_driver, postgresql_driver, kafka_client)

  lazy val ApiDependencies = Seq(play)

插件.sbt

logLevel := Level.Warn

//wrapper around play console.
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.2")

//dependency resolver. parallel downloads
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.1.0-M11")

//shows available updates. dependencyUpdates || dependencyUpdatesReport
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.4.0")

//create one jar for application.
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.5")

//linter
addSbtPlugin("org.wartremover" % "sbt-wartremover" % "2.2.1")

运行配置

【问题讨论】:

如果我了解您对 IntelliJ 没有问题,您在 Play 中遇到问题找不到您的 application.conf wchis 可能是 Play Framework 插件配置的众多困难之一:playframework.com/documentation/2.1.x/SBTSubProjects -尝试运行sbt "show resourceDirectory" 来检查项目中的资源目录。 这列出了所有其他模块中的所有资源目录,但具有 Play 应用程序(“api”模块)的目录除外。 我玩得更多了,最后我将.enablePlugins(PlayScala) 移动到了 api 模块...之后,当我使用 cli 命令运行应用程序 sbt api/run 时,它工作正常。但是使用 scala 插件,它没有。它抛出这个错误:``` [error] java.lang.RuntimeException: No main class detected。 [error] at scala.sys.package$.error(package.scala:26) [error] (Compile / bgRun) 未检测到主类。 [错误] 总时间:1 秒,完成时间为 2019 年 6 月 1 日晚上 10:44:14 进程完成,退出代码为 1 ``` 这是我当前设置的要点:gist.github.com/borkke/3a6c69cb9e76fea554451ca39c1002ed 能否添加intellij运行配置截图 【参考方案1】:

考虑更改构建结构,将api 移动为根项目,如下所示:

lazy val api = project
  .in(file("."))
  .enablePlugins(PlayScala)
  .aggregate(domain,application,query,infrastructure)
  .dependsOn(domain,application,query,infrastructure)
  .settings(
    name := "api",
    commonSettings,
    publishArtifact := false,
    libraryDependencies ++= ApiDependencies
  )

这意味着modules/adapters/api移动到项目根目录,lazy val root = ...build.sbt中删除,这样目录结构就变成了

.
├── app
│   ├── controllers
│   ├── filters
│   ├── services
│   └── views
├── build.sbt
├── conf
│   ├── application.conf
│   ├── logback.xml
│   └── routes
├── modules
│   ├── adapters
│   │   └── infrastructure
│   ├── application
│   │   ├── src
│   ├── domain
│   │   ├── src
│   └── query
│       ├── src
├── project
│   ├── Dependencies.scala
│   ├── build.properties
│   ├── plugins.sbt
│   ├── project
│   └── target

这应该使Play 2 App 运行配置再次工作,尽管通过检查确保启用 Play 编译器:

Preferences | Languages & Frameworks | Play2 | Compiler | Use Play 2 compiler for this project

如果希望保留原始结构,则作为一种解决方法,尝试定义sbt Task 运行配置而不是Play 2 App,如官方docs 中所述:

    Run | Edit Configurations 点击+添加新配置 选择sbt Tasktasks输入框中输入api/run 应用更改并选择确定。

【讨论】:

感谢马里奥的详细回答。我目前正在使用您提到的解决方法。无论如何,Web 框架/工具迫使您以特定方式构建应用程序,这太糟糕了。【参考方案2】:

背景背景,随意跳过:

最新版本的 Intellij 在使用 Play2 文档中定义的 sbt task 运行配置时遇到路由编译问题。所以我想使用Play 2 App 运行配置作为替代。

虽然马里奥的解决方案有效,但对于那些无法移动基本目录的人来说,它不是一个选择。尝试使用 Play 2 App 运行配置会导致 No main class detected 类似于 Aleksandar 在开场问题的 cmets 中所经历的。

解决方案

要使用 Play 2 App 运行配置,您必须:

    像往常一样在build.sbt 中指定项目。

    使用build.sbt 指定项目的 Play2 模块和项目 uri。除非在步骤 1 中更改,否则这将是 Play2 的默认值:分别为项目名称和项目根目录。

    在此处找到相关设置:

    File | Settings | Languages & Frameworks | Play2

    如下图所示,我还检查了Use Play 2 compiler for this project

    创建一个Play 2 App 运行配置并将Play 2 module 指定为您的主类方法的模块。

    调试端口应该是您在设置中为断点侦听器指定的端口。默认不需要更改。

    运行您新创建的运行配置。日志输出看起来应该类似于通过 bash 运行 sbt 的输出。下面的例子。

如果无法启动,请确保在 Scala 和 JVM 的默认设置中没有重复的 JVM 参数声明。

【讨论】:

以上是关于如何设置 sbt/scala/play 多模块项目,该项目将与 Intellij scala 插件一起正常工作的主要内容,如果未能解决你的问题,请参考以下文章

如何在多目录项目中正确导入 python 模块?

多工程联编的Pods如何设置

如何在 Eclipse 中正确设置由 appfuse 创建的多模块 SpringMVC 应用程序?

如何将maven多模块spring boot部署到docker容器

提供两个不同战争的多模块项目

管理多模块项目