Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do Slick configuration via application.conf from within custom sbt task?

Tags:

scala

sbt

slick

I want to create an set task which creates a database schema with slick. For that, I have a task object like the following in my project:

object CreateSchema {

    val instance = Database.forConfig("localDb")

    def main(args: Array[String]) {
        val createFuture = instance.run(createActions)
        ...
        Await.ready(createFuture, Duration.Inf)
    }

}

and in my build.sbt I define a task:

lazy val createSchema = taskKey[Unit]("CREATE database schema")

fullRunTask(createSchema, Runtime, "sbt.CreateSchema")

which gets executed as expected when I run sbt createSchema from the command line.

However, the problem is that application.conf doesn't seem to get taken into account (I've also tried different scopes like Compile or Test). As a result, the task fails due to com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'localDb'.

How can I fix this so the configuration is available?

I found a lot of questions here that deal with using the application.conf inside the build.sbt itself, but that is not what I need.

like image 936
ag5 Avatar asked Aug 28 '15 17:08

ag5


1 Answers

Answer

So, even if your code resides in your src-folder, it is called from within SBT. That means, you are trying to load your application.conf from within the classpath context of SBT.

Slick uses Typesafe Config internally. (So the approach below (described in background) is not applicable, as you can not modify the Config loading mechanism itself).

Instead try the set the path to your application.conf explicitly via config.resource, see typesafe config docu (search for config.resource)

Option 1

Either set config.resource (via -Dconfig.resource=...) before starting sbt

Option 2

Or from within build.sbt as Scala code

sys.props("config.resource") = "./src/main/resources/application.conf"

Option 3

Or create a Task in SBT via

lazy val configPath = TaskKey[Unit]("configPath", "Set path for application.conf")

and add

configPath := Def.task {
  sys.props("config.resource") = "./src/main/resources/application.conf"
}

to your sequence of settings.

Please let me know, if that worked.

Background information

Recently, I was writing a custom plugin for SBT, where I also tried to access a reference.conf as well. Unfortunately, I was not able to access any of .conf placed within project-subfolder using the default ClassLoader.

In the end I created a testenvironment.conf in project folder and used the following code to load the (typesafe) config:

def getConfig: Config = {
  val classLoader = new java.net.URLClassLoader( Array( new File("./project/").toURI.toURL ) )
  ConfigFactory.load(classLoader, "testenvironment")
}

or for loading a genereal application.conf from ./src/main/resources:

def getConfig: Config = {
  val classLoader = new java.net.URLClassLoader( Array( new File("./src/main/resources/").toURI.toURL ) )
  // no .conf basename given, so look for reference.conf and application.conf
  // use specific classLoader
  ConfigFactory.load(classLoader)
}
like image 142
Martin Senne Avatar answered Nov 03 '22 12:11

Martin Senne