如何设置 sbt/scala/play 可以与 Intellij scala 插件一起正常工作的多模块项目
How to setup sbt/scala/play multi-module project which will work fine with Intellij scala plugin
我正在建立一个新的多模块项目 (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 插件(Run/Debug 配置)
到目前为止,当我 运行 使用 Play2 Run/Debug 配置设置的应用程序时出现以下错误:
[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)
}
plugin.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")
运行 配置
考虑更改构建结构,使 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 Task
- 在
tasks
输入框中输入api/run
- 应用更改并select确定。
背景语境,随意跳过:
最新版本的 Intellij 运行 在使用 Play2 文档中定义的 sbt task
运行 配置时出现路由编译问题。所以我想使用 Play 2 App
运行 配置作为替代。
虽然 Mario 的解决方案有效,但对于那些无法移动基本目录的人来说,这不是一个选择。尝试使用 Play 2 App
运行 配置会导致 No main class detected
类似于 Aleksandar 在开始问题的评论中所经历的。
解决方案
要使用 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
作为主要 class 方法的模块。
调试端口应该是您在断点侦听器的设置中指定的端口。默认不用改。
运行 您新创建的 运行 配置。日志输出应该类似于 运行ning sbt via bash。示例如下。
如果启动失败,请确保您没有在 Scala 和 JVM 的默认设置中重复声明 JVM 参数。
我正在建立一个新的多模块项目 (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 插件(Run/Debug 配置)
到目前为止,当我 运行 使用 Play2 Run/Debug 配置设置的应用程序时出现以下错误:
[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)
}
plugin.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")
运行 配置
考虑更改构建结构,使 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
运行 配置再次工作,尽管通过检查
Preferences | Languages & Frameworks | Play2 | Compiler | Use Play 2 compiler for this project
如果希望保留原始结构,那么作为解决方法,尝试定义 sbt Task
运行 配置而不是 Play 2 App
,如官方 docs 中所述:
Run | Edit Configurations
- 点击
+
添加新配置 - 选择
sbt Task
- 在
tasks
输入框中输入api/run
- 应用更改并select确定。
背景语境,随意跳过:
最新版本的 Intellij 运行 在使用 Play2 文档中定义的 sbt task
运行 配置时出现路由编译问题。所以我想使用 Play 2 App
运行 配置作为替代。
虽然 Mario 的解决方案有效,但对于那些无法移动基本目录的人来说,这不是一个选择。尝试使用 Play 2 App
运行 配置会导致 No main class detected
类似于 Aleksandar 在开始问题的评论中所经历的。
解决方案
要使用 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
作为主要 class 方法的模块。调试端口应该是您在断点侦听器的设置中指定的端口。默认不用改。
运行 您新创建的 运行 配置。日志输出应该类似于 运行ning sbt via bash。示例如下。
如果启动失败,请确保您没有在 Scala 和 JVM 的默认设置中重复声明 JVM 参数。