我的项目有两个OSGi包(A和B)需要使用不同版本的javax.activation
- A需要1.1.0版本,而B需要1.1.1。
默认情况下,在AEM 5.6.1中,已经安装了一个捆绑包,用于导出捆绑A正在使用的版本1.1.1。为了使它使用1.1.0 instaed,我使用了boot委托从JRE 7获取了1.1.0的系统包的javax.activation。我使用AEM 5.6.1中的sling.properties文件设置它。
如果我在此sling.properties文件中为javax.activation提供大于1.1.1的版本,则A和B都使用系统版本(即使manifest.mf
中指定了import-packages的版本文件);但如果我给的版本低于1.1.1,则两个捆绑包都使用AEM提供的版本。
如何配置我的软件包以便为Bundle B中的Bundle A使用不同版本的javax.activation?
答案 0 :(得分:2)
如果你想在套装A中使用完全1.1.0版本,那么你应该在A的清单文件中指定它:
Import-Package: javax.activation;version="[1.1.0,1.1.0]"
对于捆绑包B清单将是:
Import-Package: javax.activation;version="[1.1.1,1.1.1]"
答案 1 :(得分:1)
由于OSGI捆绑解析规则,这可能非常困难。看看这篇文章 - 我发现这是对适用的各种规则的一个很好的解释。具体来说,请查看uses
指令:
http://www.christianposta.com/blog/?p=241
如果有两种方法可以使用相同的版本(但我知道这可能并不总是可行),生活将变得更加简单。
这来自上面的文章:
对于每个Import-Package包声明,必须有一个 具有相同包的相应Export-Package
Bundles还可以将其他属性附加到它导入的包或 出口。如果我们在示例中添加了一个版本属性,该怎么办:
Bundle-Name:Bundle A Import-Package:org.apache.foo; version =" 1.2.0"
这意味着,Bundle A依赖于org.apache.foo包 最低版本1.2.0。是的,你读得正确。虽然有OSGI 如果没有指定范围,则可以指定一系列版本 而是使用固定版本,它将导致“最小”的含义 固定价值。如果有相同的更高版本 包,将使用更高版本。所以捆绑A将无法解决 除非有相应的B组导出,否则正确 必需的包裹:
Bundle-Name:Bundle B Export-Package:org.apache.foo; version =" 1.2.0"
请注意反之亦然......如果Bundle B导出版本1.2.0, Bundle A不需要指定版本1.2.0。它可以使用它 导入并解决得很好:
Bundle-Name:Bundle A Import-Package:org.apache.foo
这是因为导入声明了他们需要的版本。出口了 version没有指定导入包必须使用的任何内容(哪个 适用于任何属性,而不仅仅是版本)。 Import-Package指令 确切地说它需要什么版本(或属性),以及相应的 必须存在具有相同属性的Export-Package
如果您有Bundle A导入包的场景会发生什么 它指定了由两个包提供的版本:
Bundle-Name:Bundle A Import-Package:org.apache.foo; version =" 1.2.0"
Bundle-Name:Bundle B Export-Package:org.apache.foo; version =" 1.2.0"
Bundle-Name:Bundle C Export-Package:org.apache.foo; version =" 1.2.0"
Bundle A使用哪一个捆绑包?答案取决于哪个 首先安装捆绑(B或C)。首先使用安装的捆绑包 在具有相同版本的多个包时满足依赖性 找到了
热部署捆绑包时,事情会变得复杂一些 一些已经解决后。如果安装Bundle B怎么办? 首先,然后尝试安装Bundle A和以下Bundle D. 一起:
Bundle-Name:Bundle D Export-Package:org.apache.foo; version =" 1.3.0"
正如我们从上面看到的,Bundle A中的版本声明(1.2.0) 表示最低版本1.2.0;所以如果有更高版本可用 然后它会选择(在这种情况下来自Bundle D的版本1.3.0)。 然而,这带来了另一个捆绑的时间规则 解决方案:已经解决的捆绑包具有更高的分辨率 那些未解决的优先级
原因是OSGI框架倾向于支持可重用性 对于给定的捆绑。如果它已经解决,而新的捆绑包需要它,那么它 如果它不会尝试拥有相同包的许多其他版本 不需要。捆绑“使用”指令
上述捆绑解析规则仍然不够而且 错误的类仍然可以在运行时使用,从而导致类转换 例外或类似。你能看到可能遗漏的东西吗?
如果我们有这种情况怎么办? Bundle A导出包, org.apache.foo,包含一个类FooClass。 FooClass有一个方法 返回BarClass类型的对象,但未定义BarClass 在bundle的类空间中,它是这样导入的:
1 2 3公共课FooClass { public BarClass execute(){...}}
Bundle-Name:Bundle A Import-Package:org.apache.bar; version =" 3.6.0" Export-Package:org.apache.foo; version =" 1.2.0"
到目前为止,只要有另一个捆绑包,一切都很好 正确导出org.apache.bar并使用正确的版本。
Bundle-Name:Bundle B Export-Package:org.apache.bar; version =" 3.6.0"
这两个捆绑包可以很好地解决。现在,如果我们再安装两个 bundle,Bundle C和Bundle D看起来像这样:
Bundle-Name:Bundle C Import-Package:org.apache.foo; version =" 1.2.0", org.apache.bar;版本=" 4.0.0"
Bundle-Name:Bundle D Export-Package:org.apache.bar; version =" 4.0.0"
我们可以看到Bundle C从Bundle导入了一个包org.apache.foo A. Bundle C可以尝试使用org.apache.foo中的FooClass,但是当它 得到返回值,一种BarClass,会发生什么?捆绑A. 期望使用版本3.6.0的BarClass,但是捆绑C正在使用 版本4.0.0。所以使用的类在bundle中是不一致的 在运行时(即,您可能会遇到某种类型的不匹配或类 抛出异常),但在部署时一切仍然可以解决 时间遵循上述规则。我们需要的是告诉任何人 导入我们使用特定类的org.apache.foo org.apache.bar的版本,如果你想使用org.apache.foo你 必须使用我们导入的相同版本。这正是它的用途 指令呢。让我们更改捆绑包A以准确指定:
Bundle-Name:Bundle A Import-Package:org.apache.bar; version =" 3.6.0" Export-Package:org.apache.foo; version =" 1.2.0"&#34 ;; uses:= org.apache.bar
鉴于Bundle A的新配置,捆绑包不会 从上面正确解决。捆绑C无法解决,因为它 导入org.apache.foo,但Bundle A上的“uses”约束指定 C必须使用与A(3.6.0)相同的版本 org.apache.bar,否则捆绑在尝试时将无法解析 部署。对此的解决方案是更改Bundle C中的版本 org.apache.bar为3.6.0。