1

我刚刚尝试测试一个使用 Apache Camel 2.10.3 的应用程序,并且在DefaultCamelContext实例化后立即得到以下异常:

java.lang.NoSuchMethodError: org.slf4j.Logger.trace(Ljava/lang/String;Ljava/lang/Object;)V
    at org.apache.camel.impl.DefaultPackageScanClassResolver.<init>(DefaultPackageScanClassResolver.java:70)
    at org.apache.camel.impl.DefaultCamelContext.<init>(DefaultCamelContext.java:222)

我确保slf4j-api-1.6.6(这是 Camel 2.10.3 附带的)在运行时类路径上。接下来,我怀疑我可能有其他也使用 SLF4J 的依赖项,但依赖于它的不同版本。所以我打开 Eclipse,然后运行类型搜索org.slf4j.Logger,果然,我看到该类在 2 个不同的 JAR 中列出:(slf4j-api-1.6.6.jar如预期的那样!),以及另一个 3rd 方 jar widget-lib-3.0.jar,.

所以我打开了widget-lib3.0.jar,看到 SLF4J 像这样打包在里面:

widget-lib-3.0/
    com/
        <Widget Lib's compiled classes>
    org/
        slf4j/
            spi/
                ...
            impl/
                ...
            <A bunch of SLF4J classes, like LoggerFactory.class, etc.>

没有办法知道它在这里使用的是什么版本的 SLF4J,但我敢打赌它是早于 1.6.x 的版本,这正是 Camel 2.10.3 想要的。

所以我最好的,稍微受过教育的猜测是,在运行时,JRE 类加载器widget-lib-3.0.jar#org/slf4j/Logger首先找到并加载它,然后它们去加载 Camel JAR 及其依赖项。然后,当DefaultPackageScanClassResolver调用 SLF4Jtrace(String,Object)方法时,它没有找到 SLF4J 的 1.6.6 版本,而是找到了附带的任何版本widget-lib-3.0.jar,并且该方法/重载不存在。

我在离开基地的路上吗?如果我不在基地,这对你意味着什么,所以?如果我走上正轨,那么我提出的解决方案将是在widget-lib-3.0.jar没有org/slf4j包的情况下重新 JAR(不存在其他更现代的版本)。我的理论是slf4j-api-1.6.6,它是向后兼容的,它将是唯一被加载的 SLF4J 版本,然后适用于两个 JAR。有什么想法吗?提前致谢。

4

3 回答 3

0

“没有办法知道它在这里使用的是什么版本的 SLF4J,但我敢打赌它是早于 1.6.x 的版本,这正是 Camel 2.10.3 想要的”......

为什么不从 widget-lib-3.0.jar 中反编译类文件,看看是否存在所需的方法?

于 2013-02-01T11:00:38.083 回答
0

你的方法是正确的。SLF4J 1.x 在版本之间是 API 兼容的。(顺便说一句,你在使用 Maven 吗?它旨在防止这种问题)。

是什么widget-lib?是否有不包含其依赖项的版本?如果有,你应该使用它。

于 2013-02-01T11:27:06.190 回答
0

我在离开基地的路上吗?

不,看起来你在这里走上了正轨。

org.sfl4j.Logger确认它的方法是在小部件库JAR中获取副本,并使用javah它来查看它是否具有该void trace(String, Object)方法。

确认后,有多种解决方案:

  • 最干净的解决方案是获取小部件库的源代码,针对您需要的 sfl4j 版本重新编译它,然后构建一个新版本的 JAR,而不在其中嵌入 sfl4j。(您可能需要修改小部件库的源代码,但不太可能)。

  • 一个更简单的解决方案可能是确保您将更新的(并且应该是向后兼容的)slf4 API JAR 放在类路径上的小部件库 JAR 之前。这样,小部件 JAR 中旧版本的 slf4j 将被新版本“遮蔽”,并使用 Camel 需要的额外方法。

于 2013-02-01T11:34:10.377 回答