`
ssydxa219
  • 浏览: 609483 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

osgi

    博客分类:
  • osgi
 
阅读更多
  •   如何用maven创建osgi项目
  •   如何启动osgi框架
  •   如何在osgi外部与osgi框架通信
  •   如何应用jndi配置资源引用
  •   如何发布osgi服务
  •   如何创建基于osgi的web应用项目
1.用maven创建osgi项目
 
  用maven的目的是使开发相率更高,而且不需要自己修改manifest.mf文件,用maven插件即可自动完成创建manifest并打包。创建这种项目的要求如下:
   项目包类型为:<packaging>bundle</packaging>
   要使用maven自动创建manifest.mf文件,需要插件maven-bundle-plugin,配置如下:
  <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>1.4.0</version>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>${pom.groupId}.${pom.artifactId}</Bundle-SymbolicName>
                        <Bundle-Name>${pom.name}</Bundle-Name>
                        <Bundle-Version>${pom.version}</Bundle-Version>
                        <Bundle-Activator>com.javaworld.sample.tomcat.webActivator</Bundle-Activator>
                        <Export-Package>com.javaworld.sample.tomcat</Export-Package>
                        <Import-Package>
                            org.osgi.framework
                        </Import-Package>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
  使用maven-bundle-plugin请参考:http://wso2.org/library/tutorials/develop-osgi-bundles-using-maven-bundle-plugin ,配置好后在项目目录下执行mvn install即可
同时还要引用osgi框架支持依赖包:
    <dependencies>
            <dependency>
            <groupId>org.eclipse.osgi</groupId>
            <artifactId>framework</artifactId>
            <version>3.4.2.R34x_v20080826</version>
            <type>jar</type>
            <scope>provided</scope>
        </dependency>
    </dependencies>
 注意这里的type和scope,这种用法不仅表名bundel项目可以引用第三方bundle项目,普通项目也可以。下面将会看到。

2.启动osgi框架,并在外部与osgi框架通信
 这里用Equinox OSGi框架,让EquinoxContainer 实现接口OsgiServices 并实现OsgiContainable 的start和stop方法。对于框架的启动和停止,我们放在tomcat启动和停止时触发。
首先用maven创建普通的项目,在pom中添加依赖
    <dependencies>
        <dependency>
            <groupId>apache-tomcat</groupId>
            <artifactId>catalina</artifactId>
            <version>5.5.12</version>
            <type>jar</type>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.osgi</groupId>
            <artifactId>services</artifactId>
            <version>3.1.200.v20071203</version>
            <type>jar</type>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.osgi</groupId>
            <artifactId>framework</artifactId>
            <version>3.4.2.R34x_v20080826</version>
            <type>jar</type>
            <scope>provided</scope>
        </dependency>
    </dependencies>

public interface OsgiServices {

    public Object getOSGiService(String serviceName);

    public Class<?> getBundleClass(String bundleName, String className)
            throws ClassNotFoundException;
}

//OsgiContainable 扩展OsgiServices 并提供start和stop接口
public class EquinoxContainer implements OsgiContainable {
    private static Logger log = Logger
            .getLogger(EquinoxContainer.class.getName());

    private static BundleContext context;

    private static String equinoxHome;

    private static EquinoxContainer instance;

    private EquinoxContainer() {
    }

    public static EquinoxContainer getInstance() {
        if (instance == null) {
            instance = new EquinoxContainer();
        }
        return instance;
    }

    public void start() throws Exception {

        configFramework();

        EclipseStarter.run(new String[] { "-console" }, null);
        // get BundleContext
        context = EclipseStarter.getSystemBundleContext();
    }

    private void configFramework() {
        String catalinaHome = System.getProperty("catalina.home");
        log.info("The catalina home is " + catalinaHome);
        File filePath = new File(catalinaHome, "/osgi/equinox");
        if (!filePath.exists()) {
            throw new IllegalStateException(
                    "Can not find Equinox runtime on the specified the directory. "
                            + catalinaHome + "/osgi/equinox");
        }

        equinoxHome = filePath.getAbsolutePath();
        log.info("The osgi home is " + equinoxHome);

        filePath = new File(filePath, "plugins");
        String bundlePath = filePath.getAbsolutePath();
        log.info("The bundle home is " + bundlePath);
        // set the bundle home
        FrameworkProperties.setProperty("osgi.syspath", bundlePath);

        filePath = new File(equinoxHome, "configuration");
        String confHome = filePath.getAbsolutePath();
        // set the configuration home
        FrameworkProperties.setProperty("osgi.configuration.area", confHome);
        log.info("The configuration home is " + confHome);
        //config.ini中至少需要配置osgi.bundles需要启动的bundles
        Properties prop = loadConfigProperties(confHome, "/config.ini");
        setSystemProperties(prop);

        // set the framework properties
        FrameworkProperties.setProperty("osgi.noShutdown", "true");
        FrameworkProperties.setProperty("eclipse.ignoreApp", "true");
        FrameworkProperties.setProperty("osgi.bundles.defaultStartLevel", "4");
    }
    。。。
}
为了让tomcat等启动时执行EquinoxContainer 的start和stop,需要实现LifecycleListener接口,并在tomcat server.xml文件中配置Listener :
<Listener className="com.javaworld.sample.tomcat.osgi.OsgiLifecycleListener" osgiType="Equinox"/>

public class OsgiLifecycleListener implements LifecycleListener {

    private static Logger log = Logger.getLogger(OsgiLifecycleListener.class
            .getName());

    private static OsgiLifecycleListener listener;

   
    private String osgiType = "Equinox";

    private OsgiContainable osgiContent = null;

    public OsgiLifecycleListener() {
    }

    public static OsgiLifecycleListener getInstance() {
        return listener;
    }

    @Override
    public void lifecycleEvent(LifecycleEvent event) {
        try {
            if (Lifecycle.INIT_EVENT.equals(event.getType())) {
                log.info("Initializing osgi content. osgi type is " + osgiType);
                initContent();
                log.info("The osgi content initialized. osgi type is "
                        + osgiType);
            } else if (Lifecycle.START_EVENT.equals(event.getType())) {
                log.info("Starting osgi service.");
                osgiContent.start();
                log.info("The osgi service started.");
            } else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
                log.info("Stopping osgi service.");
                osgiContent.stop();
                log.info("The osgi service stopped.");
            }
        } catch (Exception e) {
            log.info(e.getMessage());
            System.exit(-1);
        }
    }

    private void initContent() throws Exception {
        listener=this;
        log.info("listener"+listener.toString());
        osgiContent = OsgiContainerFactory.getInstance().getOsgiContent(osgiType);
    }
    。。。。
}
随着tomcat的启动将执行OsgiLifecycleListener,并通过OsgiLifecycleListener启动osgi框架,后者将完成bundles的安装和服务的注册等。

3。在osgi外部与osgi框架通信
OSGi通过BundleContext来获取OSGi服务,因此想在OSGi容器外获取OSGi服务,首要的问题就是要在OSGi容器外获取到BundleContext,EclipseStarter 中 提供了一个getSystemBundle- Context的方法,通过这个方法可以轻松拿到BundleContext,而通过BundleContext则可以轻易拿到OSGi服务的实例。不过 这个时候要注意的是,如果想执行这个OSGi 服务实例的方法,还是不太好做的,因为容器外的classloader和OSGi服务实例的class所在的classloader并不相同,因此不太好 按照java对象的方式直接去调用,更靠谱的是通过反射去调用。 如果想在容器外获取到OSGi容器里插件的class,一个可选的做法是通过BundleContext获取到Bundle,然后通过Bundle 来加载 class,采用这样的方法加载的class就可以保证是相同的。
   
    public  static Object getOSGiService(String serviceName) {
        ServiceReference serviceRef = context.getServiceReference(serviceName);
        if (serviceRef == null)
            return null;
        return context.getService(serviceRef);
    }
   
    public  static Class<?> getBundleClass(String bundleName, String className)
            throws Exception {
        Bundle[] bundles = context.getBundles();
        for (int i = 0; i < bundles.length; i++) {
            if (bundleName.equalsIgnoreCase(bundles[i].getSymbolicName())) {
                return bundles[i].loadClass(className);
            }
        }
        return null;
    }
在实现了OSGi容器外与OSGi交互之后,通常会同时产生一个需求,就是在OSGi容器内的插件要加载OSGi容器外的类,例如OSGi容器内提 供了一个mvc框架,而Action类则在OSGi容器外由其他的容器负责加载,那么这个时候就会产生这个需求了,为了做到这点,有一个比较简单的解决方 法,就是编写一个Bundle,在该Bundle中放置一个允许设置外部ClassLoader的OSGi服务,例如:

Java代码  
  1. public   class  ClassLoaderService{    
  2.     public   void  setClassLoader(ClassLoader classloader);    
  3. }   
 

      基于上面的方法,在外部启动Equinox 的类中去反射执行ClassLoaderService这个OSGi服务的setClassLoader方法,将外部的classloader设置进来, 然后在OSGi容器的插件中要加载OSGi容器外的类的时候就调用下面这个ClassLoaderService去完成类的加载。


 4.应用jndi配置资源引用
 上面知道要在osgi外面引用osgi服务或者osgi类,唯一可行的办法是获取BundleContext,这点是可以在osgi框架获取,这样一来BundleContext就是我们与osgi通信的桥梁了,OsgiServices 也是通过此桥梁与osgi框架通信,为方便对OsgiServices 的获取,现在将OsgiServices配置到jndi。同样把Resource添加到server.xml的Host标签中:
    <Resource name="osgi/services" auth="Container"
       type="com.javaworld.sample.tomcat.osgi.OsgiServices"
       factory="com.javaworld.sample.tomcat.osgi.OsgiServicesObjectFactory" />
在tomcat 的web.xml中添加Resource引用:
    <resource-env-ref>
       <description>osgi services</description>
       <resource-env-ref-name>osgi/services</resource-env-ref-name>
       <resource-env-ref-type>
           com.javaworld.sample.tomcat.osgi.OsgiServices
       </resource-env-ref-type>
    </resource-env-ref>

public class OsgiServicesObjectFactory implements ObjectFactory {

    private static Logger log = Logger.getLogger(OsgiServicesObjectFactory.class
            .getName());

    private OsgiServices osgiServices;

    @Override
    public Object getObjectInstance(Object obj, Name name, Context nameCtx,
            Hashtable<?, ?> environment) throws Exception {

        Map<String, String> attMap = new HashMap<String, String>();
        // Customize the bean properties from our attributes
        Reference ref = (Reference) obj;
        Enumeration<RefAddr> addrs = ref.getAll();
        while (addrs.hasMoreElements()) {
            RefAddr addr = addrs.nextElement();
            String attrName = addr.getType();
            String value = (String) addr.getContent();
            log.info("the attribute is (" + attrName + " == " + value + ")");
            attMap.put(attrName, value);
        }
        log.info("getObjectInstance called.");
        osgiServices=OsgiLifecycleListener.getInstance().getOsgiServices();
        return osgiServices;
    }
}
 5. 发布osgi服务
public interface HelloService {
    public String sayHello();
}

public class webActivator implements BundleActivator {
    ServiceRegistration serviceRegistration;

   
    public void start(BundleContext bundleContext) {
        serviceRegistration = bundleContext.registerService(
                HelloService.class.getName(), new HelloServiceImpl(),
                new Properties());
    }

   
    public void stop(BundleContext bundleContext) {
        serviceRegistration.unregister();
    }
}

 6.创建基于osgi的web应用项目
创建<packaging>war</packaging>web项目,添以下类:
public class TomcatWebCall {
    public static String invokeService() {
        try {
            HelloService service = OsgiServiceFactory.getOsgiService(
                    "osgi/services", HelloService.class);
            return service.sayHello();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            e.printStackTrace();
        }
        return null;
    }
}

public class OsgiServiceFactory {
    public static <T> T getOsgiService(String jndiName,Class<T> clazz) {
        OsgiServices services = (OsgiServices) Utils.lookup(jndiName);
        OsgiServiceInvocationHandler handler = new OsgiServiceInvocationHandler(
                services, clazz.getName());
        return Utils.getProxyObject(clazz,handler);
    }

    public class OsgiServiceInvocationHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        try {
            Object service = services.getOSGiService(servicName);
            if (service == null) {
                throw new IllegalServiceException("Cann't find out osgi service:"
                        + servicName);
            }
           
            Method[] methods = service.getClass().getDeclaredMethods();
            for (Method meth : methods) {
                if (meth.getName().equals(method.getName())) {
                    return meth.invoke(service, args);
                }
            }
            。。。
         }
    }
}

public class Utils {
   
    private static final String CONTAINER_PREFIX = "java:comp/env/";
   
    public static <T> T getProxyObject(Class<T> clazz, InvocationHandler handler) {
        Object o = Proxy.newProxyInstance(clazz.getClassLoader(),
                new Class[] { clazz }, handler);
        return clazz.cast(o);
    }
   
    private static String convertJndiName(String jndiName) {
        if (!jndiName.startsWith(CONTAINER_PREFIX)
                && jndiName.indexOf(':') == -1) {
            jndiName = CONTAINER_PREFIX + jndiName;
        }
        return jndiName;
    }
   
    public static Object lookup(String jndiName) {
        String convertedName = convertJndiName(jndiName);
        Object jndiObject = null;
        try {
            Context context = new InitialContext();
            jndiObject = context.lookup(convertedName);
        } catch (NamingException e) {
            throw new IllegalServiceException(
                    "The JNDI OSGi services name is error.", e);
        } catch (Exception e) {
            throw new IllegalServiceException(
                    "The JNDI OSGi services can not be initialized.", e);
        }

        return jndiObject;
    }
}
简单的jsp测试:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@page import="com.javaworld.sample.tomcat.TomcatWebCall"%>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
            <title>Demo invoke HelloService</title>
    </head>
    <body>
        <%=TomcatWebCall.invokeService() %>
    </body>
</html>
分享到:
评论

相关推荐

    osgi介绍osgi介绍

    osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍

    osgi-resource-locator-1.0.1-API文档-中文版.zip

    赠送jar包:osgi-resource-locator-1.0.1.jar; 赠送原API文档:osgi-resource-locator-1.0.1-javadoc.jar; 赠送源代码:osgi-resource-locator-1.0.1-sources.jar; 赠送Maven依赖信息文件:osgi-resource-locator...

    OSGi与Equinox 创建高度模块化的Java系统

    OSGi与Equinox:创建高度模块化的Java系统》分为四个部分。第一部分主要介绍了OSGi和Equinox,以及OSGi标准的Eclipse实现;第二部分采用非正式教程的方式教给读者如何从零开始构建真实的Toast应用,针对每一个步骤都...

    OSGI原理与最佳实践

    资源名称:OSGI原理与最佳实践内容简介:国内第一本OSGi图书OSGi国内推广者林昊多年经验的结晶涵盖OSGi从入门到深入的知识体系引领OSGi国内研究和普及本书基于作者多年使用OSGi的经验而编写,涵盖了OSGi从入门到深入...

    《OSGi实战》完整中文版

    《 OSGi实战》是学习OSGi的全面指导,利用与架构和开发人员相关的示例清楚地讲解OSGi概念,同时探讨了很多实践场景和技术,阐述了开发人员有多需要OSGi,怎么将OSGi嵌入其他容器中,将遗留系统移入OSGi的最佳实践,...

    OSGi.NET框架 Documentation

    本文档主要针对OSGi.NET模块化框架使用进行了描述 OSGi.NET框架是一个参照了OSGi规范的模块化管理框架。框架为应用程序(组件(bundle))提供了一个标准环境。整个框架可以划分为一些层次: 1.运行环境 2.模块...

    Equinox OSGI ServletBridge 原理与实践.rar

    OSGI 在 J2EE 环境下的应用越来越广泛,目前在 Servlet 应用中使用 OSGI 有两种方式:Servlet Container in OSGI 和 OSGI in Servlet Container. 前一种:和普通的 OSGI bundle 开发差不多,而后一种:Equinox 提供...

    osgi实战(pdf超请版)

    本篇 Opendoc 按照学习开源框架的基本流程进行编写,从体验 OSGI 到基于 OSGI 框架的实战,到深入 OSGI,完成对于 OSGI 从入门到深入学习的过程,最后对于 OSGI 的现状和发展发表些自己的看法和思考,限于笔者的水平以及...

    OSGi原理与最佳实践

    本书基于作者多年使用OSGi的经验而编写,涵盖了OSGi从入门到深入的知识体系,从OSGi的简介开题,介绍OSGi的作用及基本概念;其后进入OSGi实战,结合实例讲解如何基于OSGi框架编写模块化、动态化的各种Java应用;最后...

    osgi.enterprise-6.0.0

    The OSGi Enterprise Expert Group (EEG) is chartered to define the technical requirements and specifications to tailor and extend the OSGi framework to address information technology software ...

    OSGI原理最佳实践(包含源代码)

    是一本适合新接触OSGI开发学习的一本很好的书,本书介绍了Equinox, Spring-DM和Felix这三个常用的OSGi容器的使用、开发、以及WebApplication的开发部署;介绍了OSGi的规范和Core Framework和Layer。包含书中的用例源...

    OSGI 实例eclipse插件开发

    OSGI 实例 eclipse 插件开发

    OSGi原理与最佳实践pdf下载(完整版)

    OSGI原理与最佳实践的完整版,共12章 第1 章OSGi 简介 第2 章OSGi 框架简介 第3 章基于Spring-DM 实现Petstore 第4 章基于Apache CXF 实现分布式Petstore 第5 章构建OSGI Bundle Repositor'y 第6 章OSGi 规范解读 ...

    osgi-resource-locator-1.0.1-API文档-中英对照版.zip

    赠送jar包:osgi-resource-locator-1.0.1.jar; 赠送原API文档:osgi-resource-locator-1.0.1-javadoc.jar; 赠送源代码:osgi-resource-locator-1.0.1-sources.jar; 赠送Maven依赖信息文件:osgi-resource-locator...

    OSGi+SpringMVC+Spring+Hibernate企业应用框架

    辛苦研究了一个多月,终于搭建成了一个可用于实际应用开发的OSGI-WEB框架,采用OSGi+SpringMVC+Spring+Hibernate+Virgo技术,鉴于此类技术架构甚少,特提供出来供大家参考。 使用步骤: 一、下载STS搭建Osgi开发...

    (OSGi In Practice_20091217

    The Java™ programming language is one of the most popular languages today ...That module system is called OSGi. OSGi is nothing more nor less than the way to build modular applications in Java.

    osgi.residential-6.0.0

    When the OSGi Alliance started in 1998, the focus was in residential gateways the organization's name contained the word gateway before it was changed to the OSGi Alliance. Since that time, OSGi ...

    Felix_OSGi实作

    Felix_OSGi实作,介绍最流行的OSGI framwork-Felix的好文档

    OSGI原理与最佳实践(扫描版,带目录).pdf

    OSGi原理与最佳实践基于作者多年使用0SGi的经验而编写,涵盖了0SGi从/kfqN深入的知识体系,从OSGi的简介开始,介绍OSGi的作用及基本概念;其后进入OSGi实战,结合实例讲解如何基于OSGi框架编写模块化、动态化的各种...

Global site tag (gtag.js) - Google Analytics