gembin

OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

HBase, Hadoop, ZooKeeper, Cassandra

Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

About Me

 

利用 Eclipse 开发基于 OSGi 的 Bundle 应用

开放服务网关协议 (Open Services Gateway Initiative),简称 OSGi,为网络服务定义了一个标准的、面向服务的计算环境,为用户提供了开放的、面向服务组件的、易于部署的编程模型,这个编程模型允许用户将定义好的 接口规范绑定到 OSGi 运行环境中的特定Service,在构件 SOA 面向服务为中心的企业应用的过程中,OSGi 技术正发挥越来越重要的作用。在本文中,将介绍 OSGi 的概念和体系结构,并且利用 Eclipse 3.2 开发一个基于 OSGi 规范的服务应用 Bundle。通过学习本文,读者可以了解到如何开发和部署基于 OSGi 规范的 Bundle 应用。

OSGi 规范简介

OSGi 联盟建立于 1999 年,是一个非赢利机构,旨在建立一个开放的服务规范。OSGi 规范为网络服务定义了一个标准的、面向组件的计算环境,它最初的目的就是为各种嵌入式设备提供通用的软件运行平台,屏蔽设备操作系统与硬件区别的中间件平 台,通过这个平台,可以对不同软件商提供的应用(OSGi 中称为 Bundle)进行组件的生命周期管理的能力,如应用组件可以从运行中被安装、升级或者移除而不需要中断设备的操作,应用组件可以动态的发现和使用其他库 或者应用程序。由于 OSGi 技术具有服务组件模块化、动态加载应用等优点,正被越来越多的领域关注,如嵌入设备制造业、汽车制造业、企业应用等。目前,OSGi 联盟发布的最新的 OSGi 服务规范为 4.0,读者可以查阅参考资料了解详细信息。


OSGi 体系结构

OSGi 的体系架构是基于插件式的软件结构,包括一个 OSGi 框架和一系列插件,在 OSGi中,插件称为 Bundle,其中,OSGi 框架规范是 OSGi 规范的核心部分,它提供了一个通用的、安全可管理的 Java 框架,通过这个框架,可以支持 Bundle 服务应用的部署和扩展。Bundle 之间可以通过 Import Package 和 Require-Bundle 来共享 Java 类,在 OSGi 服务平台中,用户通过开发 Bundle 来提供需要的功能,这些 Bundle 可以动态加载和卸载,或者根据需要远程下载和升级。OSGi 体系结构图如图 1 所示:


图示1 OSGi 体系结构
图示1 OSGi 体系结构

其中:

Execution Environment:

Bundle 应用所倚赖运行的 Java 执行环境,如 J2SE-1.4、CDC-1.0 等都是可用的执行环境。

Modules:

模块层定义了 Bundle 应用的加载策略。OSGi 框架是一个健壮并且严格定义的类加载模型。在大多数 Java 应用中,通常只有一个单独的 ClassPath,它包含了所有的 Java 类文件和资源文件,OSGi基于Java技术,对于每个实现了 BundleActivator 接口的 Bundle 应用,为它生成一个单独的 ClassLoader,使得 Bundle 应用的组织更加模块化。

Life Cycle:

生命周期层可以动态地对 Bundle 进行安装、启动、停止、升级和卸载等操作。该层基于模块层,提供了一组 API 来控制 Bundle 应用的运行时操作。

Service Registry 和 Services:

OSGi 服务层定义了一个集成在生命周期层中的动态协作模型,是一个发布、动态寻找、绑定的服务模型。一个服务通常是一个 Java 对象实现了特定的服务接口,并且通过服务注册,被绑定到 OSGi 的运行环境中。Bundle 应用可以注册发布服务,动态绑定服务,并且在服务注册状态改变时,可以接受到事件消息等。

Security:

OSGi 的安全管理是基于 Java2 安全体系的,贯穿在 OSGi 平台的所有层中,它能够对部署在 OSGi 运行环境中的 Bundle 应用进行详细的管理控制。


Bundle 生命周期的状态

在一个动态扩展的 OSGi 环境中,OSGi 框架管理 Bundle 的安装和更新,同时也管理 Bundle 和服务之间的依赖关系。一个 Bundle 可能处于以下六个状态,如图 2 所示:


图示 2 Bundle 状态图
图示 2 Bundle 状态图

INSTALLED:安装完成,本地资源成功加载。

RESOLVED:依赖关系满足,这个状态意味该Bundle要么已经准备好运行,要么是被停止了。

STARTING:Bundle正在被启动,BundleActivator的start()方法已经被调用但是还没有返回。

STOPPING:Bundle正在被停止,BundleActivator的stop()方法已经被调用但是还没有返回。

ACTIVE:Bundle 被成功启动并且在运行。

UNINSTALLED:bundle被卸载并且无法进入其他状态。

Bundle接口定义了getState()方法来返回Bundle的状态。


OSGi 标准服务

在 OSGi 平台之上,OSGi 联盟定义了很多服务。服务是由一个 Java Interface 来定义的,Bundle 可以实现这个接口并且把服务注册到服务注册表中去,用户可以从注册表中找到需要的服务来使用,并且可以响应特定服务的状态改变,如服务注册和服务取消。下 面简单介绍一下 OSGi Release 4 的一些主要服务。OSGi 框架提供了权限管理服务,包管理服务和最初加载系统服务。这些服务是 OSGi 框架的一部分并且管理着 OSGi 框架的运作。

Permission Admin Service:权限管理是指 Bundle 是否许可其他的 Bundle 的代码。当前的或者其他的 Bundle 的权限可以通过这个服务来操作,一旦被设定权限,马上就生效。 Package Admin Service:Bundle 之间可以共享包内的 Java 类和资源,bundle 的更新可能需要 OSGi 框架重新解析 Bundle 之间的依赖关系,这个服务提供了 OSGi 服务平台中包的共享状态信息。

Start Level Service:Start Level是指一些在特定Bundle起动之前必须运行或者初始化的一系列 bundle。Start Lever Service 可以设置当前OSGi服务框架初始的Start Level,并且可以指定和查询特定Bundle的Start Level。



使用 Eclipse 开发 Bundle 应用

Equinox 框架是 Eclipse 组织基于 OSGi Release 4 的一个实现框架,它实现了 OSGi 规范的核心框架和许多标准框架服务的实现。关于Equinox项目的详细信息,请查阅参考资料信息。在本文中,我们使用 Eclipse 3.2 平台开发两个基于 OSGi 的 Bundle 应用,其中第一个 Bundle 应用声明、实现并注册了一个姓名查询服务,用于判断所给姓名是否在已定义的查询列表中;第二个 Bundle 应用查询并引用第一个 Bundle 应用所注册的姓名查询服务,如果用户所给的姓名包含在查询列表中,将返回正确的信息,最后,将开发的 Bundle应用部署的 Equinox OSGi 框架中,用户可以在 OSGi 控制命令行中输入命令来查询关于框架和 Bundle 应用的具体信息。读者可以从参考资料中获得本文 Bundle 应用的源代码。

(1)创建 Plug-in Project,在 Eclipse 3.2 开发环境中,从菜单栏选择 File > New > Project... ,打开 New Project 向导,可以看到有Plug-in Project创建向导,创建一个Plug-in 项目。项目名为 example 的 Bundle 应用,该应用实现并注册了一个姓名查询服务,实现了 BundleActivator 接口。选择 Equinox 框架作为 Bundle 应用运行的 OSGi 服务平台。


图示 3 Plug-in 项目向导
图示 3 Plug-in 项目向导

(2)实现OSGi服务通常需要两个步骤,首先定义所提供服务的接口,然后实现这个服务接口。在本例中,我们创建一个姓名查询服务用来查询所给姓名是否有效。首先定义姓名查询接口NameService.java。下面是该接口的源代码:


NameService Interface 源代码
package example.service;

/**

* A simple service interface that defines a name service.

* A name service simply verifies the existence of a Name.

**/

public interface NameService {

/**

* Check for the existence of a Name.

* @param name the Name to be checked.

* @return true if the Name is in the list,

* false otherwise.

**/

public boolean checkName(String name);

}


该服务接口很简单,只包含一个需要实现的方法。为了将服务接口和服务实现相分离,方便其他 Bundle 引用该服务,我们通常需要将该服务接口单独放在一个包内,本例中,存放NameService.java 接口的 Java 包为 example.service。接下来,需要实现 NameService 接口,并且注册该服务。在本例中,我们用内部类实现了该接口,下面是该 Bundle 应用的部分源代码。


Example Bundle部分源代码
 public void start(BundleContext context) throws Exception {

Properties props = new Properties();

props.put("ClassRoom", "ClassOne");

context.registerService(NameService.class.getName(), new NameImpl(),

props);

}

private static class NameImpl implements NameService {

// The set of names contained in the arrays.

String[] m_name = { "Marry", "John", "David", "Rachel", "Ross" };

/**

* Implements NameService.checkName(). Determines if the passed name is

* contained in the Array.

*

* @param name

* the name to be checked.

* @return true if the name is in the Array, false otherwise.

*/

public boolean checkName(String name) {

// This is very inefficient

for (int i = 0; i < m_name.length; i++) {

if (m_name[i].equals(name)) {

return true;

}

}

return false;

}

}


在start()方法中,利用BundleContext注册一个姓名查询服务,并且为该服务设置相关属性以便服务查询。在实现姓名查询服务时,我们简单定义了一个静态数组用于存放有效的姓名信息。

(3)定义Bundle描述文件MANIFEST.MF,Bundle应用example的MANIFEST.MF文件如下:


MANIFEST.MF文件信息
Manifest-Version: 1.0

Bundle-ManifestVersion: 2

Bundle-Name: Example Bundle

Bundle-SymbolicName: example

Bundle-Version: 1.0.0

Bundle-Activator: example.osgi.Activator

Bundle-Localization: plugin

Import-Package: org.osgi.framework;version="1.3.0"

Export-Package: example.service


其中,Bundle-Activator属性指明了实现BundleActivator接口的类,该类用来启动和停止Bundle应用。Export-Package属性指定了该Bundle输出的共享包,该属性可以使其他的Bundle应用引用我们所定义的服务接口。

(4)创建项目名为exampleClient的Bundle应用,该应用在OSGi平台上查寻并引用example Bundle应用已经注册的姓名查询服务,然后从标准输入读入用户所输入的姓名信息,判断所输入姓名是否有效。exampleClient应用的部分源代 码如下,读者可从参考资料中获得完整源代码。


ExampleClient Bundle部分源代码
 public void start(BundleContext context) throws Exception {

ServiceReference[] refs = context.getServiceReferences(

NameService.class.getName(), "(ClassRoom=*)");

if (refs != null) {

try {

System.out.println("Enter a blank line to exit.");

BufferedReader in = new BufferedReader(new InputStreamReader(

System.in));

String name = "";

// Loop endlessly.

while (true) {

// Ask the user to enter a name.

System.out.print("Enter a Name: ");

name = in.readLine();

// If the user entered a blank line, then

// exit the loop.

if (name.length() == 0) {

break;

}

// First, get a name service and then check

// if the name is correct.

NameService nameservice = (NameService) context

.getService(refs[0]);

if (nameservice.checkName(name)) {

System.out.println("The Name is Correct.");

} else {

System.out.println("The Name is Incorrect.");

}

// Unget the name service.

context.ungetService(refs[0]);

}

} catch (IOException ex) {

}

} else {

System.out.println("Couldn't find any name service...");

}

}




Bundle的部署及运行

在Eclipse平台中,选择File-->Export...菜单,将开发的example和exampleClient两个Bundle 应用导出成Jar文件,以便将它们部署到OSGi服务平台中。选择将要运行的Bundle应用,鼠标右键点击,在弹出菜单中,选择Run AS-->Equinox FrameWork来启动OSGi服务平台。在Equinox启动配置控制台中,可以为Bundle应用设置默认的Start Level和Bundle应用是否需要自动启动等选项。在本例中,为了讲解如何安装及启动Bundle应用,只将example Bundle应用设为自动启动,而exampleClient Bundle应用需要我们用命令安装及启动。

当OSGi Equinox FrameWork启动后,在OSGi控制命令台中输入ss命令,可以查看OSGi服务平台中已经安装的Bundle应用信息及其状态。如图4所示,可以 看到当前OSGi服务平台中有两个Bundle处于Active状态,其中,system.bundle_3.2.0.v20060328为OSGi框架 的系统Bundle,而example_1.0.0为注册姓名查询服务的Bundle应用,1.0.0为Bundle应用的版本号。


图示4 Bundle信息查询
图示4 Bundle信息查询

在OSGi控制命令台中利用install命令安装exampleClient Bundle应用,用ss命令查看安装后的Bundle应用信息及其状态。如图5所示:


图示5 安装Bundle
图示5 安装Bundle

在OSGi控制命令台中利用start命令安装exampleClient Bundle应用,用户可输入姓名,利用姓名查询服务来判断所输入姓名是否有效,用ss命令查看启动后的Bundle应用信息及其状态。如图6所示:


图示6 启动Bundle
图示6 启动Bundle

用户在在OSGi控制命令台中,可利用stop命令来停止指定的Bundle应用,close命令用来停止并退出OSGi控制命令台。关于OSGi Equinox FrameWork控制台命令的详细信息,可查看参考资料。


总结

OSGi服务框架提供了开放的、面向服务的、易于部署的编程模型,在构件面向服务为中心的企业应用的过程中,OSGi 技术正发挥越来越重要的作用。目前,Eclipse 3.2 体系架构是参照OSGi实现的,Equinox框架是 Eclipse 组织基于OSGi Release 4 的一个实现框架,它实现了OSGi 规范的核心框架和许多标准框架服务。在本文中,我们利用Eclipse 平台开发了两个Bundle应用,并且在Bundle应用中,声明、实现、注册并引用了一个简单的服务,最后,将Bundle应用部署到Equinox OSGi服务框架中。通过本文,读者可以了解如何开发和部署基于OSGi规范的Bundle应用。



下载





posted on 2008-05-08 10:50 gembin 阅读(1011) 评论(0)  编辑  收藏 所属分类: OSGi


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

常用链接

留言簿(6)

随笔分类(440)

随笔档案(378)

文章档案(6)

新闻档案(1)

相册

收藏夹(9)

Adobe

Android

AS3

Blog-Links

Build

Design Pattern

Eclipse

Favorite Links

Flickr

Game Dev

HBase

Identity Management

IT resources

JEE

Language

OpenID

OSGi

SOA

Version Control

最新随笔

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜

free counters