Проблема:
У нас был интеграционный тест, который создает пружинный ClassPathXmlApplicationContext и при этом тест NoSuchMethodError с NoSuchMethodError . Оказалось, что у нас были конфликтующие версии зависимостей от артефактов Spring. Само по себе это не является необычной проблемой — такие проблемы решаются с помощью подключаемого модуля зависимостей maven с использованием опции verbose. Тем не менее, что вы делаете, когда плагин Maven не так?
Изучение:
Мы начали копаться и обнаружили, что AbstractAutowireCapableBeanFactory в его методе getTypeForFactoryMethod пытается получить доступ к GenericTypeResolver resolveReturnTypeForGeneric и происходит сбой в java.lang.NoSuchMethodError: org.springframework.core.GenericTypeResolver.resolveReturnTypeForGenericMethod(Ljava/lang/reflect/Method; ,
Первоначальное исследование и поиск в Google показали, что метод был добавлен в 3.2.0, в то время как мы должны работать с 3.1.1. Дальнейшие исследования показали, что spring-data-mongodb зависит от структуры пружины в диапазоне [3.0.7-4) 1 и потому, что maven использует последнюю доступную версию, учитывая, что диапазон 2 он пытался взять 3.2.2.
Обратите внимание, что вышеприведенное немного меняется, учитывая конфликт между явной зависимостью от версии и зависимостью от диапазона, но, IINM, при определении зависимостей Spring Mongo конфликта не возникает.
Проблема была также замаскирована двумя симптомами:
- У нас есть другие проекты, которые используют этот шаблон и у нас нет проблем. Это объясняется тем, что механизм разрешения конфликтов maven выбирает ближайшую версию, которую он находит по умолчанию 3, и поскольку все другие проекты, которым требуется spring-data-mongodb, зависят от В этом проекте им повезло захватить версию 3.1.1, а не 3.2.2
- Зависимость: дерево показывает, что оно приносит 3.1.1, в то время как приносит 3.2.2. Поскольку трассировка стека показала другие результаты, я написал тест, который проверяет, из какого jar происходит каждый из вышеперечисленных классов, и проверял, действительно ли класс AbstractAutowireCapableBeanFactory прибывает из Spring-Beans. 3.2.2, а не 3.1.1, как показала «mvn dependency: tree» (большое спасибо http://bit.ly/10zD1iV за фрагмент кода для поиска jar класса во время выполнения).
Зависимость Maven: вывод дерева, показывающий spring-bean: в артефакте используется 3.1.1.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
>:mvn dependency:tree -Dverbose -Dincludes=org.springframework...(omitted for clarity)...[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ wix-feature-toggle-administration ---[INFO] artifact org.springframework:spring-beans: checking for updates from central[INFO] artifact org.springframework:spring-beans: checking for updates from snapshots[INFO] artifact org.springframework:spring-expression: checking for updates from central[INFO] artifact org.springframework:spring-expression: checking for updates from snapshots[INFO] artifact org.springframework:spring-tx: checking for updates from central[INFO] artifact org.springframework:spring-tx: checking for updates from snapshots[INFO] com.wixpress.common:wix-feature-toggle-administration:jar:2.180.0-SNAPSHOT...[INFO] +- org.springframework.data:spring-data-mongodb:jar:1.0.1.RELEASE:compile[INFO] | +- org.springframework:spring-beans:jar:3.1.1.RELEASE:compile[INFO] | | \- (org.springframework:spring-core:jar:3.2.2.RELEASE:compile - omitted for conflict with 3.1.1.RELEASE)[INFO] | +- org.springframework:spring-expression:jar:3.1.1.RELEASE:compile[INFO] | | \- (org.springframework:spring-core:jar:3.2.2.RELEASE:compile - omitted for conflict with 3.1.1.RELEASE)[INFO] | \- org.springframework.data:spring-data-commons-core:jar:1.2.1.RELEASE:compile[INFO] | +- (org.springframework:spring-beans:jar:3.1.1.RELEASE:compile - omitted for duplicate)[INFO] | \- (org.springframework:spring-tx:jar:3.1.1.RELEASE:compile - omitted for duplicate)[INFO] +- com.wixpress.common:wix-framework:jar:2.180.0-SNAPSHOT:compile[INFO] | +- org.springframework:spring-core:jar:3.1.1.RELEASE:compile[INFO] | | \- org.springframework:spring-asm:jar:3.1.1.RELEASE:compile...I've removed additional outputs for clarity. The additional outputs were all 3.1.1 and were further down the tree (so irrelevant due to maven conflict resolving mechanism) |
Тест, который доказывает наличие бинов: 3.2.2 используется в артефакте (утверждая, что говорил jvm в ошибке)
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package com.wixpress.springVersionBug;import org.junit.*;import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;import org.springframework.core.GenericTypeResolver;import java.security.CodeSource;import static org.hamcrest.Matchers.endsWith;/** * @author ittaiz * @since 3/24/13 */public class SpringVersionTest { @Test public void verifySpringBeans311InClasspath(){ verifyCorrectSpringVersionInClasspathFor(AbstractAutowireCapableBeanFactory.class,"spring-beans-3.1.1.RELEASE.jar"); } @Test public void verifySpringCore311InClasspath(){ verifyCorrectSpringVersionInClasspathFor(GenericTypeResolver.class,"spring-core-3.1.1.RELEASE.jar"); } public void verifyCorrectSpringVersionInClasspathFor(Class springClass,String expectedJarFileName){ CodeSource springClassCodeSource = springClass.getProtectionDomain().getCodeSource(); Assert.assertNotNull("expecting "+expectedJarFileName+" to be loaded by non-system class loader",springClassCodeSource); Assert.assertThat(springClassCodeSource.getLocation().toString(),endsWith(expectedJarFileName)); }} |
Аргумент spring-core появился в 3.1.1, когда spring-beans был 3.2.2, в том, что наша среда явно зависит от spring-core и этот артефакт явно зависит от платформы. Это означает, что spring-core 3.1.1 из каркаса составляет 2 прыжка, что короче, чем 3.2.2 из spring-data-mongodb .
Решение:
Зависит от spring-data-mongodb , исключая spring-beans например так:
|
01
02
03
04
05
06
07
08
09
10
11
|
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.0.1.RELEASE</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </exclusion> </exclusions></dependency> |
Открытый вопросительный знак:
Почему зависимость: дерево (в подробном режиме) не показывало, что оно приносит Spring-bean-компоненты в 3.2.2, но в 3.1.1, в то же время явно указав, что spring-core 3.2.2 был удален из-за конфликта? Я объясняю это ошибкой в плагине зависимостей.
- http://repo1.maven.org/maven2/org/springframework/data/spring-data-mongodb-parent/1.0.1.RELEASE/spring-data-mongodb-parent-1.0.1.RELEASE.pom ↩
- http://www.maestrodev.com/better-builds-with-maven/creating-applications-with-maven/resolving-dependency-conflicts-and-using-version-ranges/ ↩
- http://www.maestrodev.com/better-builds-with-maven/creating-applications-with-maven/resolving-dependency-conflicts-and-using-version-ranges/ ↩