为什么“提供”范围的依赖关系会隐藏Maven中的传递依赖?

我的Maven项目中有三个模块(稍微简化):

  • model包含JPA带注释的实体类
  • 持久化实例化EntityManager并在其上调用方法
  • 应用程序模型中创建类的实例,设置一些值并将它们传递给持久性

模型持久性显然取决于javax.persistence ,但我认为应用程序不应该。

javax.persistence依赖项被移动到顶级POM的dependencyManagement部分,因为它出现在许多子模块中,我只引用该条目。

令我惊讶的是,当我将其范围设置为provided时,我必须在application引用依赖项,而我不必在其范围是compile

使用提供的范围,如果我没有在应用程序dependencies列出它,则构建将失败并显示来自javac的错误消息:

com.sun.tools.javac.code.Symbol $ CompletionFailure:找不到javax.persistence.InheritanceType的类文件

这是怎么回事?

模型和持久性显然取决于javax.persistence,但我认为应用程序不应该。

确实如此。 但是传递依赖性解析与您的问题无关(实际上, javax.persistenceprovidedmodelpersistenceapplication依赖于compile范围,因此它被省略,如3.4.4。传递依赖性中所述 )。

在我看来,你是这个bug的受害者: http : //bugs.sun.com/view_bug.do?video_id = 6550655

我对使用inheritance注释的EJB3实体有​​同样的问题: @Inheritance(strategy=InheritanceType.SINGLE_TABLE)

当ejb3 annatations不在类路径上时,使用此实体的客户端类将无法编译,但崩溃时出现以下消息: com.sun.tools.javac.code.Symbol$CompletionFailure: class file for javax.persistence.InheritanceType not found

[…]

请注意,这是bug 6365854的一个特例(据报道是固定的); 这里的问题似乎是注释使用枚举作为其值。

当前的解决方法是将缺少的枚举添加到CLASSPATH。

在您的情况下,“更糟糕”的方法是将javax.persistence作为provided依赖项添加到application模块。 但这是JVM错误的解决方法, application不应该需要该依赖项来编译。

嗯,因为提供的依赖是不可传递的? 这是maven的内置行为。

dependencyManagement部分声明了使用它们时的依赖关系,而不是您使用它们。 因此,您仍需要声明一个最小的依赖项声明,以便在子项目中应用该配置。 有关详细信息,请参阅Maven书籍的依赖关系管理部分 。

所需的最小值通常是groupId和artifactId。

如果要在不声明配置的情况下inheritance配置,则应在父的dependencies部分中定义它,而不是dependencyManagementdependencyManagement