程序人生

在Java中摸爬滚打的日子

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  6 Posts :: 1 Stories :: 19 Comments :: 0 Trackbacks

提供支撑的Bundles

--- 潇湘振宇 2010-06-26  

上一篇中,我们已经为这基于OSGiWeb应用搭建了项目框架,但其中涉及到有几个支撑OSGi环境下的SSH框架的Bundles的改造或提供未曾给大家详细介绍。本篇内容就是为详细介绍这几个Bundles的作用及创建的过程。


CGLIB的改造

Cglib的改造曾在系列一中有提到,为了解决Hibernate在调用CGLIB来创建代理对象时找不到HibernateProxy对象的问题。改造也相当的简单,只需要将AbstractClassGenerator类中的getClassLoader方法中的ClassLoad改为当前类所在的ClassLoad即可,如下所示:

public ClassLoader getClassLoader() {

        ClassLoader t = classLoader;

        /**

         * FIXME 更改classLoad的加载顺序 

     *  if (t == null) {

     *      t = getDefaultClassLoader();

     *  }

     *  if (t == null) {

     *      t = getClass().getClassLoader();

     *  }

         */

        if (t == null) {

            t = getClass().getClassLoader();

        }

        if (t == null) {

            t = getDefaultClassLoader();

        }

        if (t == null) {

            t = Thread.currentThread().getContextClassLoader();

        }

        if (t == null) {

            throw new IllegalStateException("Cannot determine classloader");

        }

        return t;

    }

以上是改造的内容,而我们在项目中应用的时候需要的是一个OSGiBundle,因此我们可以通过Pax-construct来创建这个Bundle

大致过程是:首先在org.ideawork.osgi工程下面新建名为warpper的模块,再到warpper目录下面新建cglibbundle工程,并将其导入到IDE环境中。然后从官方网站下载cglib的源码,将源码添加到相应的工程,再对需要修改的地方修改之。

具体步骤如下:

1. 新建warpper的模块

通过Pax-Construct的命令来新建此warpper模块,如下:

>cd osgiapp

>pax-create-module -g org.ideawork.osgiapp -a osgiapp-warpper -v 1.0.0

其中osgiapp为当前这应用的根目录,cd osgiapp为进入到根目录下,而下面的命令则是创建module工程,这在上篇已经介绍过。

2. 新建cglibbundle

Cglibbundle工程的创建跟上篇中其他bundle的创建类似,命令如下:

>cd osgiapp-warpper

>pax-create-bundle -p org.ideawork.osgiapp.warpper.cglib -n osgiapp-warpper-cglib -g org.ideawork.osgiapp.warpper -v 2.1.3-001

         这里之所以要指定版本号为2.1.3-001是因为我们改造的是2.1.3版的cglib,而后面的001代表的是我们自己的warpper工程的小版本号,如果以后有对此cglib bundle升级,但cglib的版本还是2.1.3,那时候我们就升级001这个版本号。

3. 导入IDEEclipse

导入方式如上篇所述,导入后的视图如下:


4. 添加cglib的源码

我们将从官方网站下载的cglib的源码添加到cglib bundle下的src/main/java目录下,并将新建此bundle工程时默认生成的org.ideawork.osgiapp.warpper.cglib的包删除掉。刷新当前项目,此时会出现很多的红叉叉,这是因为缺少相关的依赖包所致。因此我们需要在此bundle工程下的pom.xml文件中添加如下依赖信息:

<dependencies>

<dependency>

<groupId>org.objectweb.asm</groupId>

<artifactId>com.springsource.org.objectweb.asm</artifactId>

<version>1.5.3</version>

<scope>compile</scope>

<optional>true</optional>

</dependency>

<dependency>

<groupId>org.objectweb.asm</groupId>

<artifactId>

com.springsource.org.objectweb.asm.attrs

</artifactId>

<version>1.5.3</version>

<scope>compile</scope>

<optional>true</optional>

</dependency>

<dependency>

<groupId>org.objectweb.asm</groupId>

<artifactId>com.springsource.org.objectweb.asm.util</artifactId>

<version>2.2.0</version>

<scope>compile</scope>

<optional>true</optional>

</dependency>

<dependency>

<groupId>org.codehaus.aspectwerkz</groupId>

<artifactId>com.springsource.org.codehaus.aspectwerkz.hook</artifactId>

<version>1.0.0</version>

<scope>compile</scope>

<optional>true</optional>

</dependency>

<dependency>

<groupId>org.apache.ant</groupId>

<artifactId>com.springsource.org.apache.tools.ant</artifactId>

<version>1.7.0</version>

<scope>compile</scope>

<optional>true</optional>

</dependency>

</dependencies>

5. 修改ClassLoad加载顺序

修改AbstractClassGenerator类中的getClassLoader方法中的ClassLoad加载顺序已经在上面描述过,大家按上面的修改即可。

6. 完善MANIFEST.MF文件中的元数据信息

这里关于MANIFEST.MF文件中的一些元数据,我们不想让bnd为我们来生成,因为通过bnd工具生成的元数据,有时候生成的元数据过于庞大。因此我们在osgi.bnd文件中添加相关的元数据信息,并删除新建项目时默认生成的Bundle-Activator元素,需要添加的内容如下:

Export-Package = net.sf.cglib.asm;version="2.1.3","

 net.sf.cglib.asm.attrs;version="2.1.3";uses:="net.sf.cglib.asm","

 net.sf.cglib.beans;version="2.1.3";uses:="net.sf.cglib.asm,net.sf.cglib.core","

 net.sf.cglib.core;version="2.1.3";uses:="net.sf.cglib.asm","

 net.sf.cglib.proxy;version="2.1.3";uses:="net.sf.cglib.asm,net.sf.cglib.core,net.sf.cglib.reflect","

 net.sf.cglib.reflect;version="2.1.3";uses:="net.sf.cglib.asm,net.sf.cglib.core","

 net.sf.cglib.transform;version="2.1.3";uses:="net.sf.cglib.asm,net.sf.cglib.core,org.apache.tools.ant,org.apache.tools.ant.types","

 net.sf.cglib.transform.hook;version="2.1.3";uses:="net.sf.cglib.asm,net.sf.cglib.transform","

 net.sf.cglib.transform.impl;version="2.1.3";uses:="net.sf.cglib.asm,net.sf.cglib.core","

 net.sf.cglib.util;version="2.1.3";uses:="net.sf.cglib.asm,net.sf.cglib.core"

Bundle-ClassPath = .

Bundle-Version = 2.1.3

JarJarStringTransformer = com.tonicsystems.jarjar.GeneratedStringTransformer

Bundle-Name = CGLIB Code Generation Library

Import-Package = org.apache.tools.ant;version="[1.7.0, 2.0.0)";resolution:=optional,"

 org.apache.tools.ant.types;version="[1.7.0, 2.0.0)";resolution:=optional,"

 org.codehaus.aspectwerkz.hook;version="[0.8.1, 0.9.0)";resolution:=optional,"

 org.objectweb.asm;version="[1.5.3, 2.0.0)";resolution:=optional,"

 org.objectweb.asm.attrs;version="[1.5.3, 2.0.0)";resolution:=optional

DynamicImport-Package = *

7. 编译打包

编译打包的工作我们是交给Maven来帮我们做,但我们需要修改cglib bundle工程下的pom.xml文件中的properties元素的相关属性内容做。需要将<bundle.namespace>org.ideawork.osgiapp.warpper.cglib</bundle.namespace>修改成<bundle.namespace>net.sf.cglib</bundle.namespace>,这样修改的目的是因为在利用Maven编译打包的时候,bnd插件会根据bundle工程的namespace的定义来导出相关的包,如果项目中的classis文件不在其namespace范围内,打包时被会被忽略掉。

修改完pom.xml文件后,在命令行窗口下进入到cglib bundle工程的目录下,运行mvn -e clean install命令就可以将cglib bundle安装到本地Maven仓库。到这里cglib的改造完成。


封装Mysql Connector

因为数据库用的是Mysql,数据库连接池使用的是C3p0,因为C3p0在创建数据库连接池的时候需要使用到指定的驱动包,而C3p0作为一个独立的Bundle,不能偶合具体的驱动程序包,所以C3p0在创建数据库连接池时,需要我们提供一个Fragment来让其导入我们指定的驱动程序包,这曾在系列一中也已经说到过。但这里我们将不通过提供另一个Fragment来实现此需求,因为我想使用最新版的Mysql connector 5.1.13,但这个版本的Mysql connectorEBR仓库中尚不存在,因此我借这个封装Mysql connector的机会来解决C3p0使用mysql的驱动包的问题,并向大家介绍如何使用pax-construts来创建warpper工程。

大致流程是:在命令行窗口下,进入到osgiapp/osgiapp-warpper目录下,运行pax-construts创建warpper工程的命令,然后修改相关的配置文件,编译打包即可。

具体步骤如下:

1. 创建osgiapp-warpper-mysqlconnector

这里的mysqlconnector跟与面的cglib都是通过改造第三方的包来达到目的的,因此我们将其统统放在了warpper模块之中,但这里的mysqlconnectorcglib还是有区别的,cglib是通过pax-construtspax-create-bundle命令创建的,而这里我们将通过pax-wrap-jar的命令来创建。命令如下:

这里的-g-a-v跟之前的含义是一样的,分别表示groupIdartifactIdversion,但这里的这些指是的将要被我们包装的Jar包的Maven属性。如果此Jar包不存在本地的Maven仓库中,Maven将会从网上的Maven2的仓库中下载此Jar文件。

2. 修改相关配置

成功创建工mysql-connectorwarpper工程后,我们需要修改的有pom.xml文件跟osgi.bnd文件。

修改pom.xml文件中的artifactIdosgiapp-warpper-mysql-connector-java,并将version改成5.1.13-001,还有就是properties中的bundle.symbolicName成改org.ideawork.osgiapp.wrapper.mysql.connector.java

另外在osgi.bnd文件中添加如下信息:

pax-wrap-jar -g mysql -a mysql-connector-java -v 5.1.13

3. 编译打包

编译打包直接运行Maven的命令即可。

Tomcat提供Fragment

为了使此web应用能正常访问,我们需要为Tomcat 相关的两个Bundle提供两个Fragment。这在系列一中曾有说到。

需要使用到这两个FragmentBundleartifactId分别是:com.springsource.org.apache.catalinacatalina.start.osgi,前者是apache公司下的包,后者是springframeworkspringDMweb支持而提供的。

具体的创建步骤如下:

1. 新建fragment的模块

通过Pax-Construct的命令来新建此fragment模块,如下:

Import-Package = ""

DynamicImport-Package = *

Fragment-Host = com.springsource.com.mchange.v2.c3p0

2. 新建两个Fragmentbundle工程

Cglibbundle工程的创建跟上篇中其他bundle的创建类似,命令如下:

3. 修改配置文件

将新建的Fragment工程导入到IDE环境,导入后工程视图如下:


这里我们只需简单的修改一下两个Fragment Bundle工程下的osgi.bnd文件并在工程的资源文件夹下添加几个配置文件即可。

a) 对于osgiapp-fragment-tomcat-conf这个Fragment,需要为其添加以下这四个配置文件,如图:

   

这四个配置文件来自于普通的tomcat安装包中,不过需要版本匹配才行。比如这里用到的tomcat bundle6.0.15的那就需要从6.0.15版的传统的tomcat的安装目录下拷贝。

然后修改其osgi.bnd文件,此osgi.bnd文件中的内容如下:

>cd osgiapp

>pax-create-module -g org.ideawork.osgiapp -a osgiapp-fragment -v 1.0.0

>cd osgiapp-fragment

>pax-create-bundle -p org.ideawork.osgiapp.fragment.tomcat.conf -n osgiapp-fragment-tomcat-conf -g org.ideawork.osgiapp.fragment -v 1.0.0

>pax-create-bundle -p org.ideawork.osgiapp.fragment.tomcat.start.conf -n osgiapp-fragment-tomcat-start-conf -g org.ideawork.osgiapp.fragment -v 1.0.0

此处的Fragment-Host=com.springsource.org.apache.catalina指当前这个Fragment的宿主为com.springsource.org.apache.catalinabundleFragment-Host的值表示的是宿主BundleBundle-SymbolicName

b) 对于osgiapp-fragment-tomcat-start-conf Fragment,需要像上面的一样添加一个server.xml的配置文件,这个文件的来由跟上面所说的一样。添加后的视图如下:

   

然后再修改其osgi.bnd文件,内容如下:

Export-Package = ""

Private-Package = 

Import-Package = ""

Fragment-Host = com.springsource.org.apache.catalina


总结

通过以上的操作得到四个bundle,这四个bundle是这个OSGiweb应用所必须的,当然这样的车轮只需要造一次,当你将需要再新建此类基于OSGi环境的SSH Web工程时,就可以直接拿过来用了。其中Tomcat的两个Fragment主要是主含些配置文件,这个在项目部署的时候可能会需要修改的,具体得视应用而定。

完成了这章中的四个Bundle后,我们可以将这四个Bundle应用于系列三中的框架中来进行测试。也许这章的内容应该位于上篇之前介绍,大家就当这是对前一篇的补充吧。


附件:项目源码 osgiapp.zip

posted on 2010-06-26 16:24 潇湘振宇 阅读(3783) 评论(5)  编辑  收藏 所属分类: OSGi系列

Feedback

# re: 基于OSGi的Web应用开发系列四(提供支撑的Bundles)[未登录] 2010-06-28 16:33 root
很强大,支持下  回复  更多评论
  

# re: 基于OSGi的Web应用开发系列四(提供支撑的Bundles) 2010-07-23 23:52 zhangls
谢谢作者能和大家分享OSGi成果~ 本人最近也在研究osgi,能否发我一份源码,希望能有更多的交流。谢谢~!  回复  更多评论
  

# re: 基于OSGi的Web应用开发系列四(提供支撑的Bundles) 2010-07-23 23:53 zhangls
email:zhanglingsi@yahoo.com.cn   回复  更多评论
  

# re: 基于OSGi的Web应用开发系列四(提供支撑的Bundles) 2010-07-28 09:24 潇湘振宇
@zhangls
源码就在本篇的末尾,只是因为最近公司事忙,没有继续这系列文章的编写,将上面源码包导入到Eclipse中,再用Maven命令来编译打包安装后,再用mvn pax:provision的命令就可以启动这个OSGi web应用,只是系列文章中说到的用户登录的功能尚未实现。但那只是业务方面,整体的开发脚手架已经搭建起来了,运行也是没问题的。
如果对这里说到的运行的命令不懂,可以仔细阅读本系列前几篇文章。  回复  更多评论
  

# re: 基于OSGi的Web应用开发系列四(提供支撑的Bundles) 2010-08-10 09:36 潇湘振宇
关于mvn-pax-plugin插件,这里给出两个开发过程中常用的参数,如下:
<param>--vmOptions=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000</param>
<param>--repositories=+http://scm.ops4j.org/repos/ops4j/projects/pax/runner-repository/</param>
其中--vmOptions参数是指设置JVM的一些属性,如上所示开启远程Java调试。
而--repositories是pax自己的一个参数来着。有时候在用pax:provision命令时,其老是去访问网络下载或检测相关pax的包,浪费掉了我们开发人员宝贵的时间,加上这个参数后会好很多。  回复  更多评论
  


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


网站导航: