为什么Maven没有解析commons-configuration的所有依赖项?

时间:2015-02-24 10:04:03

标签: java maven apache-commons-config

摘要

仅使用XMLConfiguration configuration = new XMLConfiguration("config/config.xml");尝试commons-configuration 1.10时,我需要在maven设置中添加更多依赖项(即commons-collections而不是3.2.1)。为什么会这样,为什么maven不能简单地解决所有需要的依赖?

详细

我想让commons-configuration开始工作。首先,我想使用最新版本2.0-alpha2,因为我无法配置Maven来下载正确的资源,所以它完全不能正常工作 - 但这是另一个故事。

在我发现版本1.10实际上是“一点十”(而不是“一点一零”)并因此最新版本的commons-configuration 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工作,还记得吗?)我决定去通过使用:

替换maven依赖关系到版本1.9
<dependency>
    <groupId>commons-configuration</groupId>
    <artifactId>commons-configuration</artifactId>
    <version>1.9</version>
</dependency>

这很好地解决了问题,测试用例正在运行:

property
nestedproperty.arrayvalue
nestedproperty.property

但是当我尝试实现与Very simple Apache-commons configuration example throws NoClassDefFoundError及其后续问题中引用的类似示例时,我得到了完全相同的错误,但是引入org.apache.commons.beanutils.PropertyUtils的解决方案是不工作因为我错过了豆腐。所以基本上通过降级我只是从错过集合的错误切换到缺少beanutils。

有一个dependency overview,您可以在其中查看执行操作时使用的依赖项。我有点惊讶地发现版本1.10现在使用了其他依赖项(即CollectionUtils)而不是构造函数调用中的1.9。由于在1.10和1.9中存在依赖性问题,我只是坚持使用较新的版本。

我发现CollectionUtils位于以下工件中(正如我maven repository指出的那样):

<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和源文件而言,它做得非常好。

到目前为止,我确信依赖关系不会被设计包含在层次结构中(是这样吗?),可能是为了避免开销。但是有没有办法可以简单地获取所有依赖项,甚至更好地获取我需要的所有依赖项?为什么这样设计?

3 个答案:

答案 0 :(得分:11)

如果我们分析commons-configuration的POM,我们会发现commons-collections依赖是可选的:

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

此外,来自Maven文档:

  

如果用户想要使用与可选项相关的功能   依赖性,他们将不得不重新声明可选的依赖关系   他们自己的项目。

答案 1 :(得分:3)

此问题在Commons Configuration网站的Runtime dependencies页面上进行了解释。

从该页面引用:

  

在Maven POM中声明了很多依赖项。这些都是在编译期间所需要的。 在运行时,您只需要将依赖项添加到您正在使用的Commons Configuration软件包部分所需的类路径中。下表可帮助您确定必须包含哪些依赖项。您打算使用的组件。

其他答案解释了为什么这可以从Maven的角度来看。这个答案旨在为Commons配置人员提供各种防御。他们至少警告过你!

如果依赖项存在于其他Apache Commons组件上,他们会花时间测试各种版本,并在该页面底部发布了有关兼容性的信息。

答案 2 :(得分:1)

Maven尝试解决您在pom中使用的库的所有必要依赖项。好吧,有时你有一些依赖项,这些依赖项只是某些特定功能所必需的,如果他不使用它,你不想强迫你的依赖项用户下载它。然后你将你的依赖声明为optional。这发生在commons-collections内的commons-configuration。请参阅commons-configuration - pom here