我的项目有两个OSGi包(A和B),它们需要使用不同版本的javax.activation -A需要版本1.1.0,而B需要1.1.1。
默认情况下,在AEM 5.6.1中,已经安装了导出1.1.1版的捆绑包,捆绑包A正在使用该捆绑包。为了使其使用1.1.0安装,我使用引导委托从系统包1.1.0的JRE7中获取javax.activation。我正在使用AEM5.6.1中的sling.properties文件设置此设置。
如果我在这个sling.properties文件中给出了高于1.1.1的javax.activation版本,A和B都在使用系统版本(即使在manifest.mf文件中指定了导入包的版本);但是如果我给出的版本低于1.1.1,那么两个包都使用由AEM提供的版本。
如何配置我的捆绑包,以便将不同版本的javax.activation用于捆绑包B中的捆绑包A?
发布于 2014-11-19 22:34:05
如果你想在包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]"发布于 2014-11-15 06:40:21
由于OSGI捆绑包解析规则,这可能非常困难。查看这篇文章--我发现它很好地解释了适用的各种规则。具体地说,查看uses指令:http://www.christianposta.com/blog/?p=241
如果有办法让两者使用相同的版本,生活将会简单得多(但我知道这并不总是可能的)。
这来自上面的文章:
对于每个导入包包声明,必须存在具有相同包的相应导出包
捆绑包还可以将其他属性附加到它导入或导出的包。如果我们在我们的示例中添加一个版本属性会怎么样:
包名称:包A导入包: org.apache.foo;version="1.2.0“
这意味着,捆绑包A依赖于最低版本为1.2.0的包org.apache.foo。是的,你没看错。虽然使用OSGI你可以指定一个版本范围,但是如果你不指定一个范围,而是使用一个固定的版本,它将导致一个固定值的“最小”含义。如果相同的包有更高的版本,将使用更高的版本。因此,除非存在导出所需包的相应包B,否则包A将无法正确解析:
包名称:包B导出包: org.apache.foo;version="1.2.0“
注意,反之亦然,…并非如此如果捆绑包B导出版本1.2.0,则捆绑包A不需要指定版本1.2.0。它可以使用这个导入并很好地解析:
捆绑包名称:捆绑包A导入-包: org.apache.foo
这是因为导入声明了它们需要的版本。导出的版本没有指定导入包必须使用的任何内容(这适用于任何属性,而不仅仅是版本)。Import-Package确切地指定了它需要的版本(或属性),并且必须存在具有相同属性的对应Export-Package
如果你有一个场景,包A导入了一个包,并且它指定了一个由两个包提供的版本,会发生什么:
包名称:包A导入包: org.apache.foo;version="1.2.0“
包名称:包B导出包: org.apache.foo;version="1.2.0“
包名称:包C导出包: org.apache.foo;version="1.2.0“
捆绑包A使用哪个捆绑包?答案是,这取决于首先安装了哪个包(B或C)。首先安装的包用于在找到具有相同版本的多个包时满足依赖关系
在已经解决了一些问题之后,当热部署捆绑包时,事情会变得有点复杂。如果您首先安装Bundle B,然后尝试将Bundle A和以下Bundle D安装在一起:
包名称:包D导出包: org.apache.foo;version="1.3.0“
正如我们从上面看到的,Bundle A (1.2.0)中的版本声明意味着最低版本为1.2.0;因此,如果有更高的版本可用,那么它将选择该版本(在本例中为Bundle D的版本1.3.0 )。然而,这给我们带来了包解析的另一个时间规则:已经解析的包比那些未解析的包具有更高的优先级
原因是OSGI框架倾向于支持给定捆绑包的可重用性。如果它被解决了,并且新的捆绑包需要它,那么如果不需要的话,它就不会尝试拥有同一个包的许多其他版本。Bundle“uses”指令
以上的捆绑包解析规则仍然不够,在运行时仍然可能使用错误的类,从而导致类强制转换异常或类似的异常。你能看到可能少了什么吗?
如果我们有这样的场景。包A导出一个包含类FooClass的包org.apache.foo。FooClass有一个返回类型为BarClass的对象的方法,但是BarClass没有在捆绑包的类空间中定义,它是这样导入的:
1 2 3公共类FooClass {公共BarClass execute(){ ... }}
包名称:包A导入包: org.apache.bar;version="3.6.0“导出包: org.apache.foo;version="1.2.0”
到目前为止,只要有另一个包能够正确地导出具有正确版本的org.apache.bar,一切都很好。
包名称:包B导出包: org.apache.bar;version="3.6.0“
这两个包可以很好地解决问题。现在,如果我们再安装两个包,包C和包D,看起来像这样:
包名称:包C导入包: org.apache.foo;version="1.2.0",org.apache.bar;version="4.0.0“
包名称:包D导出包: org.apache.bar;version="4.0.0“
我们可以看到,捆绑包C从捆绑包A导入了一个包org.apache.foo。捆绑包C可以尝试使用来自org.apache.foo的FooClass,但是当它获得返回值时,会发生什么呢?捆绑包A希望使用3.6.0版的BarClass,但捆绑包C使用的是4.0.0版。因此,在运行时使用的类在包中并不一致(例如,您可能会遇到某种类型的不匹配或类类型转换异常),但在部署时遵循上面的规则,一切都会很好地解决。我们需要的是告诉任何导入org.apache.foo的人,我们使用特定版本的org.apache.bar的类,如果您想使用org.apache.foo,您必须使用与我们导入的版本相同的版本。这正是uses指令所做的事情。让我们更改捆绑包A以准确地指定:
包名称:包A导入包: org.apache.foo;version="1.2.0"";uses:=org.apache.bar“3.6.0”导出包:org.apache.bar;version=
给定捆绑包A的新配置,捆绑包将无法从上面正确解析。捆绑包C无法解析,因为它导入了org.apache.foo,但捆绑包A上的“uses”约束指定C必须与A为org.apache.bar使用相同的版本(3.6.0),否则在尝试部署时捆绑包将不会解析。解决方案是将捆绑包C中的org.apache.bar版本更改为3.6.0。
https://stackoverflow.com/questions/26872006
复制相似问题