主题
企业架构
我们现在要创建的应用程序由四个OSGi程序包组成,其中两个包含业务逻辑类或服务,其余的包含一个监控服务(监听OSGi环境中发生的事件)和一个最终程序包(包括服务调用请求和以基于文本的格式返回结果的逻辑)。再说一次,请记住OSGi程序包能包含的类的多样性。我们的程序包包含服务器逻辑和客户端逻辑,以及辅助的监控功能。查阅示例下载代码,您会有此感觉,会了解我们能够多么容易地将数据库逻辑或一些其他支持功能也包括其中。
运行和部署OSGi程序包高度特定于您要针对的实现。在这点上,您可能遇到从为了运行和部署OSGi程序包的特殊GUI到命令行工具的一切情况。因为我们将针对Apache的OSGi Felix实现构建OSGi程序包,所以下列步骤说明了从此实现的命令行进行的部署过程。
在工作站上安装了Felix 1.0之后,请确定将示例下载中创建的所有OSGi程序包复制到名为bundle的Felix子目录中。接着,转到Felix的顶层目录并调用以下命令:java -jar bin/felix.jar。之后,会有Enter profile name:的提示。根据喜好输入名称;这对于我们的示例并非关键。如果是在*nix站上,Felix将在您的主目录/.felix目录下以此名称创建一个子目录来放置安装的OSGi程序包。
输入概要文件名称之后,您将在命令提示中看到首先装载的OSGi程序包。至此,您应该看到如下的事件序列:
[Assuming inside top level Felix directory] [web@ws_osmosis felix-1.0.0]$ java -jar bin/felix.jar Welcome to Felix. ================= Enter profile name: introtutorial DEBUG: WIRE: 1.0 -> org.osgi.service.packageadmin -> 0 DEBUG: WIRE: 1.0 -> org.osgi.service.startlevel -> 0 DEBUG: WIRE: 1.0 -> org.ungoverned.osgi.service.shell -> 1.0 DEBUG: WIRE: 1.0 -> org.osgi.framework -> 0 DEBUG: WIRE: 1.0 -> org.apache.felix.shell -> 1.0 DEBUG: WIRE: 2.0 -> org.osgi.framework -> 0 DEBUG: WIRE: 2.0 -> org.apache.felix.shell -> 1.0 DEBUG: WIRE: 3.0 -> org.osgi.service.obr -> 3.0 DEBUG: WIRE: 3.0 -> org.osgi.framework -> 0 DEBUG: WIRE: 3.0 -> org.apache.felix.shell -> 1.0 ->
现在,您正与OSGi环境交互。此时值得讨论的是OSGi程序包可能的状态。active状态指程序包在前面提到的实际的类装载器图中;installed状态指程序包准备好了或者预备好包含到类装载器图中;resolved状态指因为必需的依赖关系,程序包被动态装载。让我们直接看一下这些状态。输入命令ps查看安装的程序包:
-> ps
START LEVEL 1
ID State Level Name
[ 0] [Active ] [ 0] System Bundle (1.0.0)
[ 1] [Active ] [ 1] Apache Felix Shell Service (1.0.0)
[ 2] [Active ] [ 1] Apache Felix Shell TUI (1.0.0)
[ 3] [Active ] [ 1] Apache Felix Bundle Repository (1.0.0)
上面的清单表明在环境中Felix核心程序包是活动的。现在,如下面清单所示安装示例应用程序程序包:
[Assuming sample bundles are located in Felix bundle sub-directory]
-> install file:bundle/listener.jar
Bundle ID: 4
-> install file:bundle/carrier.jar
Bundle ID: 5
-> install file:bundle/carrier2.jar
Bundle ID: 6
-> install file:bundle/userdesk.jar
Bundle ID: 7
-> ps
START LEVEL 1
ID State Level Name
[ 0] [Active ] [ 0] System Bundle (1.0.0)
[ 1] [Active ] [ 1] Apache Felix Shell Service (1.0.0)
[ 2] [Active ] [ 1] Apache Felix Shell TUI (1.0.0)
[ 3] [Active ] [ 1] Apache Felix Bundle Repository (1.0.0)
[ 4] [Installed ] [ 1] Service listener (1.0.0)
[ 5] [Installed ] [ 1] International Flights (1.0.0)
[ 6] [Installed ] [ 1] Domestic Flights (1.0.0)
[ 7] [Installed ] [ 1] Service Tracker-based flight client (1.0.0)
在这最后的清单中,请注意程序包显示(ps)现在是怎样为所有四个应用程序程序包显示一个Installed状态的。启动6号程序包Domestic Flights,然后启动/调用7号程序包查询一次飞行。
-> start 6
DEBUG: WIRE: 5.0 -> intro.carrier.service -> 5.0
DEBUG: WIRE: 5.0 -> org.osgi.framework -> 0
DEBUG: WIRE: 6.0 -> intro.carrier.service -> 5.0
DEBUG: WIRE: 6.0 -> org.osgi.framework -> 0
-> start 7
DEBUG: WIRE: 7.0 -> intro.carrier.service -> 5.0
DEBUG: WIRE: 7.0 -> org.osgi.framework -> 0
DEBUG: WIRE: 7.0 -> org.osgi.util.tracker -> 0
Enter a blank line to exit.
Enter flight: Seattle
Flight available to :Seattle
Enter flight: Atlanta
No flight available to :Atlanta
Enter flight:
-> ps
START LEVEL 1
ID State Level Name
[ 0] [Active ] [ 0] System Bundle (1.0.0)
[ 1] [Active ] [ 1] Apache Felix Shell Service (1.0.0)
[ 2] [Active ] [ 1] Apache Felix Shell TUI (1.0.0)
[ 3] [Active ] [ 1] Apache Felix Bundle Repository (1.0.0)
[ 4] [Installed ] [ 1] Service listener (1.0.0)
[ 5] [Resolved ] [ 1] International Flights (1.0.0)
[ 6] [Active ] [ 1] Domestic Flights (1.0.0)
[ 7] [Active ] [ 1] Service Tracker-based flight client (1.0.0)
->
直接启动两个程序包,客户端程序包正如所料地执行,提示我们某个城市,并用Availability或No Availability的文本消息作出回答。但是请注意5号程序包的最终状态。虽然我们明显没有做任何事来影响它,但它现在却显示Resolved状态。之所以这样,原因是6号和7号程序包依赖intro.carrier.service包,它只存在于5号包中;OSGi只关心解析它的活动程序包所需的,并切换5号程序包后面的状态为Resolved,表示依赖关系被满足了。如果您希望的话,可以试试安装、卸载、启动和中止所有这些为数众多的程序包,这样您就能进一步了解OSGi是如何处理该过程的。随便输入help,会得到所有可用的OSGi命令的清单。
这个示例飞行应用程序可能似乎没什么价值,但是当您采用同样的原则用于更加复杂的企业环境时——这种环境可能同时装载成百上千的类,甚至不一定需要它们——OSGi区别对待需要装载什么和需要何时完成的概念可以拥有强大的性能。
致谢:感谢InfoQ、Peter Kriens、Alex Blewitt和Eric Newcomer对于这些OSGi、JSR和Java EE规范展开的在线讨论。
当OSGi涉及动态Java装载和Java平台缺少的其他服务时,它所提供的功能将极为有用,但是这并不意味Java标准组或JSR委员会背后的人们已经象他们常说的那样“开车时打瞌睡”。事实上,许多联盟的活动老眼与OSGi的特性有关,举例来说: JSR-291与OSGi/Java集成有关, JSR-277 是与OSGi作用域相似且独立的Java模块规范,还有范围很宽的 JSR-316,它与Java EE 6即将发行的版本有关。
顾名思义,模糊的未来是指这些JSR计划的接受程度不同。根据开发的成熟度,OSGi相关的技术——JSR-291——明显比有关Java模块的技术——JSR-277——更加成熟,后面这个计划为Java SE 7的一部分。但是,当人们展望未来,关键的确认部分就会起作用,而以企业为中心的Java EE 6规范——JSR-316——没有提到OSGi相关的特性,因而推迟了对于尚未实现的Java模块规范JSR-277(据说将在Java SE 7中完成)的决策。
当然,这个模糊的未来确实与Java EE 6有关;JSR 277专家组,即Java模块系统,已经表明将力求实现与JSR 291/OSGi的互操作。总而言之,OSGi是三者中最成熟的联盟,当然这部分归功于它对其他Java联盟的影响和其他Java联盟对它的采纳。所以剩下的问题就是:“Java EE 6和Java模块系统会怎样做呢?它们仍然还停留在图纸上,是对OSGi进行补充还是与之集成?”
您可以从这里下载与本文有关的代码。
要安装它,请先解压下载的文件并确定您的工作站安装有Java Ant和Apache Felix OSGi。在顶层目录下运行ant all编译所有示例OSGi程序包。所有程序包将会生成在bundles目录中。接着,复制Apache Felix bundle目录(挨着Felix包括的jar文件)下的所有四个示例OSGi程序包,然后返回Apache Felix顶层目录执行:java -jar bin/felix,启动OSGi命令行会话。按照提示,输入您选择的概要文件名称。然后就会看到一个活动的Felix OSGi会话。执行本文所给的命令安装或卸载程序包,或者输入help获得完整的可用操作清单。
至今,OSGi联盟已经存在一段时间了,它对许多需要动态Java装载微小细节的部门以及标准Java平台没有覆盖的其他组织都产生了一定的影响。现在随着企业面向服务架构的出现,服务器端Java开发正在向这种同样敏捷和灵活的框架/环境迁移,以提供更健壮的应用程序功能。
我们回顾了OSGi程序包的组成和创建,并介绍了如何在应用程序中部署和运行OSGi程序包,您应该能更好地理解在服务器端架构中使用OSGi以及OSGi在Java平台已有的和将有的影响整体上带来的益处和限制。
Daniel Rubio 是一名软件顾问,具有十余年的企业软件开发经验。近期,他创办了Mashup Soft公司,开始专攻为Mashup使用Web services的有关方面。