Статьи

Когда плагин Maven Dependency лежит

Проблема:

У нас был интеграционный тест, который создает пружинный 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 конфликта не возникает.

Проблема была также замаскирована двумя симптомами:

  1. У нас есть другие проекты, которые используют этот шаблон и у нас нет проблем. Это объясняется тем, что механизм разрешения конфликтов maven выбирает ближайшую версию, которую он находит по умолчанию 3, и поскольку все другие проекты, которым требуется spring-data-mongodb, зависят от В этом проекте им повезло захватить версию 3.1.1, а не 3.2.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 был удален из-за конфликта? Я объясняю это ошибкой в ​​плагине зависимостей.

  1. 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
  2. http://www.maestrodev.com/better-builds-with-maven/creating-applications-with-maven/resolving-dependency-conflicts-and-using-version-ranges/
  3. http://www.maestrodev.com/better-builds-with-maven/creating-applications-with-maven/resolving-dependency-conflicts-and-using-version-ranges/

Ссылка: Когда плагин Maven Dependency лежит от нашего партнера JCG Йоава Абрахами в блоге Wix IO .