如何在自定义sbt任务中通过application.conf进行Slick配置?

时间:2015-08-28 17:51:22

标签: scala sbt slick

我想创建一个使用slick创建数据库模式的set任务。为此,我的项目中有一个如下的任务对象:

object CreateSchema {

    val instance = Database.forConfig("localDb")

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

}

在我的build.sbt我定义了一个任务:

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

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

当我从命令行运行sbt createSchema时,它会按预期执行。

然而,问题是似乎没有考虑application.conf(我也尝试过不同的范围,例如CompileTest)。因此,任务因com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'localDb'而失败。

如何解决此问题,以便配置可用?

我发现很多问题都涉及在application.conf内部使用build.sbt,但这不是我需要的。

2 个答案:

答案 0 :(得分:3)

我已经使用SBT 0.13.8和Slick 3.0.0设置了一个小程序,它正在按预期工作。 (甚至不修改“-Dconfig.resource”。)

文件

./ build.sbt

name := "SO_20150915"

version := "1.0"

scalaVersion := "2.11.7"

libraryDependencies ++= Seq(
  "com.typesafe"                 % "config"                 % "1.3.0"                            withSources() withJavadoc(),
  "com.typesafe.slick"          %% "slick"                  % "3.0.0",
  "org.slf4j"                    % "slf4j-nop"              % "1.6.4",
  "com.h2database"               % "h2"                     % "1.3.175"
)

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

fullRunTask(createSchema, Runtime, "somefun.CallMe")

./项目/ build.properties

sbt.version = 0.13.8

./的src /主/资源/ reference.conf

hello {
  world = "buuh."
}

h2mem1 = {
  url = "jdbc:h2:mem:test1"
  driver = org.h2.Driver
  connectionPool = disabled
  keepAliveConnection = true
}

./ SRC /主/阶/ somefun / CallMe.scala

package somefun

import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import slick.driver.H2Driver.api._

/**
 * SO_20150915
 * Created by martin on 15.09.15.
 */
object CallMe {
  def main(args: Array[String]) : Unit = {
    println("Hello")
    val settings = new Settings()

    println(s"Settings read from hello.world: ${settings.hw}" )

    val db = Database.forConfig("h2mem1")
    try {
      // ...
      println("Do something with your database.")
    } finally db.close
  }

}

class Settings(val config: Config) {

  // This verifies that the Config is sane and has our
  // reference config. Importantly, we specify the "di3"
  // path so we only validate settings that belong to this
  // library. Otherwise, we might throw mistaken errors about
  // settings we know nothing about.
  config.checkValid(ConfigFactory.defaultReference(), "hello")

  // This uses the standard default Config, if none is provided,
  // which simplifies apps willing to use the defaults
  def this() {
    this(ConfigFactory.load())
  }

  val hw = config.getString("hello.world")
} 

结果

如果从控制台运行sbt createSchema,我获取输出

[info] Loading project definition from /home/.../SO_20150915/project
[info] Set current project to SO_20150915 (in build file:/home/.../SO_20150915/)
[info] Running somefun.CallMe 
Hello
Settings read from hello.world: buuh.
Do something with your database.
[success] Total time: 1 s, completed 15.09.2015 10:42:20

  • 请确认此未经修改的演示项目也适合您。
  • 然后尝试在演示项目中更改SBT版本,看看是否有所改变。
  • 或者,重新检查项目设置并尝试使用更高版本的SBT。

答案 1 :(得分:1)

答案

因此,即使您的代码位于src - 文件夹中,也会从SBT中调用它。这意味着,您尝试从SBT的类路径上下文中的加载application.conf

光滑在内部使用Typesafe Config。 (因此下面的方法(在后面描述)不适用,因为您无法修改Config加载机制本身。)

请尝试通过application.confsee typesafe config docu (search for config.resource)

明确设置config.resource的路径

选项1

在开始config.resource之前设置sbt(通过-Dconfig.resource = ...)

选项2

或者在build.sbt中作为Scala代码

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

选项3

或通过

在SBT中创建Task
lazy val configPath = TaskKey[Unit]("configPath", "Set path for application.conf")

并添加

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

到您的设置序列。

如果有效,请告诉我。

背景资料

最近,我正在为SBT编写一个自定义插件,我也尝试访问reference.conf。很抱歉,我无法使用默认.conf访问放置在project - 子文件夹中的任何ClassLoader

最后我在testenvironment.conf文件夹中创建了一个project并使用以下代码加载(类型安全)配置:

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

或从application.conf加载基因./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)
}