领先一步
VMware提供培训和认证,以加速您的进步。
了解更多最近几周,我们看到人们对由 OSGi 捆绑包组成的应用程序的未来构建解决方案越来越感兴趣。由于我们深度参与 OSGi,这对于我们来说至关重要,我们花了很长时间研究客户需求和这些需求的解决方案。在这篇博客文章中,我将概述我们已识别的需求,并提出我们认为可以解决这些需求的方案。
我非常想听取任何有额外需求、认为我们的需求是错误的或有更好解决方案想法的人的意见。
当前 OSGi 构建的一个实际问题是依赖项元数据可能在许多地方重复。对于 dm Server,我们在 ivy.xml、.classpath 和 MANIFEST.MF 文件中描述了依赖项。任何 OSGi 构建的长期解决方案都必须只要求一个依赖项元数据位置。
鉴于 OSGi 应用程序的独特特性,人们很容易尝试从头开始构建系统。我们考虑过这个想法一段时间,但很明显,这在技术上不可行,也不是我们用户的最佳解决方案。
我们的用户大量投入到他们选择的构建解决方案中,让他们迁移似乎不是一种务实的方法。相反,用户希望一个能够很好地融入他们的 Maven 或 Ant 构建的解决方案。
迁移到 OSGi 的最简单方法可能是从应用程序模块的关联元数据自动生成清单文件。理想情况下,这种方法将导致对应用程序代码或开发人员使用该代码方式的更改最小。
虽然清单生成是一种有效的方法,但许多用户都希望将他们的 OSGi 清单视为依赖项元数据的规范描述。这些用户希望从他们在清单中编写的元数据驱动他们的构建。为了支持轻松创建清单,许多用户希望看到对清单模板的支持。清单模板允许自动生成样板清单内容,同时让用户完全控制诸如版本之类的重要信息。
这种方法使用清单作为 IDE 和脱机构建中的中心依赖项描述符。开发人员手动编写 OSGi 清单,或借助工具编写,清单以类似于 Maven 使用 pom.xml 和 Ivy 使用 ivy.xml 的方式由构建工具使用。
使用 OSGi 元数据进行解析允许在构建期间应用全套 OSGi 解析规则。这将使构建时依赖项解析与运行时将发生的解析更准确地匹配。
这种方法的一个潜在缺点是开发人员需要在他们的清单中指定测试依赖项。Maven 和 Ivy 都有标记仅供测试环境使用的依赖项的方法,并且在使用清单进行依赖项解析时需要类似的解决方案。
根据这些需求,我们得出了四个主要场景。有趣的是,这些场景中的每一个都由我经常与 dm Server 交互的用户中的一位或多位代表。
与下一个场景一起,这是我们遇到的最常见场景,也是我们目前投入最多时间研究的场景。通过这种方法,开发人员将像处理任何普通的 Maven/Eclipse 项目一样执行他们的开发任务。
OSGi 清单文件由 Maven 和 Eclipse 的插件生成。开发人员可以选择让 Eclipse 插件作为增量构建的一部分或按需重新生成清单。
生成 OSGi 清单所需的大部分元数据都可以在 Java 代码(源代码/字节码)中找到。但是,无法从字节码推导出依赖项的合理版本号。在这种情况下,可以从 pom.xml 文件或可自定义的清单模板中提取版本。
清单模板可以携带比版本号更多的信息,允许开发人员添加 OSGi 属性和指令以及任何自定义标头。
这种方法类似于 Maven、pom 驱动的方法,只是依赖项元数据将从 ivy.xml 文件而不是 pom.xml 文件中提取。
开发人员将可以使用 Ant 任务在构建的适当阶段执行清单生成。
这种方法最大的缺点是 Eclipse 中缺乏令人信服的 Ivy 集成。对于 Ivy 2,Eclipse 插件支持非常缺乏。我们正在考虑的一种方法是从生成的清单创建 Eclipse 类路径。这是我们已经支持并将在接下来的两个场景中扩展的工具。开发人员将编写 ivy.xml 文件,使用 Eclipse 插件生成他们的清单,并自动更新 Eclipse 类路径。
在这种方法中,OSGi 清单文件是项目依赖项元数据的最终声明。开发人员可以选择手动编写整个清单,但最有可能的是他们将编写清单模板并让我们的插件完成其余工作。
dm Server 工具已经配备了一个由清单驱动的 Eclipse 类路径容器,这将扩展以支持准确的传递依赖项解析。
为了支持此环境中的测试,插件将允许编写 MANIFEST.MF 和 TEST.MF 文件,其中 TEST.MF 描述仅适用于测试的依赖项,而 MANIFEST.MF 描述在测试和生产期间适用的依赖项。
此场景中剩下的最后一部分是如何插入 Maven。我们目前正在研究两种方法:替换/集成 Maven 依赖项解析器或生成 pom.xml 文件。我很想听听您对哪种方法最有效以及最有利于您的看法。
这种方法与以清单驱动的方式使用 Maven 非常相似。与场景 2 不同,此场景不会因为缺乏良好的 Ivy/Eclipse 集成而受到影响,因为我们将使用与场景 3 中相同的清单驱动 Eclipse 类路径容器。
为了满足概述的需求,我们正在构建一套与 Maven、Ant 和 Ivy 协同工作的工具,以提供用于构建 OSGi 应用程序的集成解决方案。
Bundlor 是一个我们内部已经使用了一段时间的工具,用于生成 OSGi 清单。我们主要使用它来创建我们在企业捆绑包存储库中看到的所有捆绑包。Bundlor 可用于为在没有太多考虑 OSGi 的情况下创建的旧版库生成清单。Bundlor 也可用于为专门考虑 OSGi 而创建的捆绑包生成清单。Bundlor 消除了创建高质量捆绑包清单时涉及的大部分繁琐工作。
Bundlor 支持清单模板的概念,允许您自定义生成的清单。使用模板,您可以向包导入和导出添加版本和属性,从导出中排除包,在无法自动检测时添加导入,还可以添加额外的清单标头。下面的代码片段显示了我们其中一个示例应用程序的清单。
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: GreenPages Service
Bundle-SymbolicName: greenpages
Bundle-Vendor: SpringSource Inc.
Bundle-Version: 1.0
Import-Template: org.springframework.*;version="[2.5.6.A,3.0)"
Excluded-Exports: greenpages.internal
在此示例中,Excluded-Exports 标头用于防止greenpages.internal 被公开。Import-Template 标头用于为与org.springframework.* 模式匹配的所有包名称设置版本。扫描项目代码以确定可能的导入和导出集。然后使用模板文件来控制此集合中的哪些导入/导出实际进入清单以及它们的版本。重要的是,生成过程将正确为您生成uses 元数据,从而消除最繁琐的任务之一。
Bundlor 实际上将支持创建两个清单文件:MANIFEST.MF 和 TEST.MF。TEST.MF 文件将用于描述仅在测试期间所需的依赖项。这对于希望使用清单驱动构建但不希望使用测试依赖项污染生产清单的开发人员非常重要。
在接下来的几周内,我们将发布 Bundlor 的第一个公开里程碑版本。在此版本中,您将能够从 Ant 和 Maven 中为项目生成清单,并且您可以使用清单模板自定义这些清单。在接下来的几个里程碑版本中,我们将添加从 pom.xml 和 ivy.xml 文件自动检测依赖项版本的支持。
我们将及时将我们的大部分示例从手写清单切换到使用 Bundlor 和清单模板,以用于 Bundlor 1.0 正式版。此外,我们还将 dm Server 迁移到 Bundlor,丢弃我们所有手写清单。
BundlorEclipse 是一个 Eclipse 插件,它使 Bundlor 功能直接在您的 Eclipse IDE 中可用。使用此插件,您可以将完全增量的清单生成作为您正常的 Eclipse 构建生命周期的一部分执行。如果您像我一样,对保存按钮有点过于随意,您可以将 BundlorEclipse 配置为仅按需生成清单。
当与即将推出的 dm Server 容器内测试框架结合使用时,您将能够启动完整的 dm Server 测试环境,其中包含所有捆绑包的清单文件,所有这些都可以在 Eclipse 中完成。
OSGi 有自己关于如何解析模块之间的依赖关系、如何验证这些依赖关系以及如何将其转换为一致的类空间的规则。在 OSGi 之外,构建工具使用列出 JAR 文件和目录以搜索类的平面类路径。
为了支持清单驱动型构建,我们将创建一个离线依赖解析器,它可以在不启动Equinox或dm Server的情况下执行OSGi解析。我们将把它与一个工具配对,该工具将OSGi解析图展平成一个简单的类路径,用于编译和测试。此展平过程将完全由用户配置,用户可以提供策略信息来控制如何将OSGi图中的多个版本映射到类路径中的单个版本。
使用依赖解析器,我们将能够改进我们的清单类路径容器,为每个Eclipse项目创建一个完整的、传递的类路径。
依赖解析器也将构成我们的依赖解析器/pom.xml/ivy.xml生成器工具的核心部分。这里关键的观察结果是,作为开发人员,您应该期望在Eclipse和构建工具中获得一致的结果。
您可能知道,OSGi技术总监Peter Kriens提供了一个名为bnd的工具,其用途与Bundlor类似。我们最初的立场是在我们自己的项目中使用bnd,并将其作为我们工具的一部分。事实上,Spring Dynamic Modules在Bundlor出现之前很久就一直在使用bnd来创建它的bundles。那么,为什么我们决定创建Bundlor呢?
创建Bundlor的主要原因是我们必须支持bnd中不存在的一些附加功能,例如:
这些功能用于支持BundlorEclipse。我们在Eclipse中使用基于JDT的扫描来代替字节码扫描,以改善用户体验并更好地集成到Eclipse构建生命周期中。Eclipse能够很好地处理部分正确的代码,我们希望Bundlor能够以同样的方式支持部分代码。
在BundlorEclipse中,可以配置Bundlor在每次保存IDE中的更改时运行。为了提高性能,我们支持增量清单生成。当您更改代码时,Bundlor可以跟踪必须对清单文件进行哪些更改,并避免必须重新创建所有清单。
我们知道,尽管Eclipse是Java开发人员的主流IDE,但仍然有相当数量的开发人员正在运行IntelliJ和NetBeans等IDE。
虽然我们不会自己承诺构建任何这些IDE的插件,但我们将把所有描述的工具作为开源提供,使其他人能够为他们最喜欢的IDE创建插件。
我们构建工具的方法是尝试将尽可能多的功能封装在通用库中。我们致力于与NetBeans和IntelliJ团队合作,帮助他们将我们的工具库集成到他们的IDE中。
理想的最终结果是,无论您使用什么IDE,您仍然可以访问相同的底层OSGi工具。
OSGi构建的需求并不止我概述的四种场景。还有许多其他功能和增强功能可以改善使用OSGi应用程序的开发人员的体验。
许多公司将拥有大量的JAR工件积压,这些工件不是OSGi bundles。我们计划扩展Bundlor以支持批量bundle生成。在这种模式下,您可以通过将Bundlor指向JAR目录并让Bundlor为所有JAR创建bundle来节省时间。此外,Bundlor将能够使用这些工件之间的关系来确定依赖项的版本范围应该是什么。这将减少您必须编写的模板代码量,同时仍然产生高质量的bundle。
使用清单驱动型构建构建dm Server应用程序时,您必须手动编写初始清单导入。通过支持基于仓库的代码补全,您将能够针对dm Server仓库获得Eclipse代码补全,这将生成Java导入和清单导入。使用此功能,您可以根据需要构建清单依赖项,而无需切换到清单文件。