OSGi Bundle之Hello World

来源:互联网 发布:淘宝营销思路 编辑:程序博客网 时间:2024/05/02 05:29

http://developer.51cto.com/art/200909/152209.htm

本文是《你好,OSGi》系列的第二部分。之前曾介绍过OSGi是什么,下面将继续上篇介绍的内容,讲述一个简单的OSGi Bundle:Hello World是如何开发的。

51CTO编辑推荐:OSGi入门与实践全攻略

开发一个简单的Hello World的OSGi Bundle(OSGi绑定包)

在OSGi中,软件是以Bundle的形式发布的。一个Bundle由Java类和其它资源构成,它可为其它的Bundle提供服务,也可以导入其它Bundle中的Java包;同时,OSGi的Bundle也可以为其所在的设备提供一些功能。Eclipse为开发OSGiBundle提供了优秀的支持,它不仅提供了向导来创建OSGi Bundle,而且还提供了内嵌的Equinox容器,您可以使用该容器执行和调试OSGi插件。请注意每一个Eclipse插件,从本质上说,都是一个OSGi Bundle,只是这个OSGiBundle多加了一些Eclipse专用的代码而已。下面我们来看看如何使用Eclipse开发一个简单的OSGi的HelloWorld Bundle。

3.1.新建Bundle

1) 在Eclipse中,点击“File->New->Project”菜单,您将会看到新项目创建对话框;

2) 在新项目对话框中,选择“Plug-inProject(插件项目)”并点击“Next(下一步)”按钮,您将看到插件项目对话框;

3) 在插件项目对话框中,请键入下列值:

Project Name(项目名称):com.javaworld.sample.HelloWorld

Target Platform(目标平台):an OSGiFramework->Standard (OSGi框架->标准)

4) 对其它的要求输入值采用缺省值,并点击“Next(下一步)”按钮,您将会看到插件上下文对话框;

5) 在插件上下文对话框中,请选择缺省值并点击“Next(下一步)”按钮;

6) 在模板对话框中,请选择“Hello OSGiBundle(你好,OSGi包)”模板,然后点击“Finish(完成)”按钮完成该项目。

Eclipse将花几秒钟生成HelloWorld Bundle模板代码,它将新建两个文件:Activator.java和MANIFEST.MF,下面,让我们看看这两个文件:

3.1.1. Activator.java文件

源代码清单1.Activator.java

  1. package com.javaworld.sample.helloworld;  
  2. importorg.osgi.framework.BundleActivator;  
  3. importorg.osgi.framework.BundleContext;  
  4. publicclass Activator implements BundleActivator {  
  5. public void start(BundleContext context)throws Exception {  
  6. System.out.println("Helloworld");  
  7. }  
  8. public void stop(BundleContext context)throws Exception {  
  9. System.out.println("GoodbyeWorld");  
  10. }  
  11. }  
  12.  

如果您想让您开发的Bundle能在其启动或关闭时通知自身,那么您应新建一个类,让它实现BundleActivator接口,同时,您还需要遵行下列规则:

这个实现了BundleActivator接口的类必须有一个public的、不带参数的构造函数,这样,OSGi框架就能调用该类的Class.newInstance()方法创建这个BundleActivator对象;

容器将调用Activator类的start()方法来启动Bundle,因此,我们可以在start()方法中执行一些资源初始化的操作,例如,我们可以在该方法中获取数据库连接,以备后用。这个start()方法的唯一参数是一个BundleObject对象,Bundles可以通过该对象和OSGi框架通讯,我们可以从该对象中获取OSGi容器相关的一些信息;如果某个Bundle抛出异常,容器将之置为“stopped(已停止)”状态,此时,这个Bundle就不能对外提供服务。

如果我们要关闭一个Bundle,容器将调用Activator类中的stop()方法。因此,我们可在stop()方法中执行一些资源清理任务,比如释放数据库连接。

一旦Activator类准备就绪,您就可以通过MANIFEST.MF文件把该包的合法名称传给容器。下面,我们就看看这个MANIFEST.MF文件。

3.1.2. MANIFEST.MF文件

该文件是Bundle的部署描述文件,其格式和正常JAR文件包中的MANIFEST.MF文件相同,因此它由一系列的属性及这些属性对应的值组成,属性名位于每一行的开头,我们可以称其为属性头。OSGi规范规定,您可以使用属性头向容器描述您的Bundle。您的HelloWorld Bundle的MANIFEST.MF文件看起来应该如清单2所示:

源代码清单2. Hello World Bundle中的MANIFEST.MF文件

  1. Manifest-Version:1.0 
  2. Bundle-ManifestVersion:2 
  3. Bundle-Name:HelloWorld Plug-in  
  4. Bundle-SymbolicName:com.javaworld.sample.HelloWorld  
  5. Bundle-Version:1.0.0 
  6. Bundle-Activator:com.javaworld.sample.helloworld.Activator  
  7. Bundle-Vendor:JAVAWORLD  
  8. Bundle-Localization:plugin  
  9. Import-Package:org.osgi.framework;version="1.3.0" 
  10.  

我们来看看这个文件中使用的属性头:

Bundle-ManifestVersion

该属性头告诉OSGi容器,本Bundle将遵循OSGi规范,数值2表示本Bundle和OSGi规范第4版本兼容;如果该属性的数值为1,那么则表示本包和OSGi版本3或更早版本兼容。

Bundle-Name

该属性头为本Bundle定义了一个简短的、可以阅读的名称;

Bundle-SymbolicName

这个属性头为本Bundle定义了一个唯一的、非本地化的名字;当您需要从别的Bundles中访问某一指定的Bundle时,您就要使用这个名字。

Bundle-Version

该属性头给出了本Bundle的版本号。

Bundle-Activator

该属性头给出了本Bundle中使用的监听器类名字,这个属性值是可选的。监听器将对Activator中的start()和stop()方法监听。在程序清单2中,该属性头的值为com.javaworld.sample.helloworld.Activator。

Bundle-Vendor

该属性头是对本Bundle发行商的表述。

Bundle-Localization

该属性头包含了本Bundle的本地化文件所在的位置,我们的HelloWorld Bundle中并没有本地化文件,但Eclipse IDE仍自动产生这个属性头

Import-Package

该属性头定义了本Bundle中引入的Java包,我将在本文后面的依赖性管理小节中详细讲解这个问题。现在,HelloWorld Bundle已经准备就绪,让我们来运行并看看它的输出结果。

3.2. 运行Bundle

我在前面提到,Eclipse IDE中有一个内嵌的EquinoxOSGi容器,您可以利用它来执行或调试OSGi Bundle。请按照下面步骤执行刚才的HelloWorld Bundle:

1 ) 单击RunàRun… 菜单(译者注,在Eclipse3.3中,请单击RunàOpen Run Diglog…菜单);

2) Eclipse会打开“Create,manage and run configuration(新建、管理和运行配置)”对话框,请双击”EquinoxOSGi Framework”按钮,Eclipse将打开运行时配置对话框;

3) 在上面的对话框中,将Name(名称)输入框的值改为HelloWorld Bundle;

4) 您会注意到在Workspace插件目录下,有一个名为com.javaworld.sample.HelloWorld的插件,请选中它;在TargetPlatform(目标平台)下,请确保org.eclipse.osgi插件被选中。您的Run(运行)对话框应该看起来如图1所示:

HelloWorld Bundle的运行配置 

图1. HelloWorld Bundle的运行配置

5) 现在,请单击Run(运行)按钮,您应该看到控制台视图上打印出“HelloWorld”。其实,Eclipse是在控制台视图中打开OSGi控制台。

3.2.1. OSGi控制台

OSGi控制台是OSGi容器的命令行界面,您可以在这个控制台上启动、停止、安装、更新和删除Bundles。在EclipseIDE中,请点击该控制台视图获得焦点,然后按回车键,这时您可以看到OSGi提示符,如图2所示:(译者注,在Eclipse3.3中,如果您没有看到OSGi提示符,请在图1的运行配置中,点击Arguments标签,然后在ProgramArguments(程序参数)输入框中键入“-console”,然后再次运行该Bundle)。

OSGi控制台和HelloWorldActivator.java 

图2. OSGi控制台和HelloWorldActivator.java

下面是几个经常使用的OSGi命令,您可以使用这些命令与OSGi容器进行交互。

  1. ss: 该命令显示所有已安装的Bundles及它们的状态,它将显示Bundle ID,Bundle的简短名称及Bundle状态;  
  2. start< bundleid>: 该命令将启动一个Bundle;  
  3. stop< bundleid>: 该命令将停止一个Bundle;  
  4. update< bundleid>: 该命令使用新的JAR文件更新一个Bundle;  
  5. install< bundleid>: 该命令将一个新的Bundle安装到OSGi容器;  
  6. uninstall< bundleid>: 从OSGi容器中卸载一个已安装的Bundle。   

请注意,这些命令是OSGi规范中规定的,因此,您可以使用它们和任何OSGi容器交互。

读到这里,希望您对OSGi Bundle的开发有了一个大致的了解。

 

 

=================

http://zhoufu24.iteye.com/blog/131787

几种OSGI bundle的打包方法及注意事项

OSGImavenEclipse配置管理项目管理 
前言:我相信做基于OSGI框架开发的朋友,对于OSGI的基本单元Bundle应该并不陌生,平时的开发中,做得最多事情就是bundle的开发和打包了,打包其实属于蛮重要的一个过程,为什么说他重要呢,其实打包的过程就是一个理清bundle依赖关系的过程,在对OSGI的学习和使用过程中,个人觉得最令人头痛的就是bundle之间的依赖关系,而且我到现在为止还没有找到一种比较好的工具能够很好的管理OSGI环境中的各个bundle的依赖关系。不过现在公司也有开始考虑做一些类似phpadmin,mysqladmin这样的基于web的管理工具来对bundle进行统一管理,在这之前,如何解决依赖关系,如何将bundle正确的打包出来并进行部署成了OSGI开发中的一个主要问题,而这篇文章中,我主要介绍目前我自己用过得几种打包方式,总结下经验,如果大家有更好的方法或者有不清楚的地方也可以提出来一起讨论~

第一种方法就是直接通过eclipse提供的export功能,来直接导出一个一个插件工程,这个过程,相信大家已经用的很熟悉了,直接eclipse给你的提示一步步来就可以了。


这里我只想稍微提几个注意的问题,首先是在打包的时候注意把必要的资源文件给勾选上,像我有时就忘记勾选上一些OSGI service的配置文件,而导致service不能发布或者获取。其次,检查好你的项目自描述文件MANIFAST.MF里面的OSGI相关的配置信息是否都已经写正确,该export和该import的包是否写对,个人觉得OSGI最让人头疼的就是解决bundle之间的依赖关系,有时候OSGI环境一大,依赖关系变得复杂,导出包,引用包常常会容易混淆,所以对OSGI环境中的组件的依赖进行统一管理和限定,可以使bundle的依赖更加清晰,环境也易于管理,降低OSGI开发复杂度。最后,有时候在导出包的时候会碰到一些问题,比如bundle之间循环调用,多半还是由于Bundle之间的依赖发生了冲突的关系,检查一下是否多个bundle是否导出了相同包,bundle的引入包是否正确等等。

第二种方法则是利用apache为maven2.0提供的一个专门来打OSGI包的felix(http://felix.apache.org/site/maven-osgi-plugin.html)插件来利用maven进行OSGI bundle的打包工作,felix这个插件在maven中的使用还是比较容易的。官方网站(http://cwiki.apache.org/FELIX/osgi-plugin-for-maven-2.html)上给出了一个比较详尽的使用说明,这里我大致说明一下,只需要在项目的pom文件中配置一个plugin就ok了,最简单的配置如下:<o:p></o:p>

xml 代码
 
  1. <plugins>  
  2.   <plugin>  
  3.     <groupId>org.apache.felix.plugins<!---->groupId>  
  4.     <artifactId>maven-osgi-plugin<!---->artifactId>  
  5.     <extensions>true<!---->extensions>  
  6.     <version>0.3.0<!---->version>  
  7.     <configuration>  
  8.       <manifestFile>resources/manifest.mf<!---->manifestFile>  
  9.     <!---->configuration>  
  10.   <!---->plugin>  
  11. <!---->plugins>  

当然,这种配置就是告诉maven在对你的项目进行打包的时候直接使用resources/manifest.mf文件进行打包了,除此之外,如果你并不想一开始就指定一个MANIFAST.MF文件,而是将这个工作在打包过程交给felix去完成的话,那么你可以为MANIFAST.MF文件配置一些必要的属性,然后felix会根据这个属性来生成一个MANIFAST.MF一起打包到项目中,如:<o:p></o:p>

xml 代码
 
  1. <plugins>  
  2.   <plugin>  
  3.     <groupId>org.apache.felix.plugins<!---->groupId>  
  4.     <artifactId>maven-osgi-plugin<!---->artifactId>  
  5.     <extensions>true<!---->extensions>  
  6.     <version>0.3.0<!---->version>  
  7.     <configuration>  
  8.       <osgiManifest>  
  9.         <bundleName>My OSGi Application<!---->bundleName>  
  10.         <bundleDescription>An example bundle application<!---->bundleDescription>  
  11.         <bundleActivator>org.safehaus.bundle.Activator<!---->bundleActivator>  
  12.         <importPackage>org.osgi.service.log<!---->importPackage>  
  13.         <bundleVendor>Safehaus<!---->bundleVendor>  
  14.       <!---->osgiManifest>  
  15.     <!---->configuration>  
  16.   <!---->plugin>  
  17. <!---->plugins>  

显然,从<osgimanifest></osgimanifest>标签开始,你就是在手动的写一个MANIFAST.MF文件的相关OSGI配置信息了,此外你还可以加上一些打包配置来将指定的资源文件进行打包,如:

在<osgimanifest></osgimanifest>标签以内加入如下的设定

<_include>

       -target/classes/META-INF/details.bnd

<!---->

<_classpath>target/classes<!---->

第一种是告诉maven将一个指定文件打包

第二种是设定编译后类文件的存放位置

<o:p> </o:p>

这里提供一个实际运用的简要配置模板实例,大家可以稍作修改就可以直接使用了:

xml 代码
 
  1. <plugin>  
  2.     <groupId>org.apache.felix<!---->groupId>  
  3.     <artifactId>maven-bundle-plugin<!---->artifactId>  
  4.         <extensions>true<!---->extensions>  
  5.             <configuration>  
  6.                 <instructions>  
  7.                     <Bundle-Version>  
  8.                         ${project.version}  
  9.                     <!---->Bundle-Version>  
  10.                     <Bundle-SymbolicName>  
  11.                        $(replace;${project.artifactId};-;_);singleton:=true  
  12.                     <!---->Bundle-SymbolicName>  
  13.     <!---->  
  14.                     <_classpath>target/classes<!---->_classpath>  
  15.                     <Export-Package>  
  16.                        com.yourcompany.artifactId.*;version="${project.version}"  
  17.                     <!---->Export-Package>  
  18.                     <Import-Package>  
  19.                         org.springframework.test;resolution:=optional,*  
  20.                     <!---->Import-Package>  
  21.                     <DynamicImport-Package>*<!---->DynamicImport-Package>  
  22.                         <!---->  
  23.                     <_include>  
  24.                         -target/classes/META-INF/details.bnd  
  25.                     <!---->_include>  
  26.                     <Include-Resource>  
  27.                         <!---->  
  28.                         <!---->Include-Resource>  
  29.                     <!---->instructions>  
  30.                 <!---->configuration>  
  31.             <!---->plugin>  

以上仅是我在实际项目中打包时候的设置过得一个样例,仅供大家参考,大家可以根据实际项目信息来自行设置自己的项目描述。具体的其他OSGI相关配置所应对应设定什么样的标签的内容,请参考apache官网(http://cwiki.apache.org/FELIX/osgi-plugin-for-maven-2.html)提供的参考。

配置完毕后,在当前项目目录下,运行maven的package命令,就能得到一个由你自己自配置的一个OSGI bundle了。

第三种方式:

利用OPS4J组织提供的一个叫Pax的工具来进行OSGI bunder的构建. 这里需要说的就是,我什么要用PAX来构建一个OSGI工程呢,eclipse不是已经有很好的OSGI开发支持了么,这里要说的就是,PAX构建的OSGI工程并不是单单某个OSGI bundle的开发,而是,PAX会主动的为你创建一个基本的OSGI环境,这个环境包括一些OSGI的基础包,你可以通过PAX的命令来启动这个OSGI环境,同时PAX也会将其管理的一些Bundle进行打包实时发布到这个环境中,这样不但可以按需的打包bundle,还可以迅速的构建一个OSGI环境来进行调试了。这里我简要的说一下PAX的使用方法,PAX是一个专门用来构建和管理OSGI 环境的一个工具,从官网的介绍我们可以看到,他主要提供pax-create-project pax-add-repository pax-create-bundle pax-import-bundle pax-embed-jar pax-wrap-jar pax-move-bundle pax-remove-bundle  等几大脚本命令来,完成一些儿OSGI环境的构建工作。这里我只简要介绍一下我平时几条最常用的命令,通过这些命令的介绍来大概的给大家讲解一下pax的使用方式。
首先从官方down到pax的最新包

Down好后,进行解压,解压完毕后,为了在命令行中使用,你需要将其中的bin目录设置到环境变量PATH中,设置完毕后你就可以到你希望创建项目的目录,利用PAX提供的第一条命令pax-create-project来创建一个OSGI工程。创建好这个工程后,我们就可以利用maven的命令来启动这个OSGI的环境工程,pax会为帮我们构建一个基础OSGI环境,以及将test工程中的bundle工程打成bundle部署到这个环境中去,当然我们现在还为在这个工程中创建任何bundle工程,所以,我们启动的只是一个最小的OSGI环境。

<o:p> </o:p>

接下来我们在这个PAX的工程中来创建我们bundle工程,pax提供四种命令来创建bundle的打包工程pax-create-bundle pax-import-bundle pax-embed-jar pax-wrap-jar

pax-create-bundle是完全用pax创建一个符合OSGI规范bundle项目,最后在执行mvn clean install pax:provision 命令时,pax会把这个工程打成一个bundle然后部署到它的OSGI环境中去。

pax-import-bundle 则是直接导入一个符合OSGI规范的bundle,这样在启动OSGI环境的时候pax会去指定group(-g),指定的artifactId(-a)和指定的version(-v)的repository下去搜索指定的OSGI bundle并将其导入到环境中。

pax-wrap-jar 通过该命令则可以利用pax将一个jar包打包成一个符合OSGI规范的bundle,pax能够对这个jar包进行分析,找出其中的依赖关系,并生成相关的MANIFAST.MF文件。再吧这个bundle部署到之前的OSGI环境中去。

在项目中我最常用的就是以上三条,其余的命令,以及这些命令的具体使用方法大家可以参考官方网站给出的示例。

接下来,我就利用pax-create-bundle命令来创建一个bundle工程,来给大家演示一下。

先选择到一个需要创建工程的目录下

看看一个test工程生成了,可以看到pax实际上给我们生成了一些初始的pom,大家可以打开看看

接下来我们马上来跑下这个工程。看看pax会给我们带来什么效果


先进入到text目录,大家可以打开pax生成的pom.xml看看,实际上pax是把自己作为了一个maven的插件来供maven调用,这里我们用maven来运行这个工程,命令是mvn clean install pax:provision
<o:p> </o:p>


可以看到pax为我们启动了一个OSGI运行环境,我们用ss命令来查看但前环境中的bundle信息


呵呵,果然是一个最小的OSGI环境。

接下来我输入命令来创建一个bundle工程:

pax-create-bundle -g com.zhoufu.demo -a create_bundle_demo -v 1.0,接下来看看pax会为我们产生什么



可以看到在test环境工程下,pax为我们创建了一个符合OSGI规范的create_bundle_demo工程


<o:p> </o:p>

接下来我们就可以直接对这个工程进行maven(mvn eclipse:eclipse)使其成为一个eclipse可以识别的工程,来用eclipse对其进行开发了。

当开发完毕后,我们就可以直接利用之前的pax:provision命令来启动这个环境的工程,pax会依次由test目录下的pom来检索相应的bundle工程,按照各个bundle中pom的配置对其进行OSGI的bundle打包工作,打成bundle后再将其部署到启动的OSGI环境中去。

现在,我们看看我们刚才生成的那个工程里的POM文件

xml 代码
 
  1. xml version='1.0' encoding='UTF-8' ?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
  3.   
  4.   <parent>  
  5.     <relativePath>../poms/compiled/<!---->relativePath>  
  6.     <groupId>org.ops4j.example.test.build<!---->groupId>  
  7.     <artifactId>compile-bundle<!---->artifactId>  
  8.     <version>0.1.0-SNAPSHOT<!---->version>  
  9.   <!---->parent>  
  10.   
  11.   <properties>  
  12.     <bundle.package>com.zhoufu.demo<!---->bundle.package>  
  13.   <!---->properties>  
  14.   
  15.   <modelVersion>4.0.0<!---->modelVersion>  
  16.   <groupId>org.ops4j.example.test.bundles<!---->groupId>  
  17.   <artifactId>create_bundle_demo<!---->artifactId>  
  18.   <version>1.0<!---->version>  
  19.   
  20.   <name>${project.artifactId} [${bundle.package}]<!---->name>  
  21.   
  22.   <packaging>bundle<!---->packaging>  
  23.   
  24.   <build>  
  25.     <plugins>  
  26.       <plugin>  
  27.         <artifactId>maven-dependency-plugin<!---->artifactId>  
  28.       <!---->plugin>  
  29.       <plugin>  
  30.         <groupId>org.ops4j.pax.maven<!---->groupId>  
  31.         <artifactId>maven-bundle-plugin<!---->artifactId>  
  32.       <!---->plugin>  
  33.       <plugin>  
  34.         <groupId>org.ops4j.pax.construct<!---->groupId>  
  35.         <artifactId>maven-pax-plugin<!---->artifactId>  
  36.       <!---->plugin>  
  37.     <!---->plugins>  
  38.   <!---->build>  
  39.   
  40. <!---->project>  

非常好,当然,这只是个初始的POM,随着bundle的开发,这里面肯定有一些关于bundle的依赖配置,需要增加到MANIFAST.MF文件中去,那么怎么告诉pax打包的时候生成什么样的MANIFAST.MF文件呢,其实也就是在org.ops4j.pax.maven这个plugin的配置段里进行配置好了。如下,我从项目中,提取了一段配置的模板,大家可以参考参考

xml 代码
 
  1. <plugin>    
  2.                     <groupId>org.ops4j.pax.maven<!---->groupId>    
  3.                     <artifactId>maven-bundle-plugin<!---->artifactId>    
  4.                     <extensions>true<!---->extensions>    
  5.                     <configuration>    
  6.                         <instructions>    
  7.                             <Bundle-Version>    
  8.                                 这里是bundle的Version    
  9.                             <!---->Bundle-Version>    
  10.                             <Bundle-SymbolicName>    
  11.                                 这里是Bundle-SymbolicName的配置    
  12.                             <!---->Bundle-SymbolicName>    
  13.                             <!---->    
  14.                             <_classpath>    
  15.                              …    
  16.                             <!---->_classpath>    
  17.                             <Export-Package>    
  18.                             …    
  19.                             <!---->Export-Package>    
  20.                             <Import-Package>    
  21.                             …    
  22.                             <!---->Import-Package>    
  23.                             <Bundle-ClassPath>    
  24.                                 …    
  25.                             <!---->Bundle-ClassPath>    
  26.                             <Bundle-Activator>    
  27.                                 …    
  28.                             <!---->Bundle-Activator>    
  29.                             <DynamicImport-Package>*<!---->DynamicImport-Package>    
  30.                             <!---->    
  31.                             <_include>    
  32.                                 -target/classes/META-INF/details.bnd    
  33.                             <!---->_include>    
  34.                         <!---->instructions>    
  35.                     <!---->configuration>    
  36.                 <!---->plugin>   

看见了吧,其实这个跟之前的利用maven插件来打包的方式很相似,也是把配置写到pom之中,再由插件去进行打包,只不过这里用的插件是pax。

<o:p> </o:p>

假设我们的bundle开发好了,我们再把之前的那个test工程跑一下看看

在test目录下敲mvn clean install pax:provision命令。看看结果<o:p></o:p>

<u1:p> </u1:p><o:p></o:p>

看见没,在我们原来的环境中多了一个新建的这个

 

 

原创粉丝点击