【问题标题】:How to handle Import-Package entries which come from jars on the Bundle-Classpath?如何处理来自 Bundle-Classpath 上的 jar 的 Import-Package 条目?
【发布时间】:2013-06-05 09:29:54
【问题描述】:

我在我的 Bundle-Classpath 中放了几个罐子。下面的行显示了我的 pom.xml 中的条目,它使用 Felix 插件为包创建 manigest.mf。

<Bundle-ClassPath>.,lib/com.springsource.org.h2-1.0.71.jar,lib/com.springsource.org.apache.lucene-2.3.2.jar,lib/com.springsource.org.apache.lucene.search-2.3.2.jar</Bundle-ClassPath>

这些 jar 具有导入包的类,但据我所知,它们都有一个 MANIFEST.MF,它有自己的(准确的)Import-Package 语句列表。

但是,当我构建我的项目(使用 Maven 和捆绑插件)时,它会报告错误,因为它无法解析对某些类的引用。具体错误是:

Unresolved references to [com.sun.tools.javac, javax.naming, javax.naming.spi, javax.servlet, javax.servlet.http, javax.sql, javax.transaction.xa]

所有这些错误都来自 com.springsource.org.h2-1.0.71.jar 并且所有这些包都导入到该 jar 的清单中。

我无法理解:

  • 如果这些包已经在 com.springsource.org.h2-1.0.71.jar 的 MANIFEST>MF 中导入,为什么 Maven 捆绑插件会报错
  • 为什么问题只来自 com.springsource.org.h2-1.0.71.jar ?我尝试删除该特定 jar 并且构建顺利进行,即使 com.springsource.org.apache.lucene.search-2.3.2.jar 在它的 MANIFEST.MF 中也有几个 Import-Package 条目?

关于第二点,我做了一些调查,感觉是有规律的。 com.springsource.org.apache.lucene.search-2.3.2.jar 在其清单中指定的所有导入都由 com.springsource.org.apache.lucene-2.3.2.jar 满足,这也是指定的在 Bundle-Classpath 上。

com.springsource.org.apache.lucene-2.3.2.jar(在 Bundle-Classpath 上)满足的 com.springsource.org.h2-1.0.71.jar 的依赖项是错误消息中未列出,但是,Bundle-Classpath 上的 jar 不满足的依赖项将在错误消息中列出。

不太清楚发生了什么。关于 Bundle-Classpath 上指定的 jar 文件的规则是什么?他们的导入(即使它们在 Import-Package 中指定)是否必须在主项目的 pom 中列出?或者这是 Maven 捆绑插件强制执行的东西?如果是后者,有没有办法摆脱强制执行?

【问题讨论】:

    标签: osgi osgi-bundle maven-bundle-plugin


    【解决方案1】:

    当您通过 Embed-Dependency 标签嵌入任何 jar 时,maven-bundle-plugin 也会分析该 jar 并将引用的包添加到主机包 Import-Package 列表中。大多数情况下,此类软件包是可选的,具体取决于所使用的功能。例如,在您的用例中,H2 jar 依赖于 Lucene,某些功能的 Servlet API。如果您的使用场景不需要这些功能,那么您可以将这些包标记为可选

    <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <version>2.3.5</version>
            <extensions>true</extensions>
            <configuration>
              <obrRepository>NONE</obrRepository>
              <instructions>
                <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                ..
                <Embed-Dependency>
                  h2
                </Embed-Dependency>
                <Import-Package>
                  org.osgi.service.jdbc.*;
                  org.apache.lucene.*;
                  javax.transaction.*;resolution:=optional,
                  *
                </Import-Package>
              </instructions>
            </configuration>
          </plugin>
    

    在上面的配置中,我们将这些包标记为可选。主要问题是根据你的使用情况确定包列表

    一种快速而肮脏的方法是将所有标记为可选导入。 应作为最后的手段使用。因为一些有效的导入将被标记为可选,OSGi fwk 将无法检查它们。

            <Import-Package>
              *;resolution:=optional
            </Import-Package>
    

    另请注意,H2 jar 是有效的 OSGi 包,因此您可以直接部署它。

    【讨论】:

    • 将包标记为可选是危险的,除非使用这些包的代码真的被设计为将这些包视为可选。换句话说,如果代码最终尝试使用此类包中的代码,您将收到异常。如果你真的不使用代码,你还不如完全禁止导入,这样可以省去解析器甚至试图找到那个包的麻烦。
    • @MarcelOffermans 我完全同意盲目地将包裹标记为可选是危险的。很多时候,当包装第三方 jar 时,用户不知道哪些包是真正可选的。我通常采用的另一种方法是将此类包添加到动态导入列表中。但是 maven-bundle-plugin 没有为 DynamicImport-Package 指令扩展通配符,所以想出列表并不简单
    • 插件没有为DynamicImport-Package扩展通配符,因为header本身支持通配符,所以扩展它们是错误的。
    【解决方案2】:

    有关在 Bundle-Classpath 上指定的 jar 文件的规则?

    maven-bundle-plugin(mbp) 扫描 bundle-classpath 中列出的文件以识别所需的导入 每个指定的罐子。因此,mbp 将在 main(您的主包)manifest.mf 中添加所需的导入。 这确实意味着包应该由外部包导出。如果在外部找不到所需的包 捆绑然后捆绑将不会启动。

    您有 2 个解决方案来使用您的应用程序所需的第三方 jar。

    1. 准备每个第三方 jar 的 OSGi 包。你可能会发现 osgi 包已经为 spring 存储库here 中的 spring jars 和其他开源项目。只需完美搜索即可。你会找到的。

    2. 使用捆绑类路径: 有了这个,您必须将您的第三方依赖项(以及“所有”它们的传递依赖项)放入您的包中,并在 Bundle-ClassPath 标头中指定每个 jar。在这种情况下,mbp 将分析捆绑类路径 jar 并尝试弄乱您的 import-package 标头。您只需在 pom.xml 中包含自定义标头即可避免这种情况。如果您选择自定义 import-package ,请注意在您的 import-package 中正确包含来自其他(外部)捆绑包的所需包。

    拇指规则:如果你的应用在你的 bundle-classpath 中找到了一些东西,那么它就不会去 import-package。

    【讨论】:

      猜你喜欢
      • 2015-01-18
      • 2017-01-19
      • 1970-01-01
      • 1970-01-01
      • 2012-09-08
      • 2019-11-04
      • 2015-05-19
      • 2013-12-01
      相关资源
      最近更新 更多