繁体   English   中英

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

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

我想创建一个使用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'而失败com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'localDb'

我该如何解决这个问题,以便配置可用?

我在这里发现了很多关于在build.sbt使用application.confbuild.sbt ,但这不是我需要的。

我已经使用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")

./project/build.properties

sbt.version = 0.13.8

./src/main/resources/reference.conf

hello {
  world = "buuh."
}

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

./src/main/scala/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")
} 

结果

如果从Console运行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。

回答

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

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

而是通过config.resource显式设置application.conf的路径, 请参阅typesafe配置文档(搜索config.resource)

选项1

在启动sbt之前设置config.resource (通过-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 不幸的是,我无法使用默认的ClassLoader访问project -subfolder中的任何.conf

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

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

或者从./src/main/resources加载一个genereal application.conf

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)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM