管理 OSGi 依赖性地狱

2022-09-02 10:47:24

更新2:由于我的博客有点死,链接降级了,因此您可以在此处查看文章:

https://www.dropbox.com/s/xvobgzqnl43kcda/Managing_OSGi_Transitive_Dependencies__Part_1____CitizenRandom.pdf?dl=0

https://www.dropbox.com/s/0bdooux4yhrf8lf/Managing%20OSGi%20Transitive%20Dependencies%20%28...pdf?dl=0

https://www.dropbox.com/s/km3mxqah6oy23iq/Why%20using%20Require-Bundle%20is%20a%20bad%20pract...pdf?dl=0

https://www.dropbox.com/s/mtenchtjopcrmr8/How%20many%20ways%20can%20we%20import%20bundles%20in%20OSGi_%20_%20CitizenRandom.pdf?dl=0

https://www.dropbox.com/s/sldxynx3fl8vn61/Managing%20OSGi%20Transitive%20Dependencies%20%282...pdf?dl=0

我有一个maven项目,使用在我的POM中配置的非常着名的felix maven捆绑插件.XML方式:

<packaging>bundle</packaging>

(...)

<plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName>
                    <Bundle-Version>${project.version}</Bundle-Version>
                    <Export-Package>jlifx.*</Export-Package>
                    <!-- <Embed-Dependency>*</Embed-Dependency> -->
                </instructions>
            </configuration>
        </plugin>

然后,我的POM中还包含了一些1st度/级别的依赖关系:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.1</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.4</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1</version>
    </dependency>
    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>5.0.0.Alpha1</version>
    </dependency>
</dependencies>

现在我的问题开始了...如果我做mvn安装,我会用它非常棒的MANIFEST很好地构建我的捆绑包。MF和所有,但我不会得到其他依赖捆绑包,这意味着如果我抓取我的捆绑包文件并将其放在我的OSGi框架实例上,我会得到类似“无法解决1.0:缺少需求[1.0]osgi.wiring.package;(&(osgi.wiring.package= etc...”

因此,我发现创建我的1st级依赖项捆绑包的一种方法是在我的POM中创建一个配置文件,如下所示:

<profiles>
    <!-- http://www.lucamasini.net/Home/osgi-with-felix/creating-osgi-bundles-of-your-maven-dependencies -->
    <!-- -Pcreate-osgi-bundles-from-dependencies bundle:wrap -->
    <profile>
        <id>create-osgi-bundles-from-dependencies</id>
        <build>
            <directory>${basedir}/bundles</directory>
            <plugins>
                <plugin>
                    <groupId>org.apache.felix</groupId>
                    <artifactId>maven-bundle-plugin</artifactId>
                    <version>2.0.1</version>
                    <extensions>true</extensions>
                    <executions>
                        <execution>
                            <id>wrap-my-dependency</id>
                            <goals>
                                <goal>wrap</goal>
                            </goals>
                            <configuration>
                                <wrapImportPackage>;</wrapImportPackage>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

这样,当我执行 mvn -Pcreate-osgi-bundles-from-dependencies bundle:wrap 时,我会得到构建良好的捆绑包和工作。但是,真正的交易来了。这些捆绑包本身也有依赖关系,因此它们需要将其依赖关系打包为捆绑包。根据许多网页,很久以前我们有mvn org.apache.felix:maven-bundle-plugin:bundleall目标为我们做到这一点,但我已经尝试过,它是错误的,返回异常,它被标记为已弃用,根据Stuart,它将在maven 2.4.1及更高版本中被删除(参考:https://issues.apache.org/jira/browse/FELIX-4145)。

所以我现在唯一的解决方案是,手动检查我的1st级依赖项的每个清单,并去谷歌搜索包含所需软件包的jar,将它们添加到我的POM.XML作为maven依赖项,然后运行mvn -Pcreate-osgi-bundles-from-dependencis bundle:wrap将它们包装为捆绑包。

这就是所谓的依赖地狱...

有没有办法自动执行解决 maven-bundle osgi 项目的第 n 级依赖关系的任务?即,让maven研究我的每个1st级依赖项的清单文件,阅读导入包,在中央存储库中查找提供此类包的jar,下载它们并将它们包装为捆绑包?

注意:请提供有关如何实现此目的的详细说明,不要仅链接到此工具或可能解决此问题的工具。这些工具的主要问题是它们缺乏示例和文档。例如,bundleall已被弃用,但似乎没有工具可以替换它,至少在他们的maven捆绑插件的官方文档中是这样,到目前为止,它已经被弃用了......我确信我可能已经与能够做到这一点的工具交叉,但是缺乏文档禁止新手用户知道这一点......

谢谢!





编辑-1:

感谢您到目前为止的回答:)我认为我没有以最恰当的方式解释我的情况,而且仅仅通过纯文本来做到这一点,我感到有些困难。或者也许我不明白你的答案。我在OSGi中是相当“新鲜”的,我唯一的知识来自书籍(OSGi in Action等)和Google。

想象一下,我的捆绑包导入包 A 和 B。但是,包 A 导入包 C,包 B 也导入 C。但现在 C 导入了包 D、E、F 和 G。另一方面,包 D 导入大量其他包,E、F 和 G 也是如此。

我的计算机中唯一的捆绑包是我自己的捆绑包以及提供软件包 A 和 B 的捆绑软件,因为它们是我的 1 级依赖项。但是,我没有任何其他必需的捆绑包,即使它们作为jar安装在我的JDK安装文件夹中安装,我也没有它们作为捆绑包,甚至我不知道在哪里可以让jar来包装它们(实际上我知道,但让我们想象我没有)。

我希望构建工具能够运行类似于以下内容的算法:

1)转到我的捆绑清单。MF 并读取“导入-包”字段。枚举所有必需的包及其相关版本。

2)在互联网上的某个地方搜索我所需库的jars或捆绑包。

3)下载每个并检查它们是否只是普通的jars或具有有效的osgi清单文件(即它们是捆绑包)

3.1) 如果它们是捆绑包,请将它们复制到我的捆绑包/文件夹中。

3.2)否则使用任何工具将jar包装成捆绑包,并将捆绑包复制到我的捆绑包/文件夹中。

4) 现在,对于每个下载/创建的新捆绑包,重复步骤 1)、2)、3) 和 4)。

我想要的最终结果:我直接或间接依赖的每个库的捆绑包,以便我可以在我的 OSGi Framework 实例(如 felix 或 equinox)中动态安装它们。

我不想要的:

1)必须手动执行此操作,因为如果我试图解决依赖关系的每个依赖关系,我可能会花费数小时或数天来收集和包装jar。

2) 将所有依赖项嵌入到 ubber/mega 捆绑包中。根据我读过的几本书,这是一个不好的做法,单独维护每个依赖项更加困难,而且,它破坏了模块化。

注意:我的问题不在于将jar包装到捆绑包中的特定任务,而在于以递归方式将其递归到每个捆绑包的导入中,即使它们需要从在线存储库(如maven的central)下载。

有没有办法自动执行此操作,或者我错过了OSGi的一些非常重要的东西?这么大,我永远不需要做我要求的这个?

编辑-2:

一些(如果不是全部)导入包依赖项可以在运行时解决。想象一下,OSGi Framework试图启动一个捆绑包,但不是显示错误消息“无法解决8.0:缺少要求[8.0] osgi.wiring.package;它会在线搜索该软件包,下载它并动态安装它。生活会变得容易得多。


答案 1

如果你想包装不是捆绑包的jar,但只需要这些jar作为OSGi框架中的库作为捆绑包,你可以用BND工具包装它。请参阅链接如何从现有的第三方jar创建/生成OSGi捆绑包?

但是我可以看到你使用非常常见的libaries,而不是已经转换为osgi捆绑包。您可以在SpringSource Enterprise Bundle Repository中找到许多转换为捆绑包的库。

但是,如果您找不到任何未转换为良好OSGi捆绑包的库,则可以使用PAX-URL中的WRAP协议在OSGi框架中安装这些依赖项。使用这些协议取决于您使用的OSGi框架,但在apache中,默认情况下会安装karaf。例如,要从 maven 存储库安装库:

root@karaf> osgi:install -s 'wrap:mvn:commons-lang/commons-lang/2.4$Bundle-SymbolicName=commons-lang&Bundle-Version=2.4'

本说明将 commons-lang 库从 maven 存储库安装到 OSGi 框架中,并将其包装为 OSGi 捆绑包,标头显示在行中。

对于自动安装依赖项,如您在第二次编辑中所说的那样,有几种解决方案,但需要做一些工作。有两种主要的解决方案可以自动配置到OSGi framewor的捆绑包,“Felix OBR存储库”和“Felix Provisioning”捆绑包以及Equinox p2存储库。它们都具有用于自动安装捆绑软件和功能的控制台命令。问题是,实际上我找不到一个好的公共捆绑包存储库。您需要使用所需的所有捆绑包构建自己的存储库。

如果您使用 maven-bundle-plugin,当您将工件安装到本地 maven 存储库中时,该插件会更新位于存储库根目录中的文件“repository.xml”,以反映捆绑包的需求和功能。此文件是 OBR 存储库文件。


答案 2

使用 maven-bundle-plugin 中的 Conditional-Package 以递归方式内联 JAR 捆绑包中所有必需的包,并激活标记 true。


推荐