使用NetBeans6开发OSGi应用(2)——SecondOSGi[88250原创]

转载请保留作者信息:

作者:88250

Blog:http:/blog.csdn.net/DL88250

MSN & Gmail & QQ:DL88250@gmail.com


摘要

上一次,我们了解了OSGi的背景并使用NetBeans6,基于Knopflerfish(OSGi的一个RI) 完成了第一个OSGi应用——FirstOSGi。这一次,我们将对OSGi进行深入一点学习——SecondOSGi,让我们掌握Bundles之间的调用!

准备

上一次 :-)

开工:

1. 创建工程

打开NetBeans6 IDE,创建两个普通的Java App——SecondOSGi、SecondOSGiClient。把KF下的Sources拷贝到两个工程下(记得加入asm3.0的Jar):



在SecondOSGiClient工程的demo包下的两个Java文件(Demo.java, DemoFactory.java)与SecondOSGi工程demo包下的完全一样,这里是懒得发布编译好的class byte file给Client了,直接给的接口源文件。

2. 编写manifest.mf

把工程View切换到Files,改写manifest.mf如下:





关于manifest.mf里各种properties就不罗嗦了,有很多文档可以参考 :-)

3. 编写Activator

下面逐一给出源文件,一一对应上面工程结构图。

service提供者,即SecondOSGi工程下的:

/*
*@(#)Demo.java
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion3oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNULibraryGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.
*/
package secondosgi.service.demo;


/**
*Asimpledemoservice.
*
@author 88250
*
@version 1.0.0.0,Feb14,2008
*/
public interface Demo{

/**
*Addtwointegersandreturntheresult.
*
@param a
*
@param b
*
@return
*/
public int add( int a, int b);
}

/*
*@(#)DemoFactory.java
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion3oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNULibraryGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.
*/
package secondosgi.service.demo;

/**
*<b>Another</b>verysimpledemoserviceAPI.
*<p>
*Theintentionsofthisinterfaceclassistoshowthatdifferentbundles
*willgetdifferentinstancesofaservice,bythemeansofa
*ServiceFactory.
*</p>
*
@author 88250
*
@version 1.0.0.0,Feb14,2008
*/
public interface DemoFactory{

/**
*Sayhello.
*/
void hello();
}

/*
*@(#)DemoImpl.java
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion3oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNULibraryGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.
*/
package secondosgi.service.demo.impl;

import secondosgi.service.demo.Demo;

/**
*ImplementationoftheDemoservice.
*
@author 88250
*
@version 1.0.0.0,Feb14,2008
*/
public class DemoImpl implements Demo{

public int add( int a, int b){
return a + b;
}
}

/*
*@(#)DemoFactoryImpl.java
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion3oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNULibraryGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.
*/
package secondosgi.service.demo.impl;

import secondosgi.service.demo.DemoFactory;
import org.osgi.framework.Bundle;

/**
*ImplementationoftheDemoFactoryservice.Theintentionsofthis
*classistoshowthatdifferentbundleswillgetdifferentinstances
*ofaservice,bythemeansofaServiceFactory.
*
@author 88250
*
@version 1.0.0.0,Feb14,2008
*/
public class DemoFactoryImpl implements DemoFactory{

private Bundleb;

/**
*Constructorwithargument.
*
@param ba<code>Bundle</code>
*/
public DemoFactoryImpl(Bundleb){
this .b = b;
}

public void hello(){
System.out.println(
" Hellobundle# " + b.getBundleId());
}
}

很关键的Activator,实现服务的注册,注销:
/*
*@(#)Activator.java
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion3oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNULibraryGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.
*/
package secondosgi.service.demo.impl;

import secondosgi.service.demo.Demo;
import secondosgi.service.demo.DemoFactory;
import java.util.Hashtable;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;

/**
*ActivatorwhichcreatesandregistersaDemo1service.
*
@author 88250
*
@version 1.0.0.0,Feb14,2008
*/
public class Activator implements BundleActivator{

private Demodemo;

public void start(BundleContextbc){
System.out.println(
" start " + getClass().getName());
demo
= new DemoImpl();
bc.registerService(Demo.
class .getName(),
demo,
new Hashtable());

// CreateaservicefactoryforDemoFactoryimplementations
ServiceFactoryfactory = new ServiceFactory(){

Hashtableservices
= new Hashtable();
// Willgetcalledwhenabundlerequestaservice
@SuppressWarnings( " unchecked " )
public ObjectgetService(Bundleb,
ServiceRegistrationreg){
System.out.println(
" getfrom " + b.getBundleId());

// Createwhennecessary
DemoFactoryimpl = (DemoFactory)services.get(b);
if (impl == null ){
impl
= new DemoFactoryImpl(b);
services.put(b,impl);
}
return impl;
}

// willgetcalledwhenabundleungetsaserviceorstops
public void ungetService(Bundleb,
ServiceRegistrationreg,
Objectservice){
System.out.println(
" ungetfrom " + b.getBundleId());
services.remove(b);
}
};

// NotehowfactoryonlyimplementsServiceFactory,
// butwestillregisterasDemoFactory1service
bc.registerService(DemoFactory. class .getName(),
factory,
new Hashtable());
}

public void stop(BundleContextbc){
System.out.println(
" stop " + getClass().getName());

demo
= null ;
}
}

client角色,服务使用者,即SecondOSGiClient工程下的(Demo,DemoFactory两个接口同服务提供的)。
在这个Activator里,我们实现了服务的查找、调用、服务提供者状态的监听:
/*
*@(#)Activator.java
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion3oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNULibraryGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.
*/
package secondosgi.service.client.impl;

import secondosgi.service.demo.Demo;
import secondosgi.service.demo.DemoFactory;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;

/**
*Activatorwhichregistersalistenerfor,andtest,anyDemoservice.
*
@author 88250
*
@version 1.0.0.0,Feb14,2008
*/
public class Activator implements BundleActivator,ServiceListener{

private static BundleContextbc;

private ServiceListenerlistener;

public void start(BundleContextbc){
System.out.println(
" start " + getClass().getName());
Activator.bc
= bc;

try {
// FilterthatmatchesallDemoservices
Stringfilter = " (objectclass= " + Demo. class .getName() + " ) " ;

// FetchallregisteredDemoservices
// andtestthemmanually
ServiceReference[]srl =
bc.getServiceReferences(Demo.
class .getName(),filter);
for ( int i = 0 ;srl != null && i < srl.length;i ++ ){
testService(srl[i]);
}

// ...andcatchallnewlyregistedonestoo.
bc.addServiceListener(listener,filter);
}
catch (Exceptione){
// soundsunlikely,butfiltersyntaxerrorsareeasytowrite.
e.printStackTrace();
}

testServiceFactory();
}

void testServiceFactory(){
// Trytogetareferencetotheserviceproducedbyafactory
ServiceReferencefactorySR = bc.getServiceReference(DemoFactory. class .getName());
if (factorySR != null ){
DemoFactorydf
= (DemoFactory)bc.getService(factorySR);
if (df != null ){
// Differentbundleswillgetdifferentprintouts
df.hello();
}
}
}

void testService(ServiceReferencesr){
Demodemo
= (Demo)bc.getService(sr);
int r = demo.add( 140 , 1 );

System.out.println(
" Testing " + demo + " ,result= " + r);

// ..returntheobjecttobenice
bc.ungetService(sr);
}

public void stop(BundleContextbc){
System.out.println(
" stop " + getClass().getName());
Activator.bc
= null ;
}

public void serviceChanged(ServiceEventevent){
ServiceReferencesr
= event.getServiceReference();

// justprintsomeinfoandcalltestService()on
// allregisteredDemoservices
switch (event.getType()){
case ServiceEvent.REGISTERED:
System.out.println(
" GotDemoservice " );
testService(sr);
break ;
case ServiceEvent.UNREGISTERING:
System.out.println(
" LostDemoservice " );
break ;
case ServiceEvent.MODIFIED:
System.out.println(
" ModifiedDemoservice " );
break ;
default :
break ;
}
}
}

4. 测试

打开KF控制中心:

daniel@daniel-laptop:~/Work/knopflerfish_osgi_2.0.4/knopflerfish.org/osgi$java-jarframework.jar


打开构建好的SecondOSGi.jar以及SecondOSGiClient.jar,运行!



总结

这一次,我们对OSGi的了解更深了一步。

从设计的角度:一个可扩展的Service-Oriented组件服务模型

从开发的角度:我们发布接口给客户,实现了“针对接口编程”的OO核心实践

不足之处

我们一直都是在KF的控制台下启动的应用,如何做成独立的(standalone)可运行的Jar发布呢?
1. 在命令行下启动OSGi框架
首先,编写一个启动参数文件:secondosgi.xargs
-launch
-istart/home/daniel/Work/Sources/Java/SecondOSGi/dist/SecondOSGi.jar
-istart/home/daniel/Work/Sources/Java/SecondOSGiClient/dist/SecondOSGiClient.jar

然后,进入KF的安装目录,启动我们的应用:


现在,我们只是脱离了KF的图形界面控制中心,在命令行下面启动的KF框架,并把SecondOSGi与SeondOSGiClient安装运行在KF框架里。一切的主动权还是在KF手里。
结合以前JavaEE的实践,JSP/Servlets,EJBs不都是被控制在容器(container)里的吗?
不过,话又说回来了,我希望自己的框架应用构建于OSGi之上,而不是之内。
之内的部分应该是可扩展的Plug-ins部分,让OSGi作为底层框架,为我们提供稳定的插件机制。
之外的部分应该是我们应用的框架,构建在OSGi之上。对OSGi做一个封装,就KF而言,就是封装它的命令接口,让我们的框架可以对插件随时安装、卸载、运行、停止、更新。。。。
当然,以上是个设想,学习OSGi第二天的设想。。。。
总之不足的地方很多,要把这个示例慢慢演化成正真具有价值的应用可能还需要一些时间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值