问题
I'm trying to make a Jenkins plugin that uses a library that requires spring-core 3.2.2 (cloudfoundry-client-lib). I simply used the mvn command to create a skeleton plugin, then added my Maven dependency to pom.xml and a few simple code lines that uses the library. I'm not getting any problem running the skeleton plugin without my dependency.
Upon compiling with "mvn package", I'm getting a test error:
WARNING: Failed to scout hudson.security.PAMSecurityRealm
java.lang.InstantiationException: java.lang.NoClassDefFoundError: org/springframework/core/env/EnvironmentCapable
Looks like this is a class that appeared in spring-core 3.1.0. So I looked at the Maven dependency tree:
[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
So Maven tells me it's using spring-core 2.5.6 because of spring-webmvc 3.2.2? This is strange because, looking online, spring-webmvc 3.2.2 depends on spring-core 3.2.2. Looking at the verbose version of the tree, looks like jenkins-core depends on spring-core 2.5.6... This makes me suspicious that the problem is from Jenkins.
Anyway, if it's just a version conflict, then overriding Maven's decision by explicitly saying I want spring-core 3.2.2 in my pom.xml should solve the problem, right? I did this, then did not get a compile error. Problem solved!... not.
In runtime, after activating this plugin in Jenkins and running a build with this, as soon as the code runs into a line that uses the library I added, the Jenkins output tells me this:
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() is a method that was added in spring-core 3.1, so this means Jenkins is still trying to run my plugin with the old version of spring-core, even though I explicitly said I wanted the newest one in my plugin's pom.xml!
So I'm stuck on this. I'm not even sure if it's a Maven or a Jenkins issue. I'll sum up the whole thing in two questions:
- Why is Maven not compiling the plugin with a correct version of spring-core unless I explicitly tell him to? It should be able to follow dependencies without me giving it hints.
- Why is Jenkins running my plugin with an older version of spring-core than the one it was compiled with, and how can I make it use the correct one?
Thanks a LOT in advance for any hint you can provide, this is preventing any of my progress and I've been trying to solve this for a while.
回答1:
If you're picking up dependencies from the Jenkins install rather than from your plugin the solution is actual quite easy to implement. Per the Jenkins documentation, simply add the maven-hpi-plugin to the build in the pom.xml of your Jenkins plugin and set it to load the plugin classes first:
<build>
<plugins>
<plugin>
<groupId>org.jenkins-ci.tools</groupId>
<artifactId>maven-hpi-plugin</artifactId>
<configuration>
<pluginFirstClassLoader>true</pluginFirstClassLoader>
</configuration>
</plugin>
</plugins>
</build>
回答2:
Try to "shade" the CF client lib using the Maven Shade plugin, as it seems Jenkins doesn't like plugins that are using a different version of Spring than the one it uses internally itself.
Even if your own plugin doesn't use Spring directly, but the CF library does, I believe this still applies. The person that suggested shading in the jenkinsci-dev mailing list seems to be involved in Jenkins plugins development, so he might know about this more than others.
These being said, I would get the source code for cf-client-lib, I would change the pom.xml to consider shading for org.springframework
package, as well (because cf-client-lib already uses shading for org.codehaus.jackson
package) and I would use this "shaded" version of cf-client-lib in the Jenkins plugin.
来源:https://stackoverflow.com/questions/24066027/spring-core-dependency-version-error-with-a-jenkins-plugin