【问题标题】:Spring-core dependency version error with a Jenkins PluginJenkins插件的Spring-core依赖版本错误
【发布时间】:2014-07-26 18:59:06
【问题描述】:

我正在尝试制作一个使用 a library that requires spring-core 3.2.2 (cloudfoundry-client-lib) 的 Jenkins 插件。我只是使用 mvn 命令创建了一个骨架插件,然后将我的 Maven 依赖项添加到 pom.xml 和一些使用该库的简单代码行。没有我的依赖,我运行骨架插件没有任何问题。

使用“mvn package”编译时,出现测试错误:

WARNING: Failed to scout hudson.security.PAMSecurityRealm
java.lang.InstantiationException: java.lang.NoClassDefFoundError: org/springframework/core/env/EnvironmentCapable

看起来这是一个出现在 spring-core 3.1.0 中的类。于是我查看了 Maven 依赖树:

[INFO] --- maven-dependency-plugin:2.3:tree (default-cli) @ stackato-jenkins ---
[INFO] org.wiwiweb:cf-test-jenkins:hpi:1.0-SNAPSHOT
[INFO] \- org.cloudfoundry:cloudfoundry-client-lib:jar:1.0.2:compile
[INFO]    \- org.springframework:spring-webmvc:jar:3.2.2.RELEASE:compile
[INFO]       \- org.springframework:spring-core:jar:2.5.6.SEC03:compile

所以 Maven 告诉我它使用 spring-core 2.5.6 是因为 spring-webmvc 3.2.2?这很奇怪,因为looking online, spring-webmvc 3.2.2 depends on spring-core 3.2.2。查看详细版本的树,looks like jenkins-core depends on spring-core 2.5.6... 这让我怀疑问题出在 Jenkins。

无论如何,如果只是版本冲突,那么通过在我的 pom.xml 中明确说我想要 spring-core 3.2.2 来覆盖 Maven 的决定应该可以解决问题,对吗? 我这样做了,然后没有得到编译错误。问题解决了!...没有。

在运行时,在 Jenkins 中激活此插件并使用此插件运行构建后,只要代码运行到使用我添加的库的行中,Jenkins 输出就会告诉我:

FATAL: org.springframework.util.CollectionUtils.unmodifiableMultiValueMap(Lorg/springframework/util/MultiValueMap;)Lorg/springframework/util/MultiValueMap;
java.lang.NoSuchMethodError: org.springframework.util.CollectionUtils.unmodifiableMultiValueMap(Lorg/springframework/util/MultiValueMap;)Lorg/springframework/util/MultiValueMap;

UnmodifiableMultiValueMap() 是 spring-core 3.1 中添加的一种方法,因此这意味着 Jenkins 仍在尝试使用旧版本的 spring-core 运行我的插件,即使我明确表示我想要最新的插件插件的 pom.xml!

所以我坚持这一点。我什至不确定这是 Maven 还是 Jenkins 问题。我会用两个问题来总结整个事情:

  1. 为什么 Maven 不使用正确版本的 spring-core 编译插件,除非我明确告诉他这样做?它应该能够在没有我提示的情况下遵循依赖关系。
  2. 为什么 Jenkins 运行我的插件时使用的 spring-core 版本比编译时使用的版本旧,我怎样才能让它使用正确的版本?

【问题讨论】:

  • 你能发布完整的 pom.xml 吗?
  • 这里是:pastebin.com/UGS2uRfA。感谢您的宝贵时间!
  • It seems 这不是一件容易的事。在该讨论中,插件中的代码使用org.springframework 包,而在您的代码使用的库的情况下,它使用org.springframework 包。但是这个建议本身有点说,不可能在你的插件中简单地使用另一个版本的 Spring,这与 Jenkins 使用的不同。您是否有机会构建自己的使用 Maven Shade 插件的 cloudfoundry-client-lib jar 版本?
  • 你能分享你的插件的完整代码吗?我尝试了cloudfoundry-client-lib 的“阴影”版本,但我之前没有使用过 Jenkins,也没有为它开发过插件,所以我无法实际测试它是否有效。
  • Here is the entire source code. 你找到的那个链接很有趣,我想我也会自己研究一下。

标签: spring maven jenkins dependencies jenkins-plugins


【解决方案1】:

尝试使用 Maven Shade 插件“遮蔽”CF 客户端库,因为似乎 Jenkins doesn't like 插件使用的 Spring 版本与其内部使用的版本不同。

即使您自己的插件不直接使用 Spring,但 CF 库使用,我相信这仍然适用。在 jenkinsci-dev 邮件列表中建议着色的人似乎是 Jenkins 插件开发中的involved,所以他可能比其他人更了解这一点。

话虽如此,我会得到source code for cf-client-lib,我会更改pom.xml 以考虑对org.springframework 包进行着色(因为cf-client-lib 已经对org.codehaus.jackson 包使用了着色)和我会在 Jenkins 插件中使用这个“阴影”版本的 cf-client-lib。

【讨论】:

  • 虽然您无法测试您的解决方案,但您仍然帮了我很多忙。我什至不知道阴影插件。我想我现在可以解决这个问题了,非常感谢!
  • 尝试使用 Shade 进行此操作,虽然它确实对 hpi 文件进行了遮蔽,但与 Jenkins 安装的 Spring 2 jar 的运行时冲突仍然存在。
【解决方案2】:

如果您从 Jenkins 安装而不是插件中获取依赖项,则该解决方案实际上很容易实现。根据Jenkins documentation,只需将 maven-hpi-plugin 添加到 Jenkins 插件的 pom.xml 中的构建中,并将其设置为首先加载插件类:

<build>
    <plugins>
        <plugin>
            <groupId>org.jenkins-ci.tools</groupId>
            <artifactId>maven-hpi-plugin</artifactId>
            <configuration>
                <pluginFirstClassLoader>true</pluginFirstClassLoader>
            </configuration>
        </plugin>
    </plugins>
</build>

【讨论】:

  • 这看起来很有希望,可以让我摆脱当前笨重的着色解决方案,但它似乎不起作用。这是我的依赖树:pastebin.com/4qSvhvgH - 如您所见,即使我的插件需要 3.2.2.RELEASE,它仍在使用 spring-core:jar:2.5.6.SEC03
  • @Wiwiweb 这个答案解决了在将 hpi 部署到 Jenkins 后运行时遇到的 NoSuchMethodError。正如您在问题中提到的,您仍然需要将依赖项添加到 pom.xml 以构建 hpi。在 pom.xml 中显式添加依赖项后,在答案中添加此构建插件配置,然后构建和部署。结果应该是您可以在 Jenkins 上看到部署到您的插件路径的正确 jar 版本,现在类加载器正在拾取这些版本,因此在运行时不再出现 NoSuchMethodError。
  • 看起来这很好用!谢谢,这将为我以后省去很多麻烦。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
  • 2019-07-23
  • 2013-10-12
  • 1970-01-01
  • 2015-10-13
  • 2021-10-08
  • 1970-01-01
相关资源
最近更新 更多