【问题标题】:How to embed external jars dependency in OSGI bundles?如何在 OSGI 包中嵌入外部 jar 依赖项?
【发布时间】:2019-11-03 23:36:43
【问题描述】:

我正在尝试将我的项目转换为 OSGI 应用程序。我几乎没有疑问。假设我的应用程序中的 ModuleA 依赖于外部 jars jarA 和 jarB。现在为了让 ModeuleA 运行,我使用 maven-bundle-plugin 的 embed-dependency 属性嵌入了两个 jar。 现在假设我有另一个模块 ModuleB,它也依赖于 jarA。所以这个模块也嵌入了jarA。我的项目最终将 jarA 嵌入了 2 次,这将不必要地增加项目的大小。

有没有办法告诉 OSGI 只加载一次 jarA 并将其提供给两个模块。

如果将这些 jar 转换为 OSGI 包是唯一的解决方案,我还有几个问题:

  1. 将 jar 转换为捆绑包的最简单方法是什么。 BND 工具看起来是个不错的解决方案,但我找不到关于它的适当文档。

  2. jarA 也会有一些依赖的 jars。所以我还需要将所有依赖的 jar 转换为包。我的项目有 100 多个罐子。我怎样才能自动化这个过程。

提前致谢:)

【问题讨论】:

  • 如果 >100 个 jars 是外部创建的依赖项(不是您自己的),其中很多可能已经是 OSGi 包。打开或解压它们(我发现 emacs 很方便),并在 META-INF/MANIFEST.MF 文件中查看 OSGi 标头。如果有 OSGi 头文件,则无需重新打包。
  • 是的,他们中的大多数人都有。那么我们是否需要启动每个包(外部 jar),然后启动主包(这些 jar 的依赖项)?如果我们有嵌入的 jars,我们不需要启动这些包中的每一个
  • 是的,它们应该以正确的顺序启动。首先是没有 deps 的包,最后是你的包。

标签: maven osgi apache-felix


【解决方案1】:

实际上有解决方案,两者都与您现在正在做的有点不同:

  1. 构建一个“第三方依赖项”包,它将嵌入您的项目具有的所有非 OSGi 依赖项。
  2. 将每个非 OSGi 依赖项转换为 OSGi 包。

选项 1 更容易处理,所以我认为大多数项目都这样做。我个人更喜欢选项 2。我们有一个 Maven“pom.xml”模板,用于转换这些依赖项。

“pom.xml”如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <properties>
        <library.groupId></library.groupId>
        <library.artifactId></library.artifactId>
        <library.version></library.version>
    </properties>

    <artifactId></artifactId>
    <packaging>bundle</packaging>

    <name></name>
    <description>${library.groupId}:${library.artifactId}:${library.version}</description>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Import-Package>*;resolution:=optional</Import-Package>
                        <Export-Package>*</Export-Package>
                        <Embed-Dependency>*;scope=compile|runtime;inline=true</Embed-Dependency>
                        <Embed-Transitive>true</Embed-Transitive>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>${library.groupId}</groupId>
            <artifactId>${library.artifactId}</artifactId>
            <version>${library.version}</version>
        </dependency>
    </dependencies>

</project>

这样做:

  1. 将非 OSGi 库添加为依赖项
  2. 告诉maven-bundle-plugin 嵌入此依赖项(传递)
  3. 告诉maven-bundle-plugin 导出所有依赖包

我留下了一些你必须设置的空白,例如library.groupIdlibrary.artifactIdlibrary.version。还有一些我们需要调整maven-bundle-plugin 的配置。但这是我们的出发点。例如,您不想导出所有包等。

如果您确实有 100 多个依赖项需要转换,您最好使用此模板,只需将所有 100 个依赖项添加为依赖项,然后构建一个包含所有依赖项的大包。

您可以在此处找到maven-bundle-plugin 的文档:

https://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html

在这一点上,我还想提一下,您可能需要考虑一个新的捆绑插件:bnd-maven-plugin

见:https://github.com/bndtools/bnd/tree/master/maven/bnd-maven-plugin

【讨论】:

  • 我已经只使用了 maven-bundle-plugin。我在要求它的替代品。将依赖项嵌入单个包中并不是我们正在寻找的理想解决方案。我们的目标是将这个大型应用程序分解为多个模块。 Out 客户端将根据他们需要的模块下载更小的应用程序。
  • 无论如何我都在使用 BND 工具将每个依赖项 jar 转换为 OSGI 包。在启动需要这些依赖项的模块之前,我首先启动它们。在内部,我们正在维护模块与依赖罐映射。喜欢:ModuleA --> jarA, jarB ; ModuleB --> jarB, jarC 所以如果我们需要启动ModuleA,我们将首先启动jarA和jarB(都转换为OSGI bundle),然后再启动ModuleA。
  • @UdayOgra 您可以创建一个包含单个依赖项的包。这就是我们正在做的事情。我们有几个像我描述的那样带有 POM 的项目,然后部署所有这些包。
猜你喜欢
  • 2021-07-05
  • 2018-10-05
  • 2014-09-12
  • 2014-11-20
  • 1970-01-01
  • 2018-12-19
  • 1970-01-01
  • 2021-09-07
  • 2019-12-29
相关资源
最近更新 更多