我有一个有很多依赖项的应用程序。一个依赖关系是ActiveMQ Artemis。在Maven模块的pom.xml中,我将版本从2.4.0更新到2.10.0
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-server</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-commons</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client-all</artifactId>
<version>2.10.0</version>
</dependency>
我用来启动Artemis代理的代码如下:
EmbeddedActiveMQ broker = new EmbeddedActiveMQ();
String fileConfig = "file:///" + brokerFile.getAbsolutePath();
broker.setConfigResourcePath(fileConfig);
代理客户端通过 Camel 中的 sjms 组件连接:
org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory cf = new ActiveMQJMSConnectionFactory(url);
SjmsComponent component = new SjmsComponent();
component.setConnectionFactory(cf);
context.addComponent("sjms", component);
我在另一个使用 Gradle 5.6.2 构建/编译的应用程序中使用此 Maven 模块。此应用程序还包含适用于 Apache Camel 2.24.2 和 Apache ActiveMQ 5.5.10 的库。
应用程序编译正常,但在运行时我得到"NoSuchMethodError":
Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: org.apache.activemq.artemis.utils.ClassloadingUtil.loadProperty(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
从日志记录:
2019-09-21 03:03:00.883 WARN 4984 --- [ XNIO-2 task-14] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by handler execution: org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: org.apache.activemq.artemis.utils.ClassloadingUtil.loadProperty(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
java.lang.NullPointerException
at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.finalize(ActiveMQConnectionFactory.java:961)
at java.lang.System$2.invokeFinalize(System.java:1270)
at java.lang.ref.Finalizer.runFinalizer(Finalizer.java:102)
at java.lang.ref.Finalizer.access$100(Finalizer.java:34)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:217)
根据文章修复NoSuchMethodErrors和NoSuchMethodExceptions的3个步骤,我运行了"gradlew依赖项"。
| +--- org.apache.activemq:artemis-server:2.10.0 -> 2.4.0
| | +--- org.jboss.logging:jboss-logging:3.3.0.Final -> 3.3.2.Final
| | +--- org.apache.activemq:artemis-commons:2.4.0
| | | +--- org.jboss.logging:jboss-logging:3.3.0.Final -> 3.3.2.Final
| | | +--- io.netty:netty-buffer:4.1.16.Final -> 4.1.31.Final (*)
| | | +--- io.netty:netty-transport:4.1.16.Final -> 4.1.31.Final (*)
| | | +--- io.netty:netty-handler:4.1.16.Final -> 4.1.31.Final (*)
| | | +--- commons-beanutils:commons-beanutils:1.9.3
| | | | +--- commons-logging:commons-logging:1.2
| | | | --- commons-collections:commons-collections:3.2.2
| | | --- com.google.guava:guava:19.0 -> 25.1-jre (*)
| | +--- org.apache.activemq:artemis-selector:2.4.0
| | +--- org.apache.activemq:artemis-journal:2.4.0
| | | +--- org.jboss.logging:jboss-logging:3.3.0.Final -> 3.3.2.Final
| | | +--- org.apache.activemq:artemis-commons:2.4.0 (*)
| | | --- org.apache.activemq:artemis-native:2.4.0
| | | --- org.jboss.logging:jboss-logging:3.3.0.Final -> 3.3.2.Final
| | +--- org.apache.activemq:artemis-jdbc-store:2.4.0
| | | +--- org.jboss.logging:jboss-logging:3.3.0.Final -> 3.3.2.Final
| | | +--- org.apache.activemq:artemis-journal:2.4.0 (*)
| | | --- org.apache.activemq:artemis-core-client:2.4.0
| | | +--- org.jgroups:jgroups:3.6.13.Final -> 3.6.7.Final
| | | +--- org.apache.activemq:artemis-commons:2.4.0 (*)
| | | +--- org.apache.johnzon:johnzon-core:0.9.5 -> 1.1.10
| | | +--- io.netty:netty-transport-native-epoll:4.1.16.Final -> 4.1.31.Final (*)
| | | +--- io.netty:netty-transport-native-kqueue:4.1.16.Final -> 4.1.31.Final (*)
| | | --- io.netty:netty-codec-http:4.1.16.Final -> 4.1.31.Final (*)
| | +--- org.apache.activemq:artemis-core-client:2.4.0 (*)
| | --- io.netty:netty-all:4.1.16.Final -> 4.1.9.Final
| +--- org.apache.activemq:artemis-commons:2.10.0 -> 2.4.0 (*)
| +--- org.apache.activemq:artemis-jms-client-all:2.10.0
因此,Artemis代理实际上是在2.4.0版本下运行的,而客户端在2.10.0下运行(使它们不兼容(。
我的文章它指出:
"最后,我们需要决定我们实际上需要满足两个依赖项的两个版本中的哪一个。通常,这是较新的版本,因为大多数框架在某些方面是向后兼容的。但是,情况可能相反,或者我们甚至可能根本无法解决冲突。
为了强制两者在 2.10.0 上运行,我在 build.gradle 文件中明确声明:
configurations.all {
resolutionStrategy {
force 'org.apache.activemq:artemis-core-client:2.10.0', 'org.apache.activemq:artemis-broker:2.10.0','org.apache.activemq:artemis-commons:2.10.0','org.apache.activemq:artemis-selector:2.10.0','org.apache.activemq:artemis-journal:2.10.0'
}
}
compile group: 'org.apache.activemq', name: 'artemis-core-client', version: '2.10.0'
compile group: 'org.apache.activemq', name: 'artemis-commons', version: '2.10.0'
compile group: 'org.apache.activemq', name: 'artemis-server', version: '2.10.0'
compile group: 'org.apache.activemq', name: 'artemis-selector', version: '2.10.0'
compile group: 'org.apache.activemq', name: 'artemis-journal', version: '2.10.0'
在此"gradlew 依赖项"之后:
| +--- org.apache.activemq:artemis-server:2.10.0
| | +--- org.jboss.logging:jboss-logging:3.4.0.Final -> 3.3.2.Final
| | +--- org.jboss.logmanager:jboss-logmanager:2.1.10.Final
| | | --- org.wildfly.common:wildfly-common:1.5.1.Final
| | +--- org.apache.activemq:artemis-commons:2.10.0
| | | +--- org.jboss.logging:jboss-logging:3.4.0.Final -> 3.3.2.Final
| | | +--- io.netty:netty-buffer:4.1.34.Final -> 4.1.31.Final (*)
| | | +--- io.netty:netty-transport:4.1.34.Final -> 4.1.31.Final (*)
| | | +--- io.netty:netty-handler:4.1.34.Final -> 4.1.31.Final (*)
| | | --- commons-beanutils:commons-beanutils:1.9.3
| | | +--- commons-logging:commons-logging:1.2
| | | --- commons-collections:commons-collections:3.2.2
| | +--- org.apache.activemq:artemis-selector:2.10.0
| | | --- org.apache.activemq:artemis-commons:2.10.0 (*)
| | +--- org.apache.activemq:artemis-journal:2.10.0
| | | +--- org.jboss.logging:jboss-logging:3.4.0.Final -> 3.3.2.Final
| | | +--- org.apache.activemq:artemis-commons:2.10.0 (*)
| | | +--- org.apache.activemq:activemq-artemis-native:1.0.0
| | | | +--- org.jboss.logging:jboss-logging:3.3.1.Final -> 3.3.2.Final
| | | | --- org.jboss.logmanager:jboss-logmanager:2.0.3.Final -> 2.1.10.Final (*)
| | | +--- io.netty:netty-buffer:4.1.34.Final -> 4.1.31.Final (*)
| | | --- io.netty:netty-common:4.1.34.Final -> 4.1.31.Final
| | +--- org.apache.activemq:artemis-jdbc-store:2.10.0
| | | +--- org.jboss.logging:jboss-logging:3.4.0.Final -> 3.3.2.Final
| | | +--- org.apache.activemq:artemis-commons:2.10.0 (*)
| | | +--- org.apache.activemq:artemis-journal:2.10.0 (*)
| | | --- org.apache.activemq:artemis-core-client:2.10.0
| | | +--- org.jgroups:jgroups:3.6.13.Final -> 3.6.7.Final
| | | +--- org.apache.activemq:artemis-commons:2.10.0 (*)
| | | +--- org.apache.johnzon:johnzon-core:0.9.5 -> 1.1.10
| | | +--- io.netty:netty-transport-native-epoll:4.1.34.Final -> 4.1.31.Final (*)
| | | +--- io.netty:netty-transport-native-kqueue:4.1.34.Final -> 4.1.31.Final (*)
| | | +--- io.netty:netty-codec-http:4.1.34.Final -> 4.1.31.Final (*)
| | | +--- io.netty:netty-buffer:4.1.34.Final -> 4.1.31.Final (*)
| | | +--- io.netty:netty-transport:4.1.34.Final -> 4.1.31.Final (*)
| | | +--- io.netty:netty-handler:4.1.34.Final -> 4.1.31.Final (*)
| | | +--- io.netty:netty-codec:4.1.34.Final -> 4.1.31.Final (*)
| | | --- io.netty:netty-common:4.1.34.Final -> 4.1.31.Final
| | +--- org.apache.activemq:artemis-core-client:2.10.0 (*)
| | +--- org.apache.activemq:activemq-artemis-native:1.0.0 (*)
问题
代理和客户端库的版本相同,应用程序似乎工作正常。然而,这让我感到不安:
- 如何通过自动依赖解析在应用程序的发行说明中写入库已更新,而实际上使用的是两年前的版本?作为开发人员,我应该如何知道事实并非如此?
- 如何读取 gradlew 依赖项输出?什么是强制使用旧的"2.4.0"版本的根本原因库。
- 强制使用新版本真的是一个很好的解决方案,还是在覆盖自动依赖项解析时是否存在预期问题?
- 在 6.0 之前,Gradle 中的版本降级只能通过
force
、配置级别force
或替换规则来实现。您的构建中有一些东西使用这些技术之一来强制降低版本。 - 若要调查特定库的版本,请使用
dependencyInsight
任务获取有关选择模块特定版本的原因的更详细报告。 例如./gradlew dependencyInsight --configuration <relevantConfiguration> --dependency artemis-server
可以compileClasspath
或runtimeClasspath
<relevantConfiguration>
或更特定于您的项目的内容。 - 一旦您弄清楚
2.10.0
被降级到2.4.0
的原因,您就可以使用与force
不同的解决方案来获得您期望的版本。