Search code examples
scalaplayframeworksbt

Play framework multi-project structure: error in routes file


Based on the projects presented here and here I created following directory structure (intentionally omitting UI related files, as I believe they are not important here)

    conf
     - application.config
     - routes ..................... -> / app.Routes
    modules
     - app
        - conf
           - application.conf ..... play.http.router = app.Routes
           - app.routes
        - controllers ............. basic controllers (belong to controller package)
    project
     - build.properties ........... sbt.version=1.7.1
     - plugins.sbt ................ addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.16")
    build.sbt ..................... see bellow

build.sbt

    name := """scala-play-angular-seed"""
    
    version := "1.0-SNAPSHOT"
    
    lazy val root = (project in file(".")).enablePlugins(PlayScala).dependsOn(app).aggregate(app)
    
    lazy val app = (project in file("modules/app")).enablePlugins(PlayScala).settings(
      watchSources ++= (baseDirectory.value / "ui/src" ** "*").get,
      name := "app",
      scalaVersion := "2.13.8",
      libraryDependencies += guice,
      libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "5.1.0" % Test,
      libraryDependencies += "com.h2database" % "h2" % "2.1.214"
    )
    
    resolvers += Resolver.sonatypeRepo("snapshots")
    scalaVersion := "2.13.8"

app.routes

    # Routes
    # This file defines all application routes (Higher priority routes first)
    # ~~~~
    
    # Serve index page from public directory
    GET     /                           controllers.FrontendController.index()
    
    # An example route (Prefix all API routes with apiPrefix defined in application.conf)
    GET     /api/summary                controllers.HomeController.appSummary
    
    # An example route (Prefix all API routes with apiPrefix defined in application.conf)
    GET     /api/segments                controllers.HomeController.getSegments
    
    # Serve static assets under public directory
    GET     /*file                      controllers.app.FrontendController.assetOrDefault(file)
    
    # Test post request
    POST    /api/postTest               controllers.HomeController.postTest()

Whenever I run sbt clean compile I run into an error

    [error] /modules/app/conf/app.routes:6:1: type FrontendController is not a member of package controllers.app
    [error] GET     /                           controllers.app.FrontendController.index()
    [error] /modules/app/conf/app.routes:9:1: type HomeController is not a member of package controllers.app
    [error] GET     /api/summary                controllers.app.HomeController.appSummary
    [error] /modules/app/conf/app.routes:6:1: type FrontendController is not a member of package controllers.app
    [error] GET     /                           controllers.app.FrontendController.index()
    [error] /modules/app/conf/app.routes:9:1: type HomeController is not a member of package controllers.app
    [error] GET     /api/summary                controllers.app.HomeController.appSummary
    [error] four errors found
    [error] (app / Compile / compileIncremental) Compilation failed
    [error] Total time: 6 s, completed 15 Sep 2022, 11:42:52

However, all the controllers are part of the controllers package, and I made sure that the root project depends on the app project that has the package (in build.sbt file by using .dependsOn(App)).

Everything works fine when using single project setup (app resides in the root directory, no extra conf directory and build.sbt consist of only root project).


Solution

  • It turned out, that the used structure didn't really match the template. Play framework expects to find an additional app directory at the conf directory level. Adding another directory at build.sbt level and moving all source files there resolved this issue.