为 WebSphere Application Server 开发企业 OSGi 应用程序
转载地址:
http://www.ibm.com/developerworks/cn/websphere/techjournal/1007_robinson/1007_robinson.html
?
简介:?使用标准 Java? EE 部署创建模块式、可扩展的 Web 应用程序有一定难度,但通常可以通过良好的设计实践和方法来完成。但是,当您想分离公共模块以便在多个企业应用程序之间共享,或者同时使用多个公共库版本时,您就会遇到真正的麻烦。OSGi 是多年以来一直在 IBM? WebSphere? Application Server 和 Eclipse 平台中使用的一种 Java 模块技术。WebSphere Application Server V7 Feature Pack for OSGi Applications and JPA 2.0 允许模块式企业应用程序直接使用 OSGi 技术来极大地简化它们的开发、组装和部署。这个特性包还提供了一个基础设施,其中,模块式设计不仅是一个最佳实践,而且是惟一的实践方法。 本文来自于 IBM WebSphere Developer Technical Journal 中文版。
这里需要注意的一些头部是:
Export-Package 列出将从这个 bundle 导出的一个或多个包(处于特定版本)。只有导出包在 bundle 外部可见;这里没有列出的包都只在 bundle 内部可见。Import-Package 列出 bundle 需要的一个或多个包(处于特定版本或版本范围)。我们现在先不涉及版本控制的细节(将在稍后讨论),先来看看这两个头部的作用。还记得吗,前面介绍过,我们需要建立一些开发最佳实践来定义模块的外部接口并确保没有任何内部包被任何客户模块使用。借助 OSGi,现在可以通过在运行时实施来支持这个最佳实践,并可以向模块所有者提供一个机制来适当封装它的内部包。另外,您的包清单文件中包含一些元数据,明确指定 bundle 需要的、需要由其他 bundle 提供的所有包。在一个包含许多 bundle 的复杂应用程序中,这将向您提供一个更确定的方法,以确定一个 bundle 更改的影响,并理解对系统其余部分的可能影响,从而减小软件开发周期中的风险和成本。
元数据处理和可见性规则的运行时实施由 OSGi 框架解算器负责。当每个 bundle 启动时,这个解算器针对此框架中已经安装的其他 bundle 声明的导出协调该 bundle 的每个导入,并为每个 bundle 计算一个单独的类路径。如果某个 bundle 有一个无法解算的依赖项,该 bundle 将不会启动。前面提到过的滴答作响的定时炸 弹(针对一个 JAR 被移动到一个不能满足其所有依赖项要求的新环境的情况)被通过移除保险丝而拆除。相比处理一个无法启动的应用程序而言,处理一个正常工作一段时间、然后突然失败并抛出一个 ClassNotFoundException 的应用程序要困难得多。
此前我们所讨论的内容都不是特定于一个企业运行时的 — 那么这些内容如何与企业 Java 应用程序或企业应用程序服务器相关呢?
假设我们有一个企业应用程序服务器能够处理 OSGi bundle 元数据,那么 OSGi 的第一个明显的优势就是包含大量模块的复杂企业应用程序的适当模块化。但 OSGi 的优势远不止这些,它还能解决企业环境中普遍的几个其他问题。我们已经简单接触了这些问题中的一个:在部署了数十或数百个 EAR 的许多大型企业部署中,往往存在这样一种情况:每个 EAR 都是自足的,其程度达到应用程序使用的许多公共库被打包到需要它们的每个 EAR 中。这些库副本将塞满部署这些 EAR 的文件系统和知识库,并在应用程序启动时填满内存。尽管企业应用程序通常可以被部署到各种供应商的企业环境,且管理依赖项已针对独立于这些 EAR 安装的共享库配置,但这些机制因供应商不同而不同,限制了可移植性。另外,共享库配置通常与部署过程本身分离,需要独立的、部署后管理配置,这增加了端到端部署过程的复杂性。
OSGi 元数据和 bundle 知识库向您提供了一个机会,允许您只在应用程序存档中包含特定于应用程序的模块,从而极大地简化共享公共库的企业应用程序套件的部署。在理解 OSGi 元数据之后,企业部署过程变得更加强大,能够针对部署环境中配置的 bundle 知识库的内容解算 bundle 依赖项。所有公共库都可以在一个中央 bundle 知识库中管理,该知识库然后成为企业(单元)配置的一部分。
OSGi 还向您提供了一个机会,允许您在企业环境中更好地执行版本控制工作。当今企业应用程序通常包含对公共库有相似依赖性的第三方框架和库。如果不同框架需要不同版本的公共库,那么这将是个令人头痛的问题。当您遇到下面的情况时,这个问题将变得尤其严重:以前,您的应用程序一切正常,但现在您需要更新一个供应商框架,结果却发现办不到,原因是该框架在应用程序中的另一个框架使用的一个库的不兼容的新版本上有一个依赖项。
OSGi 版本控制元数据和类加载能够消除这个问题。在上面的清单 1 中,Import-Package 头部表明包 com.something.i.need 上的一个依赖项,版本范围 为 “[1.0,2.0)”。这表明这个依赖项的需求范围为 1.0 ≤ version < 2.0 的任何包版本。因此,version 1.0 或 1.5.0 或 1.9 都能满足这个依赖项的需求,但 version 2.0 不能。OSGi 的版本控制机制支持包提供者在版本的主要部分中使用一个标明,一个不兼容更新的更改来表明一个包的新版本是否向前兼容前面的版本。包使用者可以指出他们能够使用的版本或版本范围。(请参阅 这份 PDF 白皮书 了解关于 OSGi 版本控制的更多信息。)重要的是,如果一个应用程序中的两个 bundle 依赖同一个包的不同版本,那么这些依赖项的需求可以同时得到满足,因为 OSGi 解算器可以为这两个 bundle 计算不同的类路径。
OSGi 平台规范,以及参考实现和依从性测试,由 OSGi Alliance 生成,10 多年来一直被广泛使用。2010 年 3 月,OSGi V4.2 Enterprise Specification 出版物包含了企业环境。该出版物定义了企业 Java 技术的一些 OSGi 语义,比如事务、持久性和 Web 组件。这个重要的规范定义了一些标准机制来将结合 Java EE 和 OSGi 世界,包含了 bundle 元数据来声明该 bundle 包含一个 web.xmm 文件的 Web bundle、包含一个 persistence.xml 文件的持久性 bundle、还是包含一个 blueprint.xml 文件的 Blueprint bundle。Web 和持久性 bundle 只是包含额外 OSGi 清单文件头部的常见 Java EE bundle;而 Blueprint bundle 更像 Spring 模块,但包含一个标准化的 bean 定义 XML。
作为一种技术,OSGi 在独立应用程序和客户端应用程序技术中已经流行了多年,并在许多企业应用程序服务器(比如 WebSphere Application Server)的实现中内部使用。由于缺乏企业应用程序的 OSGi 标准,以及缺乏广泛可用的专用工具和企业运行时支持,在这些应用程序服务器平台上运行的企业应用程序对 OSGi 的直接利用最近受到抑制。随着 OSGi Enterprise Specification 的发布,以及可以选择在越来越多的企业应用程序服务器上将应用程序部署为 OSGi bundle,这种情况得到了改观。
本文余下部分将讨论开发和部署 WebSphere Application Server V7 Feature Pack for OSGi Applications and JPA 2.0 中引入的企业 OSGi 应用程序的运行时和工具化支持:
在 OSGi 应用程序部署过程中,WebSphere Application Server 管理控制台为应用程序计算所有包和 OSGi 服务级别依赖项,以便该应用程序能够由 EBA 和已配置的 bundle 知识库一起完整提供。应用程序清单文件本身可以由开发人员创建,也可以由 Rational Application Developer 这样的工具生成。重要的是要理解,应用程序清单文件只需在 Application-Content 中列示主要的应用程序 bundle,而不必列示这些主 bundle 依赖的所有包提供的和服务提供的 bundle。WebSphere Application Server 部署流程解算主 bundle 的所有依赖项,以计算一个短暂关闭的应用程序内容列表,并在解算过程检测到依赖项缺失时阻止应用程序部署。还需要理解的一个重点是,配置按例外管理(by-exception),因此,如果 Application-Content 全部包含在 EBA 中,则应用程序清单文件完全不必要。构成 Application-Content 一部分的每个模块,以及其全部已计算依赖项,部署为一个 OSGi bundle。如果一个不带 OSGi 元数据的 Web 模块包含在 Application-Content 中,那么 WebSphere Application Server 部署流程将在部署过程中自动将这个模块转换为一个 Web 应用程序 bundle(WAB 模块)。按例外配置(configuration-by-exception)以及 WAR 文件的自动检测和转换提供一种最快捷的方法来开始使用 OSGi 应用程序 — 可以将一个只包含 Web 模块的 Java EE EAR 部署为一个 OSGi 应用程序,只需将该存档的文件扩展名 .ear 更改为 .eba。
在这个示例中,这个容器在被实例化时将 3 个属性(可能是对 bean 定义文件 blueprint.xml 中其他位置定义的 OSGi 服务或 beans 的引用)注入到 bloggingServiceComponent bean 中。Blueprint 配置的 beans 向 OSGi 应用程序提供了一种方便的方法来将它们的业务逻辑封装到一些 POJO 组件中,这些 POJO 组件已经通过 Blueprint 容器在其中注入了它们的依赖项和配置。由于这些 POJO bean 组件在应用程序服务器上没有 Java 依赖项,因此在一个纯 Java SE 或 Eclipse 环境中对业务逻辑进行单元测试非常简单。
这个博客样例展示了企业应用程序的典型架构。该架构包含 4 个松耦合 bundle:一个 Web 层、一个业务逻辑层、一个持久化层、以及一个 API bundle。
首先,注意如何将这些 API 拉到它们各自的 bundle 中。这是保持耦合松散的一个 OSGi 最佳实践。如果必要,一个实现可以在部署时或甚至在运行时轻松交换为另一个实现。
bundle 之间的耦合利用一个基本 OSGi 构造 — 服务(在图 2 中表示为三角形),服务在 bundle 之间维护理想的松散耦合并允许以对应用程序其余部分的最小影响更轻松地替换 bundle 实现。如 OSGi 服务和 Blueprint 组件模型 所述,OSGi 应用程序不必直接与 OSGi 服务注册表交互,相反,可以通过简单 POJO beans 的声明性 Blueprint 配置这样做。blog-biz 和 blog-persistence bundle 都是用 Blueprint 配置的 beans 来封装业务逻辑,并通过管理它们的生命周期的 Blueprint 容器将它们的依赖项和配置注入自身。Blueprint 容器将 blog-biz bundle 中的 beans 连接到一起,并将 blog-biz bundle 中的组件连接到 blog-persistence bundle 提供的 Blog persistence 服务。
应用程序的前端是一个使用我们熟悉的 Java EE servelet 组件的 Web 模块。为演示结合 Java EE 编程风格和基于服务的 OSGi 风格是多么简单,样例 blog-web bundle 遵循一个纯 Java EE 编程模型并使用 JNDI 来访问 Blueprint 发布的 OSGi 服务。企业 OSGi 规范为 JNDI 客户机定义了一个标准机制来获取 OSGi 服务的引用,在两种编程风格之间架起了一个天然的桥梁。
blog-persistence-jpa bundle 将 JPA 用作持久性框架,条目通过该框架持久存储到一个数据库并从该数据库检索。它利用 Blueprint 容器的功能来管理持久性上下文和全局事务,以确保业务逻辑的开发和单元测试尽可能保持简单。
最后,这些博客 JAR 被打包到一个 EBA 中并部署到 WebSphere Application Server。
我们下面仔细看看这个应用程序的每个元素。
清单 9 还展示了一些 Blueprint 容器托管的事务。在这个示例中,persistenceManager bean 的所有方法都在 Blueprint 容器建立(或连接)的一个全局事务下运行。WebSphere Blueprint 容器支持的容器托管的事务值集合与 EJB 容器支持的集合相同。(参见 事务和 OSGi 应用程序 了解更多信息。)
清单 10 中展示的应用程序清单文件需要表明这个服务应该在 OSGi 应用程序外部可见。为此,向应用程序清单文件添加 Application-ExportService 头部,如清单 12 所示。
清单 12. 从 OSGi 应用程序导出服务
除了集成的 Rational Application Developer 工具外,还有几个开源工具可以帮助生成 OSGi bundle 清单文件。另外,Apache Aries 社区开发的 EBA Maven Plugin 也可以从作为一个构建的一部分的 Maven pom 配置生成一个 OSGi 应用程序清单文件。
您现在可以选择这个持久性 bundle 的 1.1.0 版并选择 Preview 按钮来重新解算应用程序,并检查任何不一致。如果预览没有生成错误,那么您可以选择 Commit 按钮来更新应用程序并保存配置。
回页首
结束语
模块式应用程序设计方法的好处包括降低复杂性、减少交付时间和提高服务能力。尽管开发人员非常理解这些好处,经常采取一些最佳实践来鼓励模块式设计,但 Java EE 基础设施自身实施或鼓励模式式设计的能力有限。
企业 OSGi 将 OSGi 的模块性原理和基础设施与用于企业应用程序及其运行的服务器环境的一个熟悉的 Java EE 编程模型结合起来。
WebSphere Application Server V7 Feature Pack for OSGi Applications and JPA 2.0 的 OSGi 应用程序特性为将 OSGi 应用程序部署到 WebSphere Application Server 提供了综合的运行时和集成管理支持。通过使应用程序相互隔离,同时支持共享应用程序组装元数据标示的特定 bundle,应用程序完整性得到维护。应用程序部署流程被扩大为支持从特定于应用程序的存档和共享的 OSGi bundle 知识库提供应用程序内容,从而减小了应用程序存档大小以及磁盘和内存占用。类似于 Spring 的声明式组装和依赖项注入,以及简化应用程序外部的单元测试的好处,通过由 OSGi 标准管理并集成到服务器运行时的 Blueprint 容器提供。OSGi 应用程序到异构复合的组装和 OSGi 服务的远程绑定通过 OSGi 应用程序的一个新 SCA 组件实现提供。
OSGi 开发人员的工具化通过 Rational Application Developer 提供,包括 OSGi 元数据的生成器和编辑器、开发环境中的 OSGi 模块化约束的实施、企业 bundle 存档的导入/导出、以及在服务器中运行和调试 OSGi 应用程序的工作空间集成功能。
现在就试试吧!
<!-- CMA ID: 547954 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->
参考资料
学习
WebSphere Application Server Information Center 包含这个特性包的文档