OSGI的Import-Package:version和bundle-version有什么区别?

6

我在将一个OSGi bundle加载到第三方框架时遇到了问题。它一直拒绝我的bundle,因为我指定的Import-Package版本不存在,尽管我知道它们正在加载我想要/需要的版本的bundles。为了解决这个问题,我暂时禁用了我的版本要求,但这有点丑陋。

Import-Package: com.ghc.ghTester.expressions,org.apache.ws.security;vers
 ion=0,org.apache.ws.security.components.crypto;version=0,org.apache.ws.
 security.message;version=0,org.apache.ws.security.message.token;version
 =0,org.apache.ws.security.processor;version=0

当我查看我的依赖清单时,我看到:
Bundle-Version: 1.5.11
Bundle-ClassPath: wss4j-1.5.11.jar
Bundle-Vendor: Apache
Export-Package: org.apache.ws.axis.security,
 org.apache.ws.axis.security.handler,
 org.apache.ws.security,
 org.apache.ws.security.action,
 org.apache.ws.security.components.crypto,
 org.apache.ws.security.conversation,
 org.apache.ws.security.conversation.dkalgo,
 org.apache.ws.security.handler,
 org.apache.ws.security.message,
 org.apache.ws.security.message.token,
 org.apache.ws.security.processor,
 org.apache.ws.security.saml,
 org.apache.ws.security.transform,
 org.apache.ws.security.util

在向框架小组投诉后,他们告诉我需要在我的Import-Package语句中使用bundle-version而不是version,例如:

Import-Pacakge: org.apache.ws.security;bundle-version=[1.5.0,2)

我已经阅读了OSGi规范(第50页),但似乎无法理解这两个值之间的细微差别:
开发人员可以指定任意匹配属性。请参见第58页的属性匹配。以下任意匹配属性是预定义的:
• version - 选择导出程序包版本的版本范围。语法必须遵循第36页的版本范围。有关版本选择的更多信息,请参见第54页的语义化版本控制。如果未指定此属性,则假定为[0.0.0,∞)。
• specification-version - 此属性是版本属性的别名,仅为了便于从早期版本迁移。如果存在版本属性,则值必须相等。
• bundle-symbolic-name - 导出束的束符号名称。对于片段束,这将是主机束的符号名称。
• bundle-version - 选择导出束版本的版本范围。默认值为[0.0.0,∞)。请参见第54页的语义化版本控制。对于片段束,版本来自主机束。
请问有人能解释一下versionbundle-version之间的区别吗?从我阅读文档的方式来看,bundle-version(即manifest中的Bundle-Version)将扩展到包中的所有包。那么在Import-Package语句上,包版本(即版本)不是与bundle-version(即bundle-version)相同吗?为什么可以以不同的方式指定这两个版本号?
1个回答

12

简单来说:bundle-version 绑定的是导出该包的 bundle 的版本,而 version 绑定的是该包本身的版本。

你几乎从不想在导入时使用bundle-version。导出 bundle 的版本基本上是无关紧要的……实际上当你导入一个包时,你甚至不应该关心导出它的 bundle 的身份。你关心的是包本身,而不是它来自哪个 bundle。

是谁告诉你要使用bundle-version的?可能有一些非常特殊的原因,但我觉得不太可能。更有可能的是告诉你这个的人错了。

你问道:

那么在 Import-Package 语句中,包版本(即:version)和 bundle 版本(即:bundle-version)不是一样的吗?

不是!Bundle 版本与包版本无关。当你更改一个包时,你会更改该包的版本。Bundle 只是一种交付机制。

更新

重新阅读你的问题,我注意到依赖项导出的软件包版本未指定。这意味着框架正在将所有内容导出为版本0.0.0,因为这是未指定版本时的“默认”版本。包的版本绝对不会默认为它所在的 bundle 的版本。不幸的是,似乎这个框架的作者对OSGi没有很好的理解。

更新2

由于你使用的框架没有提供版本信息,我建议创建一个无代码包装 bundle,将软件包重新导出并附加适当的版本。这很容易构建,并且可以将所有的丑陋之处都保留在一个地方。然后任何其他的 bundle 只需以正常版本导入软件包即可。

由于你没有告诉我有问题的 bundle 的 BSN,我将其称为“org.foo”。首先创建一个名为 manifest.txt 的文件,内容如下:

Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.foo.wrapper
Bundle-Version: 1.5.11
Require-Bundle: org.foo; bundle-version="[1.5.11,1.5.11]"
Export-Package: org.apache.ws.axis.security;version=1.5,
 org.apache.ws.axis.security.handler;version=1.5,
 ...

(显然我在这里做了一些关于版本的假设,您可以进行更正。)

现在使用以下命令构建捆绑包:

jar cfm wrapper.jar manifest.txt

现在您拥有这个捆绑包,您的普通捆绑包可以像这样导入一个软件包:

Import-Package: org.apache.ws.security; version="[1.5,2)"
希望您正在使用基于 bnd 的工具,这种情况下会为您生成包括版本范围的 Import-Package 标头。

那么你在哪里/如何指定软件包版本?Manifest中是否有一个声明表明它是哪个版本?或者在package-info.java文件中? - Eric B.
请看我的更新。在捆绑包的源代码中,您可以在 package-info.java 中指定版本,但是看起来您正在使用预构建的二进制捆绑包。在这种情况下,导出版本纯粹由 MANIFEST.MF 中的 Export-Package 标头定义。由于捆绑包没有指定任何版本,因此所有版本都为 0。 - Neil Bartlett
我想我明白了。在我使用的框架中,它们似乎已经采用了预构建的二进制文件(例如:Apache WSS4j 1.5),并重写了一个清单以通过清单条目公开包。因此,如果我将我的依赖项更改为一个捆绑版本,尽管在真正的OSGi环境中它不是技术上正确的,但针对这个特定的框架,我认为它应该可以工作 - 对吗?基本上表明了指定的捆绑版本所公开的所有包?这准确吗? - Eric B.
最好的做法是修复导出包以使用版本。如果失败的话,我想你可以在导入上使用bundle-version属性。你还需要使用bundle-symbolic-name属性,否则你将从任何包的X版本进行导入... 版本仅对于这个特定的包有意义。 - Neil Bartlett
坦白地说,我认为最好编写一个包装器捆绑包,该捆绑包依赖于第三方框架捆绑包(使用Require-Bundle),并重新导出带有版本的这些软件包。这将把所有恶意内容放入一个特殊位置,并避免在其导入中使用奇怪属性来污染您的“普通”捆绑包。 - Neil Bartlett
显示剩余5条评论

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