为什么当两个链结束于同一束时,使用约束会被违反?

151
我有四个捆绑包,每个包只包含一个清单。这些包是:
  • app,它导入com.example.foo.fragmentcom.example.bar
  • foo,它导出com.example.foo;uses:=com.example.foo.cfg
  • foo.fragment,它是附加到foo的片段,它导出com.example.foo.fragmentcom.example.foo.fragment.cfg;uses:=com.example.foo.fragment
  • bar,它导出com.example.bar并导入com.example.foo
捆绑包级别依赖关系图:
app -> bar
|       |
|       v
|      foo
|       |
v       v
foo.fragment

如果我在JBoss AS 7.2中一次性安装这些捆绑包,它们可以正常工作。但是,如果我在其他捆绑包之后,第一次安装或成功启动并卸载后再安装 app 捆绑包,则会出现以下使用限制违规:

Caused by: org.osgi.service.resolver.ResolutionException: Uses constraint violation. Unable to resolve resource com.example.app [HostBundleRevision[com.example.app:0.0.
0]] because it is exposed to package 'com.example.foo.fragment' from resources com.example.foo [HostBundleRevision[com.example.foo:0.0.0]] and com.example.foo [HostBund
leRevision[com.example.foo:0.0.0]] via two dependency chains.

Chain 1:
  com.example.app [HostBundleRevision[com.example.app:0.0.0]]
    import: null
     |
    export: osgi.wiring.package=com.example.foo.fragment
  com.example.foo [HostBundleRevision[com.example.foo:0.0.0]]

Chain 2:
  com.example.app [HostBundleRevision[com.example.app:0.0.0]]
    import: null
     |
    export: osgi.wiring.package=com.example.bar; uses:=com.example.foo
  com.example.bar [HostBundleRevision[com.example.bar:0.0.0]]
    import: null
     |
    export: osgi.wiring.package=com.example.foo; uses:=com.example.foo.fragment
    export: osgi.wiring.package=com.example.foo.fragment
  com.example.foo [HostBundleRevision[com.example.foo:0.0.0]]
        at org.apache.felix.resolver.ResolverImpl.checkPackageSpaceConsistency(ResolverImpl.java:1142)
        at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:197)
        at org.jboss.osgi.resolver.felix.StatelessResolver.resolve(StatelessResolver.java:56)
        at org.jboss.osgi.framework.internal.ResolverImpl.resolveAndApply(ResolverImpl.java:137)
        at org.jboss.as.osgi.service.BundleLifecycleIntegration$BundleLifecycleImpl.activateDeferredPhase(BundleLifecycleIntegration.java:296)
        ... 31 more

完整的清单如下:
app.jar/META-INF/MANIFEST.MF
----------------------------
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.example.app
Import-Package: com.example.foo.fragment,com.example.bar
----------------------------
foo.jar/META-INF/MANIFEST.MF
----------------------------
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.example.foo
Export-Package: com.example.foo;uses:="com.example.foo.cfg"
-------------------------------------
foo.fragment.jar/META-INF/MANIFEST.MF
-------------------------------------
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.example.foo.fragment
Fragment-Host: com.example.foo
Export-Package: com.example.foo.fragment,com.example.foo.cfg;uses:="co
 m.example.foo.fragment"
----------------------------
bar.jar/META-INF/MANIFEST.MF
----------------------------
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.example.bar
Export-Package: com.example.bar;uses:="com.example.foo"
Import-Package: com.example.foo

我无法在独立的Apache Felix 4.2.1中重现上述错误。

这种行为的原因是什么?如果我从foo.fragment清单中删除Fragment-Host: com.example.foo行,则可以重新安装app而没有错误。这是JBoss AS 7.2中的一个bug吗?


1
我同意这很奇怪。我倾向于将其视为JBoss AS框架实现中的一个漏洞,如果是这种情况,应该在JBoss邮件列表和/或问题跟踪器上报告。 - Neil Bartlett
在研究了一会儿后,我注意到只有当我的应用程序在 JBoss 启动时未部署时才会出现这种情况。也许确实存在另一个导出 org.hibernate.annotations 的捆绑包,如果 OSGi 平台在没有我的应用程序的情况下启动,则 OSGi 平台将其解析为 Spring ORM 捆绑包的依赖项。然后我部署我的应用程序,OSGi 无法解析它,因为它与解析为 Spring ORM 捆绑包的 org.hibernate.annotations 捆绑包不兼容。这听起来可行吗? - Emil Lundberg
4
我现在也在JBoss社区启动了一次讨论:https://community.jboss.org/thread/229824 - Emil Lundberg
1
这看起来像是一个 bug。Fragment bundles 应该表现得像它们是宿主 bundle 的一部分。在执行类路径一致性检查时,JBoss 在某些情况下似乎将 fragment 视为单独的 bundle。 - jgibson
可能是重复的问题:Constraints from the fragment conflict with the host - Paul Sweatte
显示剩余5条评论
1个回答

1
你不需要在应用程序中导入foo.fragment的依赖项,它将从foo中解析。因此,只需删除该依赖项并重新部署即可。这个问题是由于循环依赖引起的。

3
不是循环依赖。如果foo.fragment依赖于app,则会产生循环依赖。但是,现在是app依赖于foo.fragment,因此不存在循环。但是,从app到foo.fragment的显式依赖可能是不必要的,这是正确的。 - vog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接