Почему Maven не разрешает все зависимости для общей конфигурации?

Резюме

При попытке XMLConfiguration configuration = new XMLConfiguration("config/config.xml"); только с commons-configuration 1.10 мне нужно добавить больше зависимостей (а именно commons-collections не новее, чем 3.2.1) в мою настройку maven. Почему это так и почему maven просто не разрешает все необходимые зависимости?

Подробности

Я пытаюсь заставить работать commons-configuration. Сначала я хотел использовать последнюю версию, 2.0-alpha2, которая вообще не работала, так как я не смог настроить Maven для загрузки правильных ресурсов, но это уже другая история.

После того, как я узнал, что версия 1.10 на самом деле является «одной целых десять десятых» (а не «одной точкой один ноль») и, следовательно, является последней версией Commons-конфигурации 1 (и описанной в руководствах), я решил вместо этого попробовать. .

Для моих зависимостей maven (интегрированных в eclipse) я использовал:

<dependency>
    <groupId>commons-configuration</groupId>
    <artifactId>commons-configuration</artifactId>
    <version>1.10</version>
</dependency>

Однако при проверке этого примера:

package main;

import java.util.Iterator;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;

public class ConfigurationTest {
    public static void main(String... args) {
        try {
            XMLConfiguration configuration = 
                    new XMLConfiguration("config/config.xml");
            Iterator<String> iterator = configuration.getKeys();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }
    }
}

со следующим config.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<configuration>
  <property>value</property>
  <nestedproperty>
    <arrayvalue>0,1,2,3,4</arrayvalue>
    <property>anothervalue</property>
  </nestedproperty>
</configuration>

Я получил ошибку:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/collections/CollectionUtils
    at org.apache.commons.configuration.XMLConfiguration.constructHierarchy(XMLConfiguration.java:640)
    at org.apache.commons.configuration.XMLConfiguration.initProperties(XMLConfiguration.java:596)
    at org.apache.commons.configuration.XMLConfiguration.load(XMLConfiguration.java:1009)
    at org.apache.commons.configuration.XMLConfiguration.load(XMLConfiguration.java:972)
    at org.apache.commons.configuration.XMLConfiguration$XMLFileConfigurationDelegate.load(XMLConfiguration.java:1647)
    at org.apache.commons.configuration.AbstractFileConfiguration.load(AbstractFileConfiguration.java:324)
    at org.apache.commons.configuration.AbstractFileConfiguration.load(AbstractFileConfiguration.java:261)
    at org.apache.commons.configuration.AbstractFileConfiguration.load(AbstractFileConfiguration.java:238)
    at org.apache.commons.configuration.AbstractHierarchicalFileConfiguration.load(AbstractHierarchicalFileConfiguration.java:184)
    at org.apache.commons.configuration.AbstractHierarchicalFileConfiguration.<init>(AbstractHierarchicalFileConfiguration.java:95)
    at org.apache.commons.configuration.XMLConfiguration.<init>(XMLConfiguration.java:261)
    at main.ConfigurationTest.main(ConfigurationTest.java:12)

Сначала я надеялся, что они (не я, конечно) просто испортили некоторые зависимости от maven, и, поскольку я все равно больше не беспокоился о том, какую версию использовать (у меня не работала версия 2.0, помните?), я решил перейти на версию 1.9, заменив зависимость maven на:

<dependency>
    <groupId>commons-configuration</groupId>
    <artifactId>commons-configuration</artifactId>
    <version>1.9</version>
</dependency>

Это решило проблему довольно хорошо, тестовый пример работает:

property
nestedproperty.arrayvalue
nestedproperty.property

Но когда я попытался реализовать пример, аналогичный тому, на который ссылается в очень простой пример конфигурации Apache-commons, выдается NoClassDefFoundError и его последующие -up вопрос Я получил точно такую ​​​​же ошибку, на которую есть ссылка, но решение, импорт org.apache.commons.beanutils.PropertyUtils, не работает, так как мне не хватает beanutils. Таким образом, в основном, понизив версию, я просто переключился с ошибки отсутствия коллекций на отсутствие beanutils.

Существует 10.html" rel="nofollow noreferrer">обзор зависимостей, где вы можете увидеть, какие зависимости используются, когда ты делаешь что. Я был немного удивлен, узнав, что версия 1.10 теперь использует другие зависимости (а именно CollectionUtils), чем 1.9 в вызове конструктора. Поскольку в 1.10, как и в 1.9, были проблемы с зависимостями, я просто придерживался более новой версии.

Я нашел CollectionUtils, расположенный в следующем артефакте (на что мне указал его репозиторий maven< /а>):

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
</dependency>

К сожалению, этот (сначала не очевидный для меня) определяет класс CollectionUtils не в пакете collections, а в пакете collections4. На эту проблему намекали в обзоре зависимостей, но они упоминали только о возможных проблемах с более ранними версиями... Я, похоже, больше не думал об этом, а просто изменил зависимость на:

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.1</version>
</dependency>

У меня все работает (более или менее, но исключения, которые я получаю сейчас, больше не зависят от отсутствующих определений классов) после использования этих зависимостей:

<dependencies>
    <dependency>
        <groupId>commons-configuration</groupId>
        <artifactId>commons-configuration</artifactId>
        <version>1.10</version>
    </dependency>
    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
    </dependency>
    <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.9.2</version>
    </dependency>
</dependencies>

Почему я должен сам добавлять зависимости? Я думал, что весь смысл использования maven заключается в том, чтобы избежать таких вещей, и с точки зрения javadocs и исходных файлов он неплохо справляется.

К настоящему времени я убежден, что зависимости не включены в иерархию по замыслу (так ли это?), вероятно, чтобы избежать накладных расходов. Однако есть ли способ либо просто получить все зависимости сразу, либо, что еще лучше, получить все зависимости, которые мне нужны? И почему он так устроен?


person Sebastian Höffner    schedule 24.02.2015    source источник


Ответы (3)


Если мы проанализируем POM commons-configuration, мы увидим, что зависимость commons-collections не является обязательной:

  <dependencies>
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.2.1</version>
      <optional>true</optional>
    </dependency>
    ...

Кроме того, из документов Maven:

Если пользователь хочет использовать функциональность, связанную с дополнительной зависимостью, ему придется повторно объявить эту необязательную зависимость в своем собственном проекте.

person Evgeniy Dorofeev    schedule 24.02.2015

Эта проблема объясняется на странице зависимостей во время выполнения веб-сайта Commons Configuration.

Цитата с той страницы:

В Maven POM объявлено множество зависимостей. Все это необходимо во время компиляции. Однако во время выполнения вам нужно добавить в путь к классам только те зависимости, которые требуются для частей пакета конфигурации Commons, которые вы используете. Следующая таблица поможет вам определить, какие зависимости вы должны включить на основе компоненты, которые вы собираетесь использовать.

Другие ответы объясняют, почему это работает с точки зрения Maven. Этот ответ предназначен для того, чтобы обеспечить своего рода защиту для людей, занимающихся конфигурацией Commons. Тебя хоть предупредили!

В тех случаях, когда зависимости связаны с другими компонентами Apache Commons, они потратили время на тестирование различных версий и разместили информацию о совместимости внизу этой страницы.

person Duncan Jones    schedule 24.02.2015
comment
Спасибо, я нашел эти версии там, так как они помогли мне запустить проект. Я думаю, что упустил разницу между временем компиляции и временем выполнения в этом абзаце, но с двумя другими ответами теперь все это имеет смысл. - person Sebastian Höffner; 24.02.2015

Maven пытается разрешить все необходимые зависимости для библиотеки, которую вы используете в своем файле pom. Что ж, иногда у вас есть некоторые зависимости, которые необходимы только для определенных функций, и вы не хотите заставлять пользователя вашей зависимости загружать ее, если он ее не использует. Затем вы объявляете свою зависимость как необязательную. Это произошло с commons-collections в commons-configuration. См. commons-configuration-pom здесь

person Jan    schedule 24.02.2015
comment
Замечательно, что вы предоставили ссылки на документацию и файл pom. Обратите внимание, что было бы улучшением (и больше в духе stackoverflow), если бы вы также включили в свой ответ определенные части документации и pom, как это сделал Евгений Дорофеев (у него отсутствуют ссылки на источники, которые вы предоставили) . Ваши два ответа очень хорошо сочетаются друг с другом. - person Sebastian Höffner; 24.02.2015