我的应用程序使用"typesafe.config"解析设置,然后使用"ficus"将Config
对象转换为case类的实例。case类目前有19个构造函数参数。一切正常。然而,当我在"settings.conf"中添加一个新的参数和一个新对应的字段时,我会得到以下异常:
An exception or error caused a run to abort: MyCaseClass.<init>(Ljava/lang/String;Lscala/Option;Lscala/Option;IZLscala/collection/Seq;Ljava/lang/String;ILscala/concurrent/duration/FiniteDuration;ZLscala/Option;Lscala/Option;ILscala/Option;Lscala/concurrent/duration/FiniteDuration;Ljava/lang/String;Ljava/lang/String;II)V
java.lang.NoSuchMethodError: MyCaseClass.<init>(Ljava/lang/String;Lscala/Option;Lscala/Option;IZLscala/collection/Seq;Ljava/lang/String;ILscala/concurrent/duration/FiniteDuration;ZLscala/Option;Lscala/Option;ILscala/Option;Lscala/concurrent/duration/FiniteDuration;Ljava/lang/String;Ljava/lang/String;II)V
我可以看到"typesafe.config"正在正确地将我的新字段解析为Config
对象。但菲库斯随后抛出了这个例外。新字段和新case类构造函数参数的名称应该完全相同。
你知道为什么会发生这种情况吗?
具体问题记录在以下提交中:
1)https://github.com/ceilican/Scorex/commit/133157a6ad070cad7a57624c511ee917133ed5f1
2)https://github.com/ceilican/Scorex/commit/074e0bc5add3c666b0943497a5579f3fd365084d
3)https://github.com/ceilican/Scorex/commit/7c8d3475377a17b2a5383bf3a99d797650ca8bc3
前两个提交正在工作。对于第三个,会抛出上面提到的异常。
正如您所看到的,提交2和提交3在概念上没有太大区别。我不明白为什么提交2有效,而提交3无效。
有一段时间,我认为这可能是因为case类中有大量的参数,但下面的提交表明,当我将新字段添加到一个较小的case类时,问题也会发生:
4)https://github.com/ceilican/Scorex/commit/1c253b2b526db1539fa674069232cf02784c4bfb
当我尝试在提交4之后运行代码时,也会引发同样的异常。
这是菲库斯的虫子吗?
在主项目和子项目上执行sbt clean
后,问题停止发生。我的猜测是Ficus的宏魔术基于我的case类生成函数,但当case类被修改时,它们不会重新生成。然后,当Ficus试图使用与新case类不兼容的过时函数时,就会抛出异常。
有趣的是,只有当我修改"嵌套"的case类时,才会出现缺乏重新生成的情况。如果配置文件是:
main {
nested {
param: 0
}
}
案例类别:
case class MainCaseClass(nested: NestedCaseClass)
case class NestedCaseClass(param: Int)
那么,修改MainCaseClass
不会引起问题,但修改NestedCaseClass
会引起问题。