Scala Play: can't run two different play apps at the same time in a multi-project SBT setup

38 Views Asked by At

I have an SBT project, used for e2e tests, that has dependencies on two other SBT projects. I want to run both the other SBT projects alongside each other. However, there seems to be classpath conflicts as no matter what config I try to override, it will always load the first project introduced using .dependsOn() in the SBT config. E.g.:

lazy val e2eTest = project
  .in(file("e2e-test"))
  .disablePlugins(ScroogeSBT)
  .dependsOn(tracker % "compile->compile;test->test")
  .dependsOn(theSlab % "compile->compile;test->test")
  .settings(standardSettingsWithLibraryDependencies: _*)
  .settings(buildTrackerJS := runScript("./tracker-js/build.sh"))
  .settings(
    (Test / test) := ((Test / test) dependsOn buildTrackerJS).value,
    Test / javaOptions ++= Seq(
      "--add-exports=java.base/sun.security.x509=ALL-UNNAMED",
      "--add-opens=java.base/sun.security.ssl=ALL-UNNAMED"
    ),
    libraryDependencies ++= List(
      "pekko-actor",
      "pekko-actor-typed",
      "pekko-protobuf-v3",
      "pekko-serialization-jackson",
      "pekko-slf4j",
      "pekko-stream"
    ).map { art => "org.apache.pekko" %% art % "1.0.1" },
    libraryDependencies ++= List(
      "org.scalatest" %% "scalatest" % scalaTestVersion % Test,
      "org.scalatestplus" %% "selenium-4-12" % "3.2.17.0" % Test,
      "org.scalatestplus.play" %% "scalatestplus-play" % "5.1.0" % Test,
      "io.github.bonigarcia" % "webdrivermanager" % "5.6.2" % Test,
      "com.lihaoyi" %% "os-lib" % "0.9.2" % Test,
      "com.lihaoyi" %% "cask" % "0.9.1" % Test,
      "com.lihaoyi" %% "scalatags" % "0.12.0" % Test,
      "io.circe" %% "circe-core" % "0.14.6" % Test,
      "io.circe" %% "circe-parser" % "0.14.6" % Test
    )
  )

With this config, 'tracker' will always be loaded even when starting a play server with the following code:

package configuration

import theSlab.BuildInfo
import play.api.{Application, ApplicationLoader, Configuration, Environment, LoggerConfigurator}
import play.api.ApplicationLoader.Context

class TheSlabApplicationLoader extends ApplicationLoader {
  def load(context: Context): Application = {
    LoggerConfigurator(context.environment.classLoader).foreach { configurator =>
      configurator.configure(
        context.environment,
        context.initialConfiguration,
        Map("buildNumber" -> BuildInfo.buildNumber)
      )
    }

    val customConfig = Configuration.load(context.environment, Map("config.resource" -> "theSlab.conf", "play.application.loader" -> "configuration.TheSlabApplicationLoader"))

    val combinedConfig = context.initialConfiguration ++ customConfig
    
    val newContext = context.copy(initialConfiguration = combinedConfig)
    new AppComponents(newContext).application
  }
}

  def playTestServer: DefaultTestServerFactory =
    new DefaultTestServerFactory() {
      override def serverConfig(app: Application) = {
        val sc = ServerConfig(
          port = Some(0),
          sslPort = None,
          mode = Mode.Test,
          rootDir = app.path
        )
        sc.copy(configuration =
          sc.configuration ++ overrideServerConfiguration(app)
        )
      }
    }

theSlabServer = {
      val env = Environment.simple(path = new File("../the-slab"))
      val context = Context.create(env)
      val slabLoader = new TheSlabApplicationLoader()
      Option(playTestServer.start(slabLoader.load(context)))
}

If I switch the .dependsOn() statements around, it will always load the other project. Why is this and how can I fix it?

0

There are 0 best solutions below