为什么“提供”范围的依赖关系会隐藏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.persistence
被provided
给model
和persistence
, application
依赖于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
部分中定义它,而不是dependencyManagement
于dependencyManagement