使用 Typesafe Config 的 ConfigFactory 在 build.sbt 中设置密钥设置?



sbt.version=0.13.1

build.sbt,我通过调用项目依赖项的代码片段来分配设置键,该代码又通过Typesafe Config的ConfigFactory进行自我配置。我的依赖项在 jar 的根目录中有一个reference.conf,我的项目本身在 src/main/resources 中包含一个覆盖application.conf

库/依赖项也是我的代码,顺便说一句。

import com.mylib.Finders
import com.myproj.sbt.Keys._
projKeyColorSetting in Compile := Finders.findColor // this calls ConfigFactory.load
seq(projSettings:_*)

构建甚至没有加载,因为它找不到我尝试在我的 lib 代码中引用的第一个 conf 密钥。

我已经在我的构建文件中尝试了许多范围界定和类路径操作的组合,但无济于事。我假设 jar 的reference.conf应该在 Compile 范围的类路径上,但它没有像我预期的那样工作。

我昨天花了大部分时间研究有关类路径、作用域、键、任务和资源生成器的 SBT 文档 - 我的目的是执行一个依赖于build.sbtprojKeyColorSetting设置的自定义插件,如下所示:

lazy val projSettings = inConfig(Compile) {
    Seq(
        resourceGenerators in Compile <+= Def.task {
            val fileCreated = createColorFile(projKeyColorSetting.value)
            Seq(fileCreated)
        }
    )
 }

如果你从 foo.jar 获得一个类,那么ConfigFactory.load()应该得到一个在同一个 jar 中找到的 reference.conf。如果没有,那么有些问题,但很难猜测是什么。可能是 reference.conf 中可能存在一些无效的语法;可能是 reference.conf 不在罐子里;可能是 reference.conf 位于子目录中,而不是 jar 的根目录中;很难猜到。我会尝试-Dconfig.trace=loads在那里寻找问题(例如,它应该告诉您配置是否尝试加载 reference.conf(。您也可以自己做classLoader.getResources,看看是否可以在不涉及配置的情况下找到该文件。您也可以尝试ConfigFactory.parseResourcesAnySyntax("reference"),看看您的参考设置是否在那里,并尝试直接拨打ConfigFactory.load,看看您的设置是否在那里。一般来说,仔细检查所有假设,看看哪里出了问题。

至于如何添加 src/main/resources,两个基本策略是 1( 以某种方式将其放在类路径上(在这种情况下可能很困难;您甚至在启动 sbt 之前就需要它,或者需要做某种自定义的 ClassLoader 乐趣(或者可能更实用 2( 使用 ConfigFactory.parseFile() 手动加载它。

我可能会抓住resourceDirectory键作为任务的依赖项,然后做类似的事情(未经测试(:

myTask := {
   val resourceDir = (resourceDirectory in Compile).value
   val appConfig = ConfigFactory.parseFile(resourceDir / "application.conf")
   val config = ConfigFactory.load(appConfig) // puts reference.conf underneath
   Finders.findColor(config)
}

请注意,这涉及更改findColor以采用Config参数,或者您可能更愿意使Finders成为可以用Config构造的非单例;请参阅 https://github.com/typesafehub/config/blob/master/examples/scala/simple-lib/src/main/scala/simplelib/SimpleLib.scala#L22 中的示例,我试图说明在使用Config时,通常库应该默认为ConfigFactory.load,但也有一个构造函数,允许自定义Config以下情况。这。

我认为这是 sbt 中的一个错误。

以下是我对你的用例以及 sbt 最终行为的理解。

项目/生成属性

sbt.version=0.13.5-M2

文件夹仅配置项目适用于具有以下两个文件 - build.sbt 和 src/main/resources/application.conf 的项目。这是为了模拟对内部application.conf项目的外部依赖关系。

build.sbt in config-only-project

libraryDependencies += "com.typesafe" % "config" % "1.2.0"

src/main/resources/application.conf in config-only-project

app-name {
  hello = "Hello from Typesafe Config"
}

以下文件配置项目的默认plugins以及生成配置本身(以及正在调查的项目的生成(。

project/build.sbt

lazy val configOnlyProject = uri("../config-only-project")
lazy val plugins = project in file(".") dependsOn (configOnlyProject)

project/build.scala

import sbt._
import Keys._
import com.typesafe.config._
object build extends Build {
  lazy val mySetting = taskKey[String]("Setting using Typesafe Config")
  lazy val myS = mySetting := {
    // Compiler issue Config conf???
    println((fullClasspath in Compile).value)
    val conf = ConfigFactory.load()
    conf getString "app-name.hello"
  }
  lazy val configOnlyProject = uri("config-only-project")
  lazy val root = project in file(".") settings (myS) dependsOn (configOnlyProject)
}

这给出了以下目录结构:

jacek:~/sandbox/so/setting-typesafe-config
$ tree
.
├── config-only-project
│   ├── build.sbt
│   ├── project
│   └── src
│       └── main
│           └── resources
│               └── application.conf
└── project
    ├── application.conf
    ├── build.properties
    ├── build.sbt
    └── build.scala
6 directories, 6 files

我无法理解的是设置本身不起作用 - 无论是主项目还是plugins项目。

> mySetting
List(Attributed(/Users/jacek/sandbox/so/setting-typesafe-config/target/scala-2.10/classes), Attributed(/Users/jacek/sandbox/so/setting-typesafe-config/config-only-project/target/scala-2.10/classes), Attributed(/Users/jacek/.sbt/boot/scala-2.10.4/lib/scala-library.jar), Attributed(/Users/jacek/.ivy2/cache/com.typesafe/config/bundles/config-1.2.0.jar))
[trace] Stack trace suppressed: run last root/*:mySetting for the full output.
[error] (root/*:mySetting) com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'app-name'
[error] Total time: 0 s, completed Mar 31, 2014 10:24:12 PM

错误如下:

> last root/*:mySetting
com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'app-name'
    at com.typesafe.config.impl.SimpleConfig.findKey(SimpleConfig.java:124)
    at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:147)
    at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:159)
    at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:164)
    at com.typesafe.config.impl.SimpleConfig.getString(SimpleConfig.java:206)
    at build$$anonfun$myS$1.apply(build.scala:11)
    at build$$anonfun$myS$1.apply(build.scala:7)
    at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
    at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:42)
    at sbt.std.Transform$$anon$4.work(System.scala:64)
    at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
    at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
    at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
    at sbt.Execute.work(Execute.scala:244)
    at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
    at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
    at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:160)
    at sbt.CompletionService$$anon$2.call(CompletionService.scala:30)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:744)
[error] (root/*:mySetting) com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'app-name'

当我在 Scala 控制台中执行相同的代码时,它确实有效:

> console
[info] Starting scala interpreter...
[info]
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import com.typesafe.config._
import com.typesafe.config._
scala> ConfigFactory.load()
res0: com.typesafe.config.Config = ...
scala> res0 getString "app-name.hello"
res1: String = Hello from Typesafe Config

当我切换到plugins项目时,它也运行良好:

> reload plugins
[info] Loading project definition from /Users/jacek/sandbox/so/setting-typesafe-config/project
> console
[info] Starting scala interpreter...
[info]
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import com.typesafe.config._
import com.typesafe.config._
scala> ConfigFactory.load()
res0: com.typesafe.config.Config = ...
scala> res0 getString "app-name.hello"
res1: String = Hello from Typesafe Config

我希望我能解释一下,但这对我来说似乎太大了:(

Play 项目的相同问题,通过在任务定义中向ConfigFactory.parseResourcesAnySyntax()添加 ClassLoader 参数来解决:

import com.typesafe.config.ConfigFactory
lazy val root = (project in file(".")).
  settings(
    myTask := {
      val cl = new java.net.URLClassLoader(Array((resourceDirectory 
        in Compile).value.toURI.toURL))
      // load ./conf/foo.conf
      val config = ConfigFactory.parseResourcesAnySyntax(cl, "foo.conf")
  }
)
我在使用

sbt 1.4.4 时遇到的问题是我试图在我的元构建(project/build.sbt(中添加一个依赖项,以便我可以在我的主构建中使用它。

该库使用的是ConfigFactory.load(),它使用当前线程中的类加载器,最终成为 SbtMetaClassLoader,它没有元构建依赖项的加载器。

解决方法是将库更改为使用 ConfigFactory.load(getClass.getClassLoader),以便它使用从库中加载类的类装入器,并可能使用包括reference.conf文件在内的 JAR 的其余部分。

相关内容

  • 没有找到相关文章

最新更新