Vikram
Vikram

Reputation: 333

Properly adding a SBT subproject to a Scala Play project

I'm trying to leverage some existing code with a new Scala Play project. I'm attempting to do this by adding the existing project as a sub-project to my Scala Play project by following the instructions here.

However, I am unable to figure out how to access objects in the subproject from the parent project. For example, I'm trying to create Scala Play singleton object that provides an instance of an object from the subproject.

package services
import javax.inject.Singleton

@Singleton
class EngineProvider {

  var instance: Engine = _

  def getEngine: Engine = {
    if (instance == null) {
      instance = new ScalaPlayEngine()
    }
    instance
  }
}

However, my Intellij cannot find a way to import Engine, or ScalaPlayEngine (both objects are from my subproject). I can "trick" Intellij into removing it's errors by importing the following:

import _root_.Engine
import _root_.ScalaPlayEngine

But when I actually try to run the Play project, I still get an error:

play.sbt.PlayExceptions$CompilationException: Compilation error[_root_ cannot be imported]
        at play.sbt.PlayExceptions$CompilationException$.apply(PlayExceptions.scala:27)
        at play.sbt.PlayExceptions$CompilationException$.apply(PlayExceptions.scala:27)
        at scala.Option.map(Option.scala:145)
        at play.sbt.run.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:49)
        at play.sbt.run.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:44)
        at scala.Option.map(Option.scala:145)
        at play.sbt.run.PlayReload$.taskFailureHandler(PlayReload.scala:44)
        at play.sbt.run.PlayReload$.compileFailure(PlayReload.scala:40)
        at play.sbt.run.PlayReload$$anonfun$compile$1.apply(PlayReload.scala:17)
        at play.sbt.run.PlayReload$$anonfun$compile$1.apply(PlayReload.scala:17)

My parent (Scala Play) project build.sbt file contains this:

lazy val root = (project in file("."))
  .enablePlugins(PlayScala)
  .aggregate(engine)
  .dependsOn(engine)

lazy val engine = project

so I would have expected it to be able to pick up any objects from the sub project (since it depends on it). My project structure looks something like this:

ParentScalaPlayProject
  build.sbt
  app
    services
      EngineProvider.scala
  .
  .
  .
  engine (child project)
    build.sbt
    src
      main
        scala
          Engine.scala
          ScalaPlayEngine.scala
    .
    .
    .

I'm very new to both SBT and Scala Play, so it's very likely I'm missing something obvious here. Thanks in advance!

Upvotes: 1

Views: 463

Answers (1)

jqno
jqno

Reputation: 15520

Your error message says: Compilation error[_root_ cannot be imported]

According to the Scala Language Specification, Section 9.2:

Top-level definitions outside a packaging are assumed to be injected into a special empty package. That package cannot be named and therefore cannot be imported. However, members of the empty package are visible to each other without qualification.

And indeed, your classes Engine and ScalaPlayEngine don't live in a package (src/main/scala doesn't count as a package). If you move them to a proper package, it should work.

Upvotes: 2

Related Questions