sbt.version = 0.13.1
在build.sbt
中我通过调用我的项目依赖项代码来分配设置键,而该代码又通过Typesafe Config的ConfigFactory
进行自我配置。我的依赖项在jar的根目录中有一个reference.conf
,我的项目本身在application.conf
中包含一个覆盖src/main/resources
。
lib / dependency也是我的代码,顺便说一句。
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
范围的类路径上,但它不能像我期望的那样工作。
我昨天花了大部分时间仔细阅读有关Classpath,Scopes,Keys,Tasks和ResourceGenerators的SBT文档 - 我的目的是执行一个依赖于projKeyColorSetting
中的build.sbt
设置的自定义插件如下:
lazy val projSettings = inConfig(Compile) {
Seq(
resourceGenerators in Compile <+= Def.task {
val fileCreated = createColorFile(projKeyColorSetting.value)
Seq(fileCreated)
}
)
}
答案 0 :(得分:7)
如果你从foo.jar获得一个类,那么ConfigFactory.load()
应该在同一个jar中找到一个reference.conf。如果没有,那么有些事情是错的,但很难猜到是什么。可能是reference.conf中可能存在一些无效的语法;可能是reference.conf不在jar中;可能是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
的构造函数对于这样的情况。
答案 1 :(得分:1)
我认为这是sbt中的一个错误。
以下是我对您的用例的理解以及最终的行为方式。
<强>项目/ build.properties 强>
sbt.version=0.13.5-M2
文件夹 config-only-project 适用于包含以下两个文件的项目 - build.sbt 和 src / main / resources / application.conf 即可。这是为了模拟内部application.conf
的项目的外部依赖。
config-only-project
中的build.sbt
libraryDependencies += "com.typesafe" % "config" % "1.2.0"
config-only-project
中的src / main / resources / application.conf
app-name {
hello = "Hello from Typesafe Config"
}
以下文件配置默认的plugins
项目以及构建配置本身(以及因此正在调查的项目的构建)。
<强>项目/ build.sbt 强>
lazy val configOnlyProject = uri("../config-only-project")
lazy val plugins = project in file(".") dependsOn (configOnlyProject)
<强>项目/ 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
我希望我能解释一下,但对我来说似乎有太多的认知负担:(
答案 2 :(得分:1)
与Play项目相同的问题,通过在任务定义中向ClassLoader
添加ConfigFactory.parseResourcesAnySyntax()
参数来解决:
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")
}
)
答案 3 :(得分:0)
sbt 1.4.4的问题在于,我试图在我的元版本(project/build.sbt
)中添加一个依赖项,以便可以在主版本中使用它。
该库正在使用ConfigFactory.load()
,该库使用了当前线程中的ClassLoader,而该线程最终成为SbtMetaClassLoader,后者没有用于元构建依赖项的加载器。
解决方法是将库更改为使用ConfigFactory.load(getClass.getClassLoader)
,以便它使用的是类加载器,该类加载器从库以及大概是JAR的其余部分(包括reference.conf
文件)中加载类。>