OSGi点菜
在OSGi上进行网络搜索将产生数量众多的开源项目。 除了熟悉的Equinox和Felix,随着OSGi进入企业Java领域,与OSGi相关的项目数量也在增加。 如果您对OSGi感兴趣,那么这些项目中的许多项目将对您很有用,但如何使用它可能并不立刻显而易见。 本文希望通过作者遇到的最有用的开源工具来缓解这种不足。
自90年代末以来,OSGi作为一种技术就已经存在了,最初是在嵌入式领域。 在Eclipse采用OSGi作为Eclipse IDE底层的集成和插件技术之后,人们产生了更广泛的兴趣。 此举之后,OSGi被采用为大多数JEE应用服务器核心的模块化技术。 即使在那时,OSGi在单个应用程序领域也要少得多。 只有在带有Spring dmServer的专用企业级OSGi编程模型出现之后,我们才看到对OSGi的广泛兴趣。
从历史上看,OSGi通常被认为是一种很难入门的技术,尤其是因为OSGi当然是一种侵入性技术。 正确使用OSGi及其模块化模型需要开发人员和框架作者的纪律和远见。 特别是关于类加载器的假设通常在OSGi环境中不再成立。 但是,使用OSGi进行模块化的好处及其对动力学的内在支持远远超过了使用它的最初挑战。
本文希望通过引入适当的工具集来消除使用OSGi的一些最大障碍,其中许多工具是最近才使用的。 第一组工具旨在帮助开发捆绑软件。 接下来,我们看一下促进与OSGi集成(即容器内)测试的工具。 最后,我们来看一下部署和分发选项。
假定读者熟悉一些基本的OSGi概念,例如捆绑软件,捆绑软件清单,服务和OSGi生命周期。 完全不熟悉OSGi的读者可以参考介绍性资源,例如尼尔·巴特利特(Neil Bartlett)的“ 实践中的OSGi ”以及OSGi主页 。
开发捆绑
在最简单的层次上,OSGi捆绑包只是一个传统的JAR文件,其清单包含一些其他标头,这些标头定义了捆绑包的身份以及其(包)功能和要求–导入和导出。 但是,经常被引用的粗体说法“使用OSGi不再出现NoClassDefFoundErrors”依赖于正确的元数据。 缺少所需软件包的导入很容易意味着OSGi在最初使用时实际上会引入更多的缺失类,而不是更少。
因此,用于OSGi开发的工具至少应帮助开发人员生成正确的元数据和结构合理的捆绑包。 除此以外,开发工具还应有助于测试捆绑软件的运行,并且理想情况下应支持OSGi编程模型,例如组件模型,Web应用程序捆绑软件,持久性捆绑软件等。
Eclipse PDE和天秤座
也许最著名的OSGi工具是Eclipse插件开发环境 ,它来自Eclipse IDE的许多常见发行版(例如,用于JEE开发的发行版)。 它提供了OSGi开发的所有必需品,例如内容感知的捆绑清单清单编辑器和强制执行OSGi可见性规则的编译器插件(除非通过自定义构建路径回避)并报告缺少导入的错误。 最重要的是,可以通过OSGi框架定义直接从IDE启动捆绑包集合。 PDE的最大资产也是其最大的缺点:明确性。 开发人员需要精心制作OSGi清单,并在代码更改时对其进行更新。
另一方面,结果清单将永远不会包含任何意外。 另外,一些有关版本范围和Require-Bundle使用情况的默认建议也不符合被广泛接受的OSGi最佳实践。
对于开发更多以企业为中心的OSGi应用程序,例如在捆绑包中使用JPA结束Servlet功能, Eclipse Libra承诺是一个有趣的选择。 该项目与IBM的免费(但不是开源) OSGi开发工具松散相关,旨在将现有的用于JEE开发的高质量Eclipse工具与OSGi企业规范相应章节中定义的OSGi特定功能集成在一起。
Bnd和BndTools
尽管PDE的显式创作方法显然可以工作,但是还有另一个更方便的选择,即可以生成大多数困难的东西(尤其是Import-Package)。
毕竟,源代码以及字节码具有确定依赖关系所需的大多数信息。 彼得·克林斯(Peter Kriens)的Bnd工具建立在这样的前提下:大多数清单可以用一种特定的领域特定语言(DSL)描述,其余的可以在通过内省这些类来组装捆绑包时填写。 使用这种方法,将第三方JAR转换为功能束也变得很简单(假设它们没有对代码中的类加载器进行假设)。 Bnd还尊重OSGi最佳实践,例如为导出的软件包生成use指令。
Bnd工具不仅可以转换JAR文件,还可以为捆绑软件开发提供整体解决方案,支持复杂的捆绑软件程序集,可以从多个来源提取类,捆绑软件验证以及启动用于运行应用程序或运行集成测试的框架。 下面的调用显示了将JAR转换为包的非常基本的用法(清单1)。
尽管上面的示例将Bnd显示为独立的命令行工具,但是它可以集成到Ant或Maven构建中。 Neil Bartlett甚至基于Bnd创建了一个完整的Eclipse开发环境BndTools 。 完整的软件包包括功能强大的编辑器,用于定义捆绑软件(甚至对于一个Eclipse项目来说,甚至几个),支持运行捆绑软件的集合,甚至将代码更改热交换到正在运行的框架中。 最重要的是,有用于定义声明式服务组件(图1)和集成测试的预构建模板。
带有Felix Bundle插件和Pax Construct的Maven
上面的项目以IDE为中心或与Bnd无关。 一些读者可能正在寻找非常成熟的构建解决方案,尤其是在面对大型OSGi应用程序时。 这可以在几乎所有Apache OSGi项目中使用的Maven构建基础结构中找到。 Maven作为OSGi项目的构建选择,因为所有主要的IDE都具有Maven插件,因此可以自由选择IDE。 而且,Maven的依赖性管理有利地与OSGi的模块化概念保持一致。 Maven本身并没有直接支持OSGi打包,但是Apache Felix Bundle插件增加了该功能,并在Apache项目中广泛使用。 Felix软件包插件在后台使用Bnd,因此用于定义软件包的配置选项与直接使用Bnd或通过BndTools使用Bnd相同。
尽管Maven有许多优点,但为OSGi建立正确的基础结构却是一个耗时的过程,尤其对于Maven新手而言,这似乎令人生畏。 幸运的是, Pax Construct项目提供了一个非常有用的入门工具包。 它有助于创建Maven 2 OSGi项目并定义单个捆绑包。 Pax Construct还为从Maven启动测试OSGi环境提供了出色的支持。
组件模型
最后,如果不提到组件模型,那么关于OSGi开发的任何部分都将是不完整的,这极大地简化了OSGi动态性的使用,尤其是OSGi服务(或由 Peter Kriens称为μServices的μServices )的使用。 这两个模型使开发人员免于使用复杂的OSGi API进行服务的责任,并且在某种程度上还可以隐藏一些不需要的动态特性。 作为OSGi汇编规范的一部分,两个组件模型已经标准化,并且得到了广泛使用。
较旧的组件模型Declarative Services允许定义服务组件。 这些组件是普通的Java类,它们由Declarative Services扩展程序实例化以及**和停用。 组件可以依赖于其他服务,这些服务由扩展程序注入。 在运行时,组件以XML定义。 但是,Bnd工具还允许使用更简单的属性语法和注释。 在此基础上,BndTools具有一组不错的编辑器和项目模板,可用于声明式服务。 下面的代码示例显示了带注释的组件和等效的(生成的)XML的示例。 该示例组件使用零个或多个StockProvider服务,可以动态添加或删除这些服务(清单2)。
OSGi Compendium Specification版本4.2引入的更新的组件模型Blueprint提供了完整的依赖项注入框架,该语法从语法上基于流行的Spring框架,并提供了与OSGi服务注册表交互的一流支持。 除了XML组件描述符的语法外,声明式服务和蓝图之间最显着的区别可能在于两者如何公开OSGi服务动态。
声明式服务将动态直接暴露给客户端代码。 通过一种方法(在示例中为addProvider)注入的服务通过另一种方法(在示例中为remove-Provider)删除。 当强制性服务依赖关系消失时,组件将被停用;当替换可用时,组件将被重新**。 另一方面,蓝图试图隐藏其中的一些动态。 例如,如果所需的服务依赖项不可用,则不会停止或通知Blueprint bean。 实际上,它将继续运行,直到组件尝试以某种方式使用所需的服务。 那时,Blueprint容器将暂停以等待替换服务可用,然后继续对该服务进行暂停的方法调用。 通过此服务,基于Blueprint构建的OSGi捆绑包可以忽略其服务依赖项的短暂中断(例如由于实时更新),同时仍可享受潜在的连续更新带来的好处。 当然,Blueprint还支持让组件侦听并对服务生命周期事件直接做出反应。 清单3中的Blueprint片段显示了与之前显示的Declarative服务描述符等效的Blueprint描述符。
Pax考试测试
在OSGi的生命中早晚都会出现一个问题,即如何测试不同捆绑软件之间的集成,尤其是使用OSGi服务的项目(例如,通过上述组件模型之一)。 可以对组件进行相当彻底的单元测试,但是必须进行一定程度的容器内测试,例如,以确保正确定义组件。
存在一些用于运行容器内测试的选项,每种选项都提供了实现基本目标的不同方法:在具有特定运行时捆绑包的OSGi框架中启动包含多个JUnit测试的捆绑包。 可用的选项包括Bnd本身,基于它的BndTools集成测试配置以及PaxExam。 其中,作者发现PaxExam及其基于注释的配置和流线型配置DSL特别优雅。 基本的PaxExam测试(使用2.0.0分支)可能类似于清单4。
该代码段显示了一个简单的集成测试,在这种情况下,该测试驱动了Blueprint公开服务。 请注意,即使只有一个带@Test注释的方法,给定的测试类实际上也会执行两个测试:一个在Equinox上,一个在Felix上。 如代码中所示,Pax Exam与Maven构建基础结构配合使用时效果特别好。 但是,它也可以与纯文件URL一起使用。
部署方式
对于OSGi项目,部署问题相对较早出现。 使用OSGi,仅用适当长的类路径运行Java命令并指向某个主类就不再足够了。 相反,部署OSGi应用程序的任务变得复杂,因为首先需要引导OSGi框架,然后安装并**应用程序捆绑包及其所有依赖项。
最简单的方法是启动三个常见的开源框架( Apache Felix , Eclipse Equinox和Knopflerfish )中的每个框架,然后使用该框架的默认控制台-所有这些都不一样! –或OSGi框架API以安装其他捆绑软件。 这种方法很快变得非常不便,并且无助于OSGi框架的可访问性。 特别是,对于使用一个或多个纲要或企业规范的复杂应用程序,显然不是这种选择。
幸运的是,有各种选项可轻松引导自定义的苗条OSGi运行时以及完整的企业级预构建运行时。 几乎在所有情况下,各种运行时位都是完全独立于运行时的,就像人们从主要关注模块化的技术组件中所期望的那样,它们可以在任何其他运行时中重用。
Pax Runner
作为单个OSGi框架的基本本机启动工具的替代,Pax Runner项目提供了一种统一的方式来启动三个开源框架(始终安装了默认控制台)中的任何一个,并将应用程序和支持包置备到该框架中。 这使得启动简单的OSGi应用程序变得轻而易举。
捆绑包可以通过多种来源进行设置:磁盘上的文件,URL以及列出捆绑包资源的简单设置文本文件。 特别是URL方案有很多灵活性(通过嵌入式使用Pax URL项目); 捆绑包可以通过其Maven坐标直接从Maven存储库中获取。 最后,概要文件提供了许多非常有用的预构建捆绑包选择,以供诸如Declarative Services运行时之类的常用功能使用。 下面的命令显示了一种特定的调用。
pax运行–platform = equinox –profiles = felix.ds <bundles…>
该命令引导一个Equinox框架,然后安装Apache Felix Declarative Services实现所需的所有捆绑软件,最后将所有列出的文件作为捆绑软件安装到该运行时中。
卡拉夫
从Pax Runner 迈进的一步是Karaf ,它提供了更加完善的原型运行时,同时仍然非常轻巧且启动Swift。 默认情况下,Karaf带有对Blueprint组件模型,远程访问,基于JAAS的安全性和供应的出色内置支持–更不用说出色且可扩展的shell(基于Felix Gogo shell),所有这些使得与Karaf一起工作真正的乐趣。
与Pax Runner提供的配置文件相似的是Karaf功能,这些功能捕获了通常需要的功能。 例如,要部署Web应用程序捆绑包(WAB),只需安装“ war”功能即可。 甚至还有一个功能可以部署成熟的Spring dmServer运行时(请参阅下文)。 借助大量预定义的EE功能,可以轻松启动仅包含所需功能的自定义企业级运行时。 也可以通过自定义“扫描功能” URL方案从Pax Runner使用Karaf功能。 请注意,在某些情况下,需要在空白Pax Runner框架中手动添加Karaf中默认可用的先决条件。
一个值得特别提及的特别不错的选择是可以基于Apache Felix Web Console设置Web控制台 ,当然也可以在其他运行时中单独安装它。
供应
Pax Runner配置文件和Karaf功能依赖于捆绑包的预定义集合。 这样做的好处是可以可靠地测试组成特征的束的具体选择。 但是,这种供应机制无法利用运行时功能的存在。 例如,war功能需要servlet API,并且将在运行时中不管servlet类是否已经可用(以正确的软件包版本)都将安装Geronimo servlet API捆绑包。 功能和配置文件的主要挑战是它们不声明声明的捆绑包依赖项(Import-Package,Require-Bundle等),因此置备系统无法避免重复。
一个不受此问题困扰的有趣替代方法是可从Apache Felix OBR获得的OSGi Bundle存储库技术(OBR)。 OSGi捆绑软件存储库不仅存储捆绑软件二进制文件,还存储从捆绑软件清单和可能的其他来源(例如组件描述符等)中提取的功能和要求。 供应者可以使用这些信息以及有关当前运行时的信息来精确供应所需的信息。 因此,根据功能X和Y(其中Y在运行时中已经可用)而配置包A,将安装A和提供X的包(以及该包的任何其他传递依赖项)。 这是一个功能强大的预配置模型,无需一次又一次精确地指定捆绑组合,并将工作的重心转移到预配置系统上。
为了使用OBR,Karaf在OBR功能中提供了OBR预配器。 可以通过Bindex工具 (仅支持在软件包清单中声明的软件包和软件包依赖项)或Apache Aries存储库生成器 (用于为Blueprint定义的服务和引用生成功能和要求)来生成软件包存储库。 。 可以在Apache Felix Sigil找到公共OBR存储库的集合。
预先建立的企业堆栈
到目前为止提供的运行时选项都与简化管理自定义运行时的任务有关,仅使用所需OSGi应用程序所需的功能,而不会增加负担。 但是,在某些情况下,较小的运行时和更快的启动时间所带来的好处不会超过管理本质上是轻量级应用服务器运行时所需的额外工作,而不是采用预定义的全包程序。
共有三个开源选项: Apache Geronimo 3.0 , Eclipse Virgo和Glassfish 。 这些都支持不同类型的应用程序。 这些完整选项的基础是许多企业规范,其中包括Blueprint,JNDI,Web和JPA。 这些可以作为单独组件从Eclipse Gemini和Apache Aries中获得,但Pax Web可以提供Web应用程序捆绑支持,但可以单独使用(例如,通过Karaf,它具有Aries组件的预定义功能) )。 即使应用程序模型在语法上有所不同,Geronimo和Virgo之间的核心思想是相同的。
通过Geronimo中的应用程序清单或处女座中的计划定义的OSGi应用程序定义了从逻辑上定义应用程序的捆绑软件(甚至是处女座的计划中的配置工件)的集合。 作为示例,上面显示了Apache Aries Blog示例应用程序的描述符。
分配
在采取OSGi开发的第一步之后不久,许多人想知道如何将事物连接起来。 例如,如何使在两个不同框架中运行的两个OSGi应用程序互相通信? OSGi应用程序如何容易地分布在多个部署系统中?
如何将OSGi应用程序连接到旧版JEE应用程序? Apache CXF和Tuscany提供了一些答案。 Apache CXF是分布式OSGi规范的参考实现。 通过非常简单的元数据添加,它允许在OSGi服务级别上连接两个OSGi框架。 这种分发方法非常适合OSGi服务模型,该模型从一开始就是动态的。 与大多数OSGi规范实现一样, ECF项目中的Eclipse相当于分布式OSGi。
Apache Tuscany可用于将OSGi服务连接到非OSGi工件,例如传统的Java,Spring或Web组件。 为此,托斯卡纳支持OSGi服务要实现的SCA(服务组件体系结构)组件。 这样,其他SCA组件就可以使用此类服务,而其他SCA组件不一定要在OSGi中实现。 类似地,被定义为SCA组件的OSGi服务可以声明对其他SCA组件的引用,并以此作为服务使用,而这些OSGi服务不再需要在OSGi中实现。
结论
希望通过这次简短的导览使读者对OSGi生态系统所能提供的功能产生启发。 根据作者的经验,各种不同工具和框架之间的重用量惊人。 这仅说明了组件的成熟度以及OSGi作为模块化和重用平台的优势。
Article taken from Java Tech Journal .