在 Lotus Domino 8 上利用 OSGi 特性开发和部署插件程序

OSGi 和 Eclipse

OSGi 是基于 Java 的服务平台的规范。OSGi 的本质是将 Java 面向对象的开发转向面向组件和服务的开发。OSGi 框架提供了一套完善的机制用于管理和控制组件(Bundle)、服务(Service)的生命周期,以及组件和服务在其生命周期内的交互。由于具有服务组件模块化、动态加载应用等优点, OSGi 技术正被越来越多的领域关注,如嵌入设备制造业、汽车制造业、企业应用等。目前,OSGi 联盟发布的最新的 OSGi 服务规范为 V4.2,读者可以查阅 参考资料 了解详细信息。

Equinox 项目是 Eclipse 开源组织提供的 OSGi 框架的实现。Equinox 的加入使得 OSGi 标准的应用领域不断扩充, Equinox 不仅提供了大部分 OSGi 标准服务的 bundle 实现,还借助 Eclipse 环境的一些自身的特点,提供了很多功能扩展服务。


Domino 集成 OSGi

众所周知,Lotus Notes V8 使用基于 Eclipse 的架构增强了 Lotus Notes 用户界面,强化了协作和消息传递功能,并使用最先进的编程结构扩展了应用程序开发模型。然而很少被人提及的是,Lotus Domino 在 V8 中也提供了一个 OSGi 平台,基于这个平台我们可以动态地添加或更改插件。我们打开 Domino 的安装目录,可以找到 osgi 文件夹。这个文件夹用来存放基于 Eclipse 的常用 features 和 plugins。其中 rcp 文件夹中是 Domino 运行的基础插件集,而 shared 文件夹中则是依赖于 rcp 文件夹中插件集的一些应用程序。

那么将 OSGi 的运行和编程模型引入 Domino 带来了什么好处呢?

  • 可以和客户端 Notes 保持一致;
  • 可以最大化地重用基于 Eclipse 的插件(如 http 服务,日志服务等);
  • 由于使用了插件机制,各模块的组织更加规范化,方便复用和扩展;
  • 插件容易部署和升级;
  • 只有请求发生时才加载相关组件,系统更加高效。

在最新版本的 Domino 中,OSGi 控制台已经集成在 Domino 服务器控制台里了。使用如下命令可以查看系统中安装的所有组件,返回结果如图 1 所示。

> tell http osgi ss 



图 1. Domino 中的 OSGi 控制台
图 1. Domino 中的 OSGi 控制台


配置 Eclipse 开发环境

我们在开发基于 Domino 的应用程序之前,需要将 Eclipse 中的目标平台指向 Domino。在下文的环境配置中,我将假设 Domino 安装在默认位置 C:/Program Files/IBM/Lotus/Domino。请读者根据情况自行修改。

打开 Eclipse,单击 Window> Preferences。在打开的 Preferences对话框中,选择 Plug-in Development> Target Platform,如图 2 所示。


图 2. Eclipse Preferences 对话框
图 2. Eclipse Preferences 对话框

单击 Browser 按钮,切换 Platform LocationC:/Program Files/IBM/Lotus/Domino/osgi/rcp/eclipse,单击确定,如图 3 所示。


图 3. 选择 Target platform
图 3. 选择 Target platform

这样 Domino 中的 OSGi 插件会全部加载进来,如图 4 所示。


图 4. Eclipse 环境配置完成界面
图 4. Eclipse 环境配置完成界面

单击 OK,开发环境配置完毕。


开发 plugin

我们利用配置好的 Eclipse 环境开发一个示例程序。这个程序扩展了 org.eclipse.equinox.http.registry.servlets,从而可以利用 Domino 作为 Servlet 容器。在正式开发之前,我们先做一些准备工作。

准备

打开 Lotus Domino Designer,我们新建一个 demo.nsf。在 demo.nsf 中新建一个 Form,在 Form 中建一个域 name 和一个按钮,如图 5 所示。按钮 Click 事件的 Formula 为 @Command([FileSave]);@Command([FileCloseWindow])。同时创建一个对应的 View


图 5. 新建 demo.nsf
图 5. 新建 demo.nsf

在 Form标签中点击 Preview in Notes按钮,我们通过 Lotus Notes 在 demo.nsf 中加入一些测试数据,如图 6 所示。


图 6. 测试数据
图 6. 测试数据

创建 Plug-in 工程

在 Eclipse 中创建一个 Plug-in 工程,输入工程名为 com.ibm.domino.demo,如图 7 所示。这里和创建普通的 Java 工程唯一的不同点就是需要选择 Target Platform,我们选择 Equinox,单击 Next按钮。


图 7. 插件工程设置
图 7. 插件工程设置

输入插件的相关元数据信息,如图 8 所示。

  • Plug-in ID指的是 Bundle 的唯一标识,在实际的项目中可以采用类似 java 的包名组织策略来保证标识的唯一性。这里默认为项目的名称 com.ibm.domino.demo。
  • Plug-in Version指的是插件的版本,默认为 1.0.0。
  • Plug-in Name指的是插件更具有意义的名称,默认为 Demo Plug-in。
  • Plug-in Provider指的是插件的提供商,默认为从项目名称中解析出来的字段。
  • Execution Environment指的是插件运行需要的环境,选择 JavaSE 1.6。

去掉 Generate an activator前边的勾号,我们不需要创建 Activator。单击 Finish按钮。


图 8. 插件信息设置
图 8. 插件信息设置

添加扩展点

我们用扩展点的方式使得项目具有处理 http Servlet 的能力。为了配置扩展点,我们可以在项目的根目录下手动建立一个 plugin.xml 或者打开 MANIFEST.MF 文件,在其 Overview视图标签页上找到扩展点设置区域,点击 extensions即可对其扩展点进行配置,如图 9 所示。


图 9. 配置扩展点
图 9. 配置扩展点

在弹出的 Extension Point Selection对话框中去掉 show only extension points from the required plug-ins 的勾号,在 Extension Point filter 中输入 org.eclipse.equinox.http.registry.servlets,单击 finish 按钮。Eclipse 会自动提示是否要加入所需的插件,单击 Yes。如图 10 所示。


图 10. 添加扩展点
图 10. 添加扩展点

plugin.xml 文件的内容如清单 1 所示,我们在其中定义了扩展点用来处理 Servlet 请求。


清单 1 . plugin.xml

				
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
    <extension
        point="org.eclipse.equinox.http.registry.servlets">
        <servlet
         alias="/demo"
         class="com.ibm.domino.demo.servlet.DemoServlet"
         load-on-startup="true">
        </servlet>
    </extension>    
</plugin>

 

最终的 MANIFEST.MF 文件如清单 2 所示。


清单 2 . MANIFEST.MF

				
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Demo Plug-in
Bundle-SymbolicName: com.ibm.domino.demo;singleton:=true
Bundle-Version: 1.0.0
Bundle-Vendor: IBM
Require-Bundle: org.eclipse.equinox.http.registry
Import-Package: javax.servlet,javax.servlet.http

 

编写 DemoServlet 代码

我们将要用到之前准备好的 demo.nsf 了。我们写一个 Servlet,将 demo.nsf 里的内容输出到浏览器上,代码见清单 3。


清单 3 . DemoServlet.java

				
package com.ibm.domino.demo.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.DocumentCollection;
import lotus.domino.NotesException;
import lotus.domino.NotesFactory;
import lotus.domino.NotesThread;
import lotus.domino.Session;

public class DemoServlet extends HttpServlet{

    private static final long serialVersionUID = 1L;
    private static final String NSF_NAME = "demo.nsf";
    private static final String FILED_NAME = "name";
    public DemoServlet() {
        
    }
    
    @Override
    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<body>");
        out.println("<head>");
        out.println("<title>Domino OSGi Demo</title>");
        out.println("</head>");
        out.println("<body>");
        try {
            NotesThread.sinitThread();
            Session session = NotesFactory.createSession();
            Database db = session.getDatabase(null, NSF_NAME);
            if (!db.isOpen()) { // open database failed
                return;
            }
            DocumentCollection dc = db.getAllDocuments();
            Document tmpdoc;
            Document doc = dc.getFirstDocument();
            int index = 0;
            while (doc != null) {
                out.println("Item" + index + ": ");
                index++;
                String fieldValue = doc.getItemValueString(FILED_NAME);
                out.println(fieldValue);
                out.println("<br/>");
                tmpdoc = dc.getNextDocument();
                doc.recycle();
                doc = tmpdoc;
            }
            db.recycle();
            out.println("<br/>");
            out.println("Total " + index +" documents in " + NSF_NAME);
        } catch (NotesException e) {
            e.printStackTrace();
        } finally {
            NotesThread.stermThread();
            out.println("</body>");
            out.println("</html>");
            out.flush();
            //out.close();
        }
    }
}

 

将清单 3 粘贴到 Eclipse 中,会有一些编译错误。为了访问 Domino 中的元素,我们需要将 Notes.jar 加入到 JRE 库中。方法如下:

在 Eclipse 中单击 Window> Preferences> Java> Installed JREs,选择当前使用的 JRE,单击 Edit按钮,如图 11 所示。


图 11. 配置 JRE
图 11. 配置 JRE

Edit JRE对话框中,单击 Add External JARs按钮,将 C:/Program Files/IBM/Lotus/Domino/jvm/lib/ext/Notes.jar添加进来,如图 12 所示。这样编译错误应该会全部消失。


图 12. 加入 Notes.jar
图 12. 加入 Notes.jar

导出 jar 包

接下来,我们要将写好的程序打包成插件放在 Domino 下运行。右击 com.ibm.domino.demo 项目,选择 Export命令导出项目,导出类型选择 Deployable plug-ins and fragments,如图 13 所示。导出位置选择 C:/Program Files/IBM/Lotus/Domino/osgi/shared/eclipse。单击 Finish按钮,插件将被导出到 C:/Program Files/IBM/Lotus/Domino/osgi/shared/eclipse/plugins目录下。


图 13. 部署 Plug-in
图 13. 部署 Plug-in

创建 Feature 工程

我们还需要为插件程序建立一个功能部件。单击 New> Project> Feature Project,在 Eclipse 中创建一个 Feature 工程。Project Name输入 com.ibm.domino.demo.feature。单击 Next按钮,如图 14 所示,选择我们之前开发的 Plug-in com.ibm.domino.demo。单击 Finish按钮完成 Feature 工程创建。


图 14. 为 feature 选择 plug-in
图 14. 为 feature 选择 plug-in

可以在 feature.xml 的 Information视图标签页面输入一些描述性文字,用于说明 License 和 Copyright 等。

导出 Feature

我们将建好的 Feature 导出到 Domino 中。右击 com.ibm.domino.demo,feature 项目,单击 Export,导出类型选择 Deployable features,如图 15 所示。导出位置和导出 Jar 包时一样,仍然是 C:/Program Files/IBM/Lotus/Domino/osgi/shared/eclipse。单击 Finish按钮,该 feature 将被导出到 C:/Program Files/IBM/Lotus/Domino/osgi/shared/eclipse/features目录下。


图 15. 部署 Feature
图 15. 部署 Feature

至此,一个 demo plug-in 项目就开发并部署完毕了,我们来测试一下。首先启动 Domino 服务器,在控制台中输入 tell http osgi ss demo。从图 16 可以看到,我们的插件已经处于 RESOLVED 状态了。


图 16. 查看 plug-in 状态
图 16. 查看 plug-in 状态

打开浏览器,输入 http://localhost/demo。该页面将返回 demo.nsf 中所有 document 中 Item 名称为 name 的数据,如图 17 所示。


图 17. 返回结果
图 17. 返回结果


远程调试

由于我们开发的插件程序是依托 Domino 平台运行的,因此调试时我们需要用到远程调试的技巧。

设置 Domino 的远程调试

我们需要做一些设置以打开 Domino 中的远程调试开关。

打开 Notes.ini(C:/Program Files/IBM/Lotus/Domino/notes.ini),加入以下粗体显示的代码。


清单 4. 修改 Notes.ini

				
[Notes] 
NotesProgram=C:/Program Files/IBM/Lotus/Domino 
JavaEnableDebug=1 
JavaDebugOptions=transport=dt_socket,server=y,suspend=n,address=8000 
Directory=C:/Program Files/IBM/Lotus/Domino/data 

 

重新启动 Domino 服务器。如果你在控制台发现如下信息,则说明远程调试已经启用了。

2010-08-10 13:04:34 JVM: WARNING: Remote Java Debugging is enabled, resulting in 
decreased performance and potentially compromised security 
> Listening for transport dt_socket at address: 8000 

 

使用 Eclipse 进行远程调试程序

打开 Eclipse,单击 Run > Debug Configurations,单击 Remote Java Application,单击 New 新建一个 Configuration,如图 18 所示。


图 18. 设置 Eclipse 的远程调试
图 18. 设置 Eclipse 的远程调试

修改名称为 Domino Remote,Connection Type 选择默认的 Standard (Socket Attach)Connection Properties 选择 Domino 启动的 HostPort,这里为 localhost 和 8000。如图 19 所示。


图 19. 设置 Domino Remote
图 19. 设置 Domino Remote

接着需要将待调试的源代码加到工作空间中。单击 Source 标签进入 Source 标签页面,单击 Add > Java Project 添加待调试的源代码,如图 20 所示。


图 20. 增加源代码
图 20. 增加源代码

选择项目 com.ibm.domino.demo,如图 21 所示。最后,单击 Apply 按钮结束配置。


图 21. 选择待调试的项目
图 21. 选择待调试的项目

装载 Debug Configurations,在源代码中设置断点,当 Domino 上运行的程序执行到断点处时,程序会停在断点处,我们就可以像平时一样调试程序了。


结束语

本文讲述了 Lotus Domino 的新特性 —— OSGi,并演示了如何利用 OSGi 在 Domino 上开发一个插件程序的过程。阅读完本文,您应该对 Domino 的 OSGi 特性有所了解,并可以遵循本文提供的配置向导进行插件开发。最后,您还掌握了如何调试 Domino 中的插件程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值