Hibernate 和 Apache Felix 的依赖链冲突

Posted

技术标签:

【中文标题】Hibernate 和 Apache Felix 的依赖链冲突【英文标题】:Dependency chain conflicts for Hibernate and Apache Felix 【发布时间】:2014-06-23 02:14:18 【问题描述】:

我理解 OSGi 抱怨多个依赖链的概念 - 一个包不止一次可用,当导入包没有准确指定它需要哪个版本时,所以 OSGi 容器可能会遇到不知道什么的麻烦提供。

不幸的是,我本周遇到了这样的问题,但涉及的两个捆绑包都是第三方捆绑包,所以我无法真正影响他们的进出口。这是我收到的两条错误消息:

org.osgi.framework.BundleException: Uses constraint violation. Unable to resolve bundle revision org.hibernate.core [28.0] because it is exposed to package 'javax.xml.stream' from bundle revisions com.springsource.javax.xml.stream [23.0] and org.apache.felix.framework [0] via two dependency chains.

Chain 1:
  org.hibernate.core [28.0]
    import: (osgi.wiring.package=javax.xml.stream)
     |
    export: osgi.wiring.package=javax.xml.stream
  com.springsource.javax.xml.stream [23.0]

Chain 2:
  org.hibernate.core [28.0]
    import: (osgi.wiring.package=javax.xml.transform.stax)
     |
    export: osgi.wiring.package=javax.xml.transform.stax; uses:=javax.xml.stream
    export: osgi.wiring.package=javax.xml.stream
  org.apache.felix.framework [0]
    at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:3824) 
    at org.apache.felix.framework.Felix.startBundle(Felix.java:1868)
    at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1191)
    at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:295)
    at java.lang.Thread.run(Thread.java:724)



org.osgi.framework.BundleException: Uses constraint violation. Unable to resolve bundle revision org.hibernate.core [28.0] because it is exposed to package 'javax.xml.stream' from bundle revisions org.apache.felix.framework [0] and com.springsource.javax.xml.stream [23.0] via two dependency chains.

Chain 1:
  org.hibernate.core [28.0]
    import: (osgi.wiring.package=javax.xml.stream)
     |
    export: osgi.wiring.package=javax.xml.stream
  org.apache.felix.framework [0]

Chain 2:
  org.hibernate.core [28.0]
    import: (osgi.wiring.package=org.dom4j.io)
     |
    export: osgi.wiring.package=org.dom4j.io; uses:=javax.xml.stream
  com.springsource.org.dom4j [27.0]
    import: (&(osgi.wiring.package=javax.xml.stream)(version>=1.0.1)(!(version>=2.0.0)))
     |
    export: osgi.wiring.package=javax.xml.stream
  com.springsource.javax.xml.stream [23.0]
    at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:3824)
    at org.apache.felix.framework.Felix.startBundle(Felix.java:1868)
    at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1191)
    at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:295)
    at java.lang.Thread.run(Thread.java:724)

当我尝试从已安装的捆绑包中删除 com.springsource.javax.xml.stream 时,com.springsource.org.dom4j 抱怨缺少包 javax.xml.stream

我检查了org.apache.felix.frameworkMANIFEST.MF 文件,因为我真的很惊讶Felix 显然导出了javax.xml.stream,但它不包含这样的条目。此外,dom4j 捆绑包不会根据其清单重新导出流包。

如果有任何提示可以让我更接近回答这个依赖链问题的来源,我将不胜感激。从我的角度来看,除了 com.springsource.javax.xml.stream 导出所说的包之外,我找不到捆绑包-

【问题讨论】:

【参考方案1】:

如果包在捆绑包中以及 bpot 类路径 (JDK) 中可用,这通常是一个问题。如果该包是从另一个 JDK 包连接的,并且也直接从一个包连接,那将是一个更大的问题。在您的情况下,问题如下:

javax.xml.transform.stax 仅在引导类路径 (JDK) 上可用,因此 hibernate.core 连接到该包。 由于 javax.xml.transform.stax 来自引导类路径,它可以连接到引导类路径上的另一个包。它需要 javax.xml.stream 以便连接到来自 JDK 的包

我们有链:

hibernate.core -> javax.xml.transform.stax -> javax.xml.stream

另一方面,hibernate.core 直接连接到 javax.xml.stream。可能它甚至在 Import-Package 部分中使用了一个版本,因此它无法连接到来自 JDK 的包。

我们有链:

hibernate.core -> javax.xml.stream

这会产生冲突。由于 hibernate.core 在 javax.xml.transform.stax 的帮助下使用 javax.xml.stream API,hibernate.core 和 javax.xml.transform.stax 应该使用与 javax.xml.stream 相同的类。但是,他们没有。

您有几个选项可以解决您的问题:

您可以安装包含 javax.xml.transform.stax 包的捆绑包。该包将能够连接到来自包的 javax.xml.stream 包,并且 hibernate.core 可以连接到包含 javax.xml.transform.stax。你可以祈祷线路永远没问题。

根据我的经验,框架启动后线路良好。由于包中的包版本较高,因此当包从其他包中导入时,它们将是首选。但是,当捆绑包在运行时更新和刷新时,接线经常会出错。我不知道为什么,它只是发生了。

为了避免所有问题,我通常会从引导类路径中排除捆绑包中也可用的那些包。

您的下一个问题可能是这些 API 经常使用工厂类。当有人使用这样的工厂时,工厂类的类加载器也必须看到实现类。我创建了一个包含所有 xmlcommons 包的 bundle。它包含所有 xml-apis 类和它们的实现(xerces、xalan 等)。它可能对你有帮助。如果此捆绑包解决了您的问题,请告诉我。在这种情况下,我最终会花时间收集所有必要的数据(授权到 pom、来源)并将其发布到 maven-central,以便它也可以帮助其他人。

【讨论】:

您好 Balazs,感谢您的详细回答。它有助于点亮事业。我尝试为 javax.xml.transform.stax 安装一个包,但这只会导致下一个包导致问题并且越来越多地弄乱我的依赖项。由于框架可能永远不会在运行时看到包更新,因此解决方案已经足够好了。 --- 您能否提供有关如何从类路径中排除包的更多信息?我可以通过代码做到这一点还是它是一些启动配置? 这是一个启动配置,你可以通过系统属性来完成。遗憾的是,您不能进行排除,但您可以定义引导类路径的内容。如果您使用 felix,请参阅felix.apache.org/site/… 的“org.osgi.framework.system.packages”系统属性。该值会很长,因为您应该在此处列出您从 JDK 使用的每个包。 github.com/everit-org/osgi-liquibase-bundle/blob/… 提供了一个示例 好吧......我以前见过,但我的某些部分希望你在某个地方有一个更好的解决方案;)但最终重要的是解决了问题:)有时我会更深入地研究捆绑包的依赖关系,以便稍微清理一下那个包混乱,但至少它可以作为一个开始,非常感谢! --- 在我忘记之前,你的捆绑包看起来真的很酷!由于政策限制,我不能将它用于我的项目,但我相信它会帮助很多人。

以上是关于Hibernate 和 Apache Felix 的依赖链冲突的主要内容,如果未能解决你的问题,请参考以下文章

Apache Felix 和 Apache Tomcat 有啥区别

OSGi:Apache Felix 和 Apache Karaf 有啥区别?

m2eclipse Error:ArtifactTransferException: Failure to transfer org.apache.felix:org.apache.felix.res

org.apache.felix.framework-5.6.12源码解析——org.apache.felix.framework文件夹最后的部分

Apache Felix 和 Glassfish V2

使用 Java 8 和 JavaFX 测试 Apache Felix