Странное поведение после замены `mvn clean install` на` mvn clean package` - PullRequest
0 голосов
/ 30 июня 2018

Мой проект получает две зависимости, и у каждого есть класс com.Foo. Разница во втором методе setVersion.

dependency_1  com.Foo does not have method setVersion

dependency_2  com.Foo.serVersion
  • Это нормально, когда я использую mvn clean install для создания файла .war.
  • Когда я изменяю его на mvn clean package, он может успешно скомпилироваться. Но во время выполнения выдается NoSuchMethodError.

Я знаю, что импортировать класс с тем же именем не очень хорошая идея. И я решаю эту проблему, удалив dependency_1.

Но я хочу знать, почему это имеет значение после использования mvn clean package? Или может быть другая проблема, которую я не заметил, вызывая такое поведение?

Ответы [ 2 ]

0 голосов
/ 01 июля 2018

В Maven установка - это просто еще одна фаза, которая берет артефакт, созданный во время фазы package, и помещает его в локальный репозиторий .m2.

Обвинение Maven

Итак, прежде всего, я бы проверил, что mvn clean install и mvn clean package производят один и тот же артефакт в вашей целевой директории.

Для 99% проектов они должны быть одинаковыми, хотя технически возможно написать плагин Maven, который будет применяться для фазы установки или любой фазы между пакетом и установкой. В жизненном цикле Maven по умолчанию есть некоторые фазы между:

Вы можете добавить плагины, которые будут применяться на любом этапе, поэтому прежде всего убедитесь, что у вас нет

  • Предварительная интеграция тест
  • интеграция-тест
  • после интеграции тест
  • проверить

Итак, еще раз, если вы подозреваете Maven, просто запустите mvn clean package, перейдите к директории 'target', скопируйте артефакт в сторону, затем запустите mvn clean install и сравните цель.

Если в вашей организации существует политика, запрещающая запуск mvn install (хотя это довольно странное решение, поскольку установка не затрагивает какие-либо удаленные компоненты и работает локально на вашем компьютере), вы всегда можете переопределить Maven по умолчанию. расположение хранилища:

mvn clean install -Dmaven.repo.local=/alternate/repo/location

Теперь, когда часть Maven, если вы видите, что артефакты одинаковы, то нет причин обвинять Maven :) Проверьте контейнер тогда

Виноват контейнер

Это то, где все становится действительно сложным, потому что обычно контейнеры (и я предполагаю, что здесь у вас есть контейнер, например, tomcat или wildfly), имеют иерархию загрузчиков классов. Нет необходимости говорить, что классы с именем FQDN, но загруженные разными загрузчиками классов, являются совершенно разными классами.

Итак, если есть 2 класса с одинаковым полным доменным именем в разных jar-файлах, и оба jar-файла находятся в WAR (в classpath), загрузчик классов выберет первый, который появится в classpath, и загрузит его.

В Java (в отличие, например, от C ++) классы загружаются динамически (по требованию) при первой попытке загрузки класса и не нужны прямо во время запуска программы.

Добавьте к этому иерархию загрузчика классов (родительский загрузчик классов для всех «общих» классов и загрузчик классов для каждого артефакта), политику изменения порядка поиска (загрузка «родитель - первый» против «загрузка потомок»), настраиваемого на уровне контейнера, и вы получите довольно сложную политику, которая не может быть решена здесь в ответе, если вы хотите понять, что там происходит, вам придется отлаживать контейнер.

Конечно, мой совет очевиден - просто не поддерживайте эти два класса в одном пакете - выбирайте разные классы (разные пакеты, разные имена классов), возможно, интерфейс с разными реализациями, есть много опций.

Но мое внутреннее чувство говорит о том, что вы уже знаете это, так что это едва ли можно ответить как ответ. :)

0 голосов
/ 30 июня 2018

Для меня это звучит как проблема с загрузчиком классов. Вы уверены, что результаты повторяются в течение нескольких тестов?

Если у вас есть 2 класса с одинаковым идентификатором на пути к классам, порядок загрузки зависимостей становится значительным, а последующие классы перезаписывают более ранние. Чаще всего эта проблема проявляется как «непоследовательное поведение», особенно если вы сами не определяете порядок (через -classpath), а зависимости загружаются из каталога (например, WEB-INF/lib), тогда ваша судьба находится в руками любой библиотеки IO читает файлы.

Вы правы, чтобы удалить дублирующую зависимость, хотя, это рецепт для катастрофы!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...