分享

扩展Tomcat支持OSGi应用服务(3)

 CevenCheng 2011-11-25

扩展Tomcat支持OSGi应用服务(2)
 
Tomcat6.0源码学习-构建Eclipse源码工程
扩展Tomcat支持OSGi应用服务(3)  

2009-08-12 14:52:17|  分类: OSGI |字号 订阅 

 
4.测试

       通过以上的实现,我们将OSGi平台集成到了Tomcat中,并且明确了web应用如何使用OSGi服务。下面就来创建一个测试的例子,看看OSGi编程模式对web应用开发的影响,同时也测试一下集成的效果。
4.1 创建并发布OSGi服务

Step1.创建插件工程com.dinstone.demo.user,选择standard OSGi framework。创建接口:
package com.dinstone.demo.user;

 

public interface IUserService {

    public String getUserName(String id);

}


Step2.创建插件工程com.dinstone.demo.user.db,创建类UserServiceImpl实现IUserService接口。
package com.dinstone.demo.user.db;

import java.util.logging.Logger;

import com.dinstone.demo.user.IUserService;

 

public class UserServiceImpl implements IUserService {

 

       private static Logger log = Logger.getLogger(UserServiceImpl.class

                     .getName());

 

       @Override

       public String getUserName(String id) {

              log.info("get user name from db");

              return "db" + id;

       }

}


 

Step3.向OSGi平台发布IUserService服务。创建Activator注册服务对象。
package com.dinstone.demo.user.db;

 

import java.util.Properties;

 

import org.osgi.framework.BundleActivator;

import org.osgi.framework.BundleContext;

import org.osgi.framework.ServiceRegistration;

 

import com.dinstone.demo.user.IUserService;

 

public class Activator implements BundleActivator {

 

       private ServiceRegistration serviceReg;

 

       /*

        * (non-Javadoc)

        * 

        * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)

        */

       public void start(BundleContext context) throws Exception {

              Properties p = new Properties();

              serviceReg = context.registerService(IUserService.class.getName(),

                            new UserServiceImpl(), p);

       }

 

       /*

        * (non-Javadoc)

        * 

        * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)

        */

       public void stop(BundleContext context) throws Exception {

              serviceReg.unregister();

       }

 

}


 

Step4. 创建插件工程com.dinstone.demo.user.file,创建类UserServiceImpl实现IUserService接口。
package com.dinstone.demo.user.file;

 

import java.util.logging.Logger;

 

import com.dinstone.demo.user.IUserService;

 

public class UserServiceImpl implements IUserService {

 

       private static Logger log = Logger.getLogger(UserServiceImpl.class

                     .getName());

 

       @Override

       public String getUserName(String id) {

              log.info("get user name from file");

              return "file" + id;

       }

}


 

Step5.向OSGi平台发布IUserService服务。创建Activator注册服务对象。
package com.dinstone.demo.user.file;

 

import java.util.Properties;

 

import org.osgi.framework.BundleActivator;

import org.osgi.framework.BundleContext;

import org.osgi.framework.ServiceRegistration;

 

import com.dinstone.demo.user.IUserService;

 

public class Activator implements BundleActivator {

 

       private ServiceRegistration serviceReg;

 

       /*

        * (non-Javadoc)

        * 

        * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)

        */

       public void start(BundleContext context) throws Exception {

              Properties p = new Properties();

              serviceReg = context.registerService(IUserService.class.getName(),

                            new UserServiceImpl(), p);

       }

 

       /*

        * (non-Javadoc)

        * 

        * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)

        */

       public void stop(BundleContext context) throws Exception {

              serviceReg.unregister();

       }

}


 
4.2 创建Web应用

Step1.创建动态web工程webDemo,并新建类:UserServiceFacade。
package com.dinsotne.web.demo;

 

import com.dinsotne.web.osgi.OsgiServiceFacade;

import com.dinstone.demo.user.IUserService;

 

public class UserServiceFacade {

 

       public static String getUserName(String id) {

              try {

                     IUserService service = OsgiServiceFacade.getOsgiService(

                                   "osgi/services", IUserService.class, IUserService.class

                                                 .getName());

 

                     return service.getUserName(id);

              } catch (IllegalArgumentException e) {

                     e.printStackTrace();

                     e.printStackTrace();

              }

 

              return null;

       }

}


 

Step2.创建index.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./TR/html4/loose.dtd">

<%@page import="com.dinsotne.web.demo.UserServiceFacade"%>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<title>Insert title here</title>

</head>

<body>

User Name is

<%=UserServiceFacade.getUserName("001") %>

 

</body>

</html>


 

Step3.修改web.xml文件,添加红色部分。
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www./2001/XMLSchema-instance"

    xmlns="http://java./xml/ns/javaee"

    xmlns:web="http://java./xml/ns/javaee/web-app_2_5.xsd"

    xsi:schemaLocation="http://java./xml/ns/javaee http://java./xml/ns/javaee/web-app_2_5.xsd"

    id="WebApp_ID" version="2.5">

    <display-name>webDemo</display-name>

    <welcome-file-list>

       <welcome-file>index.html</welcome-file>

       <welcome-file>index.htm</welcome-file>

       <welcome-file>index.jsp</welcome-file>

       <welcome-file>default.html</welcome-file>

       <welcome-file>default.htm</welcome-file>

       <welcome-file>default.jsp</welcome-file>

    </welcome-file-list>

    <resource-env-ref>

       <description>osgi service</description>

       <resource-env-ref-name>osgi/services</resource-env-ref-name>

       <resource-env-ref-type>

           com.dinstone.osgi.OsgiServices

       </resource-env-ref-type>

    </resource-env-ref>

</web-app>


 

说明:

1. 由于UserServiceFacade依赖IUserService类,故需要将com.dinstone.demo.user_1.0.0.jar(参见4.3)添加到lib中。

2. 由于UserServiceFacade依赖OsgiServiceFacade类,故将com.dinsotne.web.osgi_1.12.0.jar(参见3.4说明)添加到lib中。

 
4.3 发布OSGi Bundle

Step1.依次从插件工程导出插件包:com.dinstone.demo.user_1.0.0.jar,com.dinstone.demo.user.file_1.0.0.jar,com.dinstone.demo.user.db_1.0.0.jar。

Step2.将以上的插件放于${Tomcat_Home}\osgi\felix\bundle目录下。

 
4.4 发布web应用

Step1.导出web应用webDemo.war。

Step2.将webDemo.war放于${Tomcat_Home}\webapps目录下。

 
4.5 启动Tomcat并安装OSGi Bundle

Step1.在命令行下启动Tomcat。E:\Cluster\apache-tomcat-6.0.18为我的${Tomcat_Home}。
E:\Cluster\apache-tomcat-6.0.18>bin\startup.bat

Using CATALINA_BASE:   E:\Cluster\apache-tomcat-6.0.18

Using CATALINA_HOME:   E:\Cluster\apache-tomcat-6.0.18

Using CATALINA_TMPDIR: E:\Cluster\apache-tomcat-6.0.18\temp

Using JRE_HOME:        C:\Program Files\Java\jdk1.6.0_10

2009-8-12 13:21:39 com.dinstone.tomcat.osgi.OsgiLifecycleListener lifecycleEvent

信息: The osgi content is initialized. Using osgi content:felix

2009-8-12 13:21:39 org.apache.coyote.http11.Http11Protocol init

信息: Initializing Coyote HTTP/1.1 on http-8080

2009-8-12 13:21:40 org.apache.coyote.http11.Http11Protocol init

信息: Initializing Coyote HTTP/1.1 on http-8443

2009-8-12 13:21:40 org.apache.catalina.startup.Catalina load

信息: Initialization processed in 1748 ms

2009-8-12 13:21:41 com.dinstone.tomcat.osgi.OsgiLifecycleListener lifecycleEvent

信息: Starting osgi service.

2009-8-12 13:21:41 com.dinstone.tomcat.osgi.felix.FelixContent start

信息: *********************************

2009-8-12 13:21:41 com.dinstone.tomcat.osgi.felix.FelixContent start

信息: catalina home is E:\Cluster\apache-tomcat-6.0.18

2009-8-12 13:21:41 com.dinstone.tomcat.osgi.felix.FelixContent start

信息: osgi home is E:\Cluster\apache-tomcat-6.0.18\osgi\felix

2009-8-12 13:21:41 com.dinstone.tomcat.osgi.felix.FelixContent start

信息: ******user.dir is E:\Cluster\apache-tomcat-6.0.18

 

Welcome to Felix.

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

 

-> 2009-8-12 13:21:42 org.apache.catalina.core.StandardService start

信息: Starting service Catalina

2009-8-12 13:21:42 org.apache.catalina.core.StandardEngine start

信息: Starting Servlet Engine: Apache Tomcat/6.0.18

2009-8-12 13:21:42 org.apache.catalina.loader.WebappLoader start

信息: Dual registration of jndi stream handler: factory already defined

2009-8-12 13:21:44 org.apache.coyote.http11.Http11Protocol start

信息: Starting Coyote HTTP/1.1 on http-8080

2009-8-12 13:21:44 org.apache.coyote.http11.Http11Protocol start

信息: Starting Coyote HTTP/1.1 on http-8443

2009-8-12 13:21:44 org.apache.jk.common.ChannelSocket init

信息: JK: ajp13 listening on /0.0.0.0:8009

2009-8-12 13:21:44 org.apache.jk.server.JkMain start

信息: Jk running ID=0 time=0/47  config=null

2009-8-12 13:21:44 org.apache.catalina.startup.Catalina start

信息: Server startup in 3882 ms

-> ps

START LEVEL 1

   ID   State         Level  Name

[   0] [Active     ] [    0] System Bundle (1.6.0)

[  25] [Active     ] [    1] Apache Felix Shell Service (1.2.0)

[  26] [Active     ] [    1] Apache Felix Shell TUI (1.2.0)

[  27] [Active     ] [    1] Apache Felix Bundle Repository (1.4.0)

->


 

Step2.安装bundle。
-> install file:E:\Cluster\apache-tomcat-6.0.18\osgi\felix\bundle\com.dinstone.demo.user_1.0.0.jar

Bundle ID: 39

-> install file:E:\Cluster\apache-tomcat-6.0.18\osgi\felix\bundle\com.dinstone.demo.user.db_1.0.0.jar

Bundle ID: 40

-> install file:E:\Cluster\apache-tomcat-6.0.18\osgi\felix\bundle\com.dinstone.demo.user.file_1.0.0.jar

Bundle ID: 41

-> ps

START LEVEL 1

   ID   State         Level  Name

[   0] [Active     ] [    0] System Bundle (1.6.0)

[  25] [Active     ] [    1] Apache Felix Shell Service (1.2.0)

[  26] [Active     ] [    1] Apache Felix Shell TUI (1.2.0)

[  27] [Active     ] [    1] Apache Felix Bundle Repository (1.4.0)

[  39] [Installed  ] [    1] User Model Interface Plug-in (1.0.0)

[  40] [Installed  ] [    1] User DB Implement Plug-in (1.0.0)

[  41] [Installed  ] [    1] User File Implement Plug-in (1.0.0)

->


Step3.访问web应用,http://localhost:8080/webDemo/。由于没有启动OSGi服务,故出现500异常页面,错误原因是没有找到服务。
root cause 
com.dinsotne.web.osgi.IllegalServiceException: Cann't find out osgi service:com.dinstone.demo.user.IUserService
        com.dinsotne.web.osgi.OsgiServiceInvocationHandler.invoke(OsgiServiceInvocationHandler.java:30)
        $Proxy0.getUserName(Unknown Source)
        com.dinsotne.web.demo.UserServiceFacade.getUserName(UserServiceFacade.java:14)
        org.apache.jsp.index_jsp._jspService(index_jsp.java:64)
        org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
        org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
        org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 


 

Step4.启动User DB Implement Plug-in服务,激活User模块的DB实现。
->ps

START LEVEL 1

   ID   State         Level  Name

[   0] [Active     ] [    0] System Bundle (1.6.0)

[  25] [Active     ] [    1] Apache Felix Shell Service (1.2.0)

[  26] [Active     ] [    1] Apache Felix Shell TUI (1.2.0)

[  27] [Active     ] [    1] Apache Felix Bundle Repository (1.4.0)

[  39] [Installed  ] [    1] User Model Interface Plug-in (1.0.0)

[  40] [Installed  ] [    1] User DB Implement Plug-in (1.0.0)

[  41] [Installed  ] [    1] User File Implement Plug-in (1.0.0)

-> start 40

-> ps -s

START LEVEL 1

   ID   State         Level  Symbolic name

[   0] [Active     ] [    0] org.apache.felix.framework (1.6.0)

[  25] [Active     ] [    1] org.apache.felix.shell (1.2.0)

[  26] [Active     ] [    1] org.apache.felix.shell.tui (1.2.0)

[  27] [Active     ] [    1] org.apache.felix.bundlerepository (1.4.0)

[  39] [Resolved   ] [    1] com.dinstone.demo.user (1.0.0)

[  40] [Active     ] [    1] com.dinstone.demo.user.db (1.0.0)

[  41] [Installed  ] [    1] com.dinstone.demo.user.file (1.0.0)

->


访问http://localhost:8080/webDemo/。页面显示:




 

Step5. 启动User File Implement Plug-in服务,激活User模块的File实现。
-> ps

START LEVEL 1

   ID   State         Level  Name

[   0] [Active     ] [    0] System Bundle (1.6.0)

[  25] [Active     ] [    1] Apache Felix Shell Service (1.2.0)

[  26] [Active     ] [    1] Apache Felix Shell TUI (1.2.0)

[  27] [Active     ] [    1] Apache Felix Bundle Repository (1.4.0)

[  39] [Resolved   ] [    1] User Model Interface Plug-in (1.0.0)

[  40] [Active     ] [    1] User DB Implement Plug-in (1.0.0)

[  41] [Installed  ] [    1] User File Implement Plug-in (1.0.0)

-> start 41

-> ps

START LEVEL 1

   ID   State         Level  Name

[   0] [Active     ] [    0] System Bundle (1.6.0)

[  25] [Active     ] [    1] Apache Felix Shell Service (1.2.0)

[  26] [Active     ] [    1] Apache Felix Shell TUI (1.2.0)

[  27] [Active     ] [    1] Apache Felix Bundle Repository (1.4.0)

[  39] [Resolved   ] [    1] User Model Interface Plug-in (1.0.0)

[  40] [Active     ] [    1] User DB Implement Plug-in (1.0.0)

[  41] [Active     ] [    1] User File Implement Plug-in (1.0.0)

->


 

访问http://localhost:8080/webDemo/。页面显示:


 

 

Step6.现在停止User DB Implement Plug-in服务。
-> ps

START LEVEL 1

   ID   State         Level  Name

[   0] [Active     ] [    0] System Bundle (1.6.0)

[  25] [Active     ] [    1] Apache Felix Shell Service (1.2.0)

[  26] [Active     ] [    1] Apache Felix Shell TUI (1.2.0)

[  27] [Active     ] [    1] Apache Felix Bundle Repository (1.4.0)

[  39] [Resolved   ] [    1] User Model Interface Plug-in (1.0.0)

[  40] [Active     ] [    1] User DB Implement Plug-in (1.0.0)

[  41] [Active     ] [    1] User File Implement Plug-in (1.0.0)

-> stop 40

-> ps

START LEVEL 1

   ID   State         Level  Name

[   0] [Active     ] [    0] System Bundle (1.6.0)

[  25] [Active     ] [    1] Apache Felix Shell Service (1.2.0)

[  26] [Active     ] [    1] Apache Felix Shell TUI (1.2.0)

[  27] [Active     ] [    1] Apache Felix Bundle Repository (1.4.0)

[  39] [Resolved   ] [    1] User Model Interface Plug-in (1.0.0)

[  40] [Resolved   ] [    1] User DB Implement Plug-in (1.0.0)

[  41] [Active     ] [    1] User File Implement Plug-in (1.0.0)

->


 

访问http://localhost:8080/webDemo/。页面显示:


 

 
4.6 停止Tomcat服务器

重新打开一个命令行窗口,切换到${Tomcat_Home}\bin目录下。执行:
E:\Cluster\apache-tomcat-6.0.18\bin>shutdown.bat


Tomcat服务器关闭。
5结论

       通过以上的测试,我们发现以上的实现基本符合最初的设想:

l         OSGi的集成对Tomcat几乎是透明的。

l         OSGi的所有优点。

l         Web表现和业务逻辑的完全分离。

l         基于模块化服务的编程模型。

 

同时,我们也发现了一些问题:

l         Web层没有支持模块化、可热插拔的编程模型。

l         OSGi层的服务日志跟web层的日志分离增加了维护的难度。

l         该集成方式没有经严格测试,虽然已经有产品应用了。
附录:
1.测试Demo

2.源码工程

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多