2011年5月20日 星期五

OSGI Tutorial (3) - how to get BundleContext in spring DM and to get other bundle.

首先建立2個Bunlde
OSGIApp.Sample.OSGiSample
OSGIApp.Sample.OSGiSample2

OSGIApp.Sample.OSGiSample2 比較單純, 只包含了一隻class, 如下圖

然後是MANIFEST.mf檔,
Manifest-Version: 1.0
Export-Package: com.sample.OSGiSample2;version="1.0.0"
Unversioned-Imports: *
Build-Jdk: 1.6.0_24
Built-By: momo
Bundle-Version: 1.0.0
Tool: Bnd-1.15.0
Bnd-LastModified: 1305872257329
Bundle-Name: Spring OSGi Bundle
Bundle-ManifestVersion: 2
Created-By: Apache Maven Bundle Plugin
Bundle-SymbolicName: OSGIApp.Sample.OSGiSample2

之後把他deploy 到Virgo Server上,
接下來是OSGIApp.Sample.OSGiSample bundle, 如下

這邊要測試的是在bundle start & stop 時去控制
OSGIApp.Sample.OSGiSample2 bundle的行為,
首先是Activator.java
package com.my;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.osgi.context.BundleContextAware;

public class Activator implements BundleContextAware {
 
 
 Bundle bundle;
 
 BundleContext btx;
  
 public void start() throws BundleException{
  
  System.out.println("bundle  = " bundle);
  
  //update sampe2 bundle 
  bundle.update();
 }
 
 public void stop() throws BundleException{
  //stop sample2 , 
  bundle.stop();
 }
 
 public void setBundle(Bundle bundle) {
  System.out.println("bnudle set");
  this.bundle = bundle;
 }

 public void setBundleContext(BundleContext bundleContext) {
  System.out.println("set bundle context ");
  this.btx= bundleContext;
  
 }
}


在OSGi 的BuneleContext裡提供一個方法
btx.getBundle(70); //get bundle by bundle ID
這邊會從OSGi Container裡面去找Bundle id = 70的bundle,
Spring DM 裡面可以設定如下

bundle-context-osgi.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:osgi="http://www.springframework.org/schema/osgi"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

  <!-- definitions using elements of the osgi namespace can be included
       in this file. There is no requirement to keep these definitions
       in a separate file if you do not want to. The rationale for 
       keeping these definitions separate is to facilitate integration
       testing of the bundle outside of an OSGi container -->
         <context:annotation-config />
       <osgi:bundle id="rbundle" symbolic-name="OSGIApp.Sample.OSGiSample2" />
       <!-- This is the same as with the results of Bundle update();
       <osgi:bundle id="rbundle" symbolic-name="OSGIApp.Sample.OSGiSample2" action="update"/>  
        -->
</beans>

然後是bundle-context.xml, 相關的bean 設定
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

  <!-- regular spring configuration file defining the beans for this
       bundle. The configuration of OSGi definitions is kept in a separate 
       configuration file so that this file can easily be used
       for integration testing outside of an OSGi environment -->
       <context:annotation-config />
       
       <bean id="activator" class="com.my.Activator" init-method="start"
     destroy-method="stop">
     <property name="bundle" ref="rbundle"></property>
     </bean>
       
</beans>

然後別忘了重新設定MANIFEST.mf檔, Spring bundlor plugin 可以自動generation template.mf to MANIFEST.mf, 會自動check 需要class , 不過有時候會有一些class的問題,可能需手動解決。
在template.mf 檔或project 上按右鍵, 然後選Spring tools > Run Generation MANIFEST.mf file

完成後的MANIFEST如下
Manifest-Version: 1.0
Export-Package: com.my;version="1.0.0";uses:="org.osgi.framework,org.s
 pringframework.beans.factory.annotation,org.springframework.osgi.cont
 ext"
Unversioned-Imports: *
Built-By: momo
Tool: Bnd-1.15.0
Bundle-Name: Spring OSGi Bundle
Created-By: Apache Maven Bundle Plugin
Bundle-Version: 1.0.0
Build-Jdk: 1.6.0_24
Bnd-LastModified: 1305707690281
Bundle-ManifestVersion: 2
Import-Package: org.osgi.framework,
 org.springframework.beans.factory.annotation,
 org.springframework.osgi.context
Bundle-SymbolicName: OSGIApp.Sample.OSGiSample


結果如下, OSGIApp.Sample.OSGiSample2, OSGIApp.Sample.OSGiSample deploye 上去時, start() 調用後會先把OSGIApp.Sample.OSGiSample2給update(stop > start), 最後看到Refresh 是個人在測試時hot deploy 的效果。

2個bundle 的狀態, 然後把OSGIApp.Sample.OSGiSample 給stop

OSGIApp.Sample.OSGiSample2也會一起Stop,

2個Bundle 都是RESOLVED狀態


Reference :
Spring Dynamic Modules Reference Guide

沒有留言:

張貼留言