我的项目是否使用了比我需要的旧版本的依赖项?

时间:2014-05-01 17:50:54

标签: maven maven-3

我工作的地方使用Maven,我们有很多内部库。我们尝试以向后兼容的方式进行更改,但有时我们的某个库需要更新版本的另一个库。如果最终产品最终没有引入更新的库版本,那么这可能会导致问题。

对于每个最终产品,我们都有一个dependencyManagement部分,声明应该为项目使用哪些版本的传递依赖项。我们这样做,而不是让Maven找出要使用的版本,因为我们想要控制使用哪个版本的库。

即使我们让maven弄清楚应该使用哪个版本的库,也可能会使用旧库,这可能导致ClassNotFoundExceptions等...

当项目的某个依赖项需要更新版本时,是否有Maven插件或方法来确定我的项目是否使用旧版本的依赖项?

mvn dependency:tree但我们有很多的依赖关系,而且我不想手动查看巨人列表。

谢谢!

修改

由于我们有很多库,如果最终产品使用库A,B和C,并且A和B都使用不同版本的C,则不会始终使用最新版本的C.来自Introduction to the Dependency Mechanism

  

依赖关系中介 - 这决定了依赖关系的版本   将在遇到多个版本的工件时使用。   目前,Maven 2.0仅支持使用"最近的定义"   这意味着它将使用最接近的依赖版本   您的项目在依赖树中。你可以随时保证   版本通过在项目的POM中明确声明它。请注意,如果   两个依赖版本在依赖关系树中处于相同的深度,   直到Maven 2.0.8没有定义哪一个会赢,但从那以后   Maven 2.0.9它在声明中的顺序是:第一个   声明获胜

2 个答案:

答案 0 :(得分:2)

由于我们几乎总是以向后兼容的方式进行更改,因此对我们来说最好的解决方案是确保使用最新版本的依赖项。 Maven Enforcer插件带有"需要上限依赖关系"功能完成了这一点。

来自http://maven.apache.org/enforcer/enforcer-rules/requireUpperBoundDeps.html

  

此规则要求解析每个依赖项的版本   在构建期间,等于或高于所有传递依赖   声明。在构建期间解析了每个依赖项的版本   通常是POM中指定的版本或带有的版本   最不可传递的步骤("最近的"定义)。更多   有关Maven依赖关系解析的信息,请参阅Maven站点。

     

这是一个具体的例子。这将导致构建失败:

  <dependencies>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.4.0</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>0.9.9</version>
      <!-- Depends on org.slf4j:slf4j-api:1.5.0 -->
    </dependency>
  </dependencies>
  

因为该项目将使用slf4j-api运行logback-classic 0.9.9   1.4.0和slf4j-api 1.4.0可能与slf4j-api 1.5.0不兼容。

     

这是日志消息:

Failed while enforcing RequireUpperBoundDeps. The error(s) are [
RequireUpperBoundDeps error for org.slf4j:slf4j-api:1.4.0 paths to dependency are:
+-test:TestParent:1.0-SNAPSHOT
  +-org.slf4j:slf4j-api:1.4.0
and
+-test:TestParent:1.0-SNAPSHOT
  +-ch.qos.logback:logback-classic:0.9.9
    +-org.slf4j:slf4j-api:1.5.0
]

我们可能会在我们可以开启或关闭的个人资料中设置此插件。

答案 1 :(得分:1)

我不确定是否会有你想问的插件。一般情况下,较新的版本将是您定居的版本,但这并不总是一个硬规则 - 有时您会推出更新的版本,但旧版本实际上就是您的版本需要。

根据我的经验,您必须孤立地处理每个依赖性问题。

我们处理此问题的方法是结合使用您建议的<dependencyManagement/>部分以及带有<DependencyConvergence/>规则的Maven Enforcer插件。

The dependencyConvergence rule

  

...要求依赖版本号收敛。如果一个项目有   两个依赖项,A和B,都取决于相同的工件C,   如果A依赖于不同版本的C,则此规则将无法构建   那么C的版本取决于B。

基本上,如果您dependency tree中有同一个lib的2个不同版本,则validate phase会失败。

所以:

我的方式是 - 我们通常有多个模块Maven项目,我尝试在父级<dependencyManagement/>部分定义常见的依赖版本 - EG Spring,{ {1}}等。然后在子模块级别,根据需要定义专家Jersey部分。

在我们所有的poms中,我们定义了使用<dependencyManagement/>规则配置的Maven Enforcer插件,如下所示:

<dependencyConvergence/>

然后在每个<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.3.1</version> <executions> <execution> <id>enforce-versions</id> <goals> <goal>enforce</goal> </goals> </execution> </executions> <configuration> <rules> <DependencyConvergence/> </rules> <fail>true</fail> </configuration> </plugin> 版本中,如果有人添加了一个新的依赖项(或者那里有一个新的传递依赖项)与另一个版本发生冲突,那么您的构建将失败,并且您将会得到一个(略微重复的)依赖性问题日志供你处理。

作为终点,我没有看到Maven Enforcer插件使用得太多,但它有really useful rules的负载以及custom rules的能力。

如果确实是<{1}}的{​​{1}},总是想要,我确定你可以编写一个简单的规则来执行此操作。

希望这有帮助,

威尔