跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

Lotus Notes/Domino 与 WebSphere Portal 集成实践

创建一个迷你型日历 Portlet

刘 奇, 软件工程师, IBM
刘奇是 IBM 中国软件工程师,现在 IBM 中国软件开发实验室 Lotus Notes Client 开发中心工作。
梁 骞, 高级软件工程师, IBM
梁骞是 IBM 中国高级软件工程师,现在 IBM 中国软件开发实验室 Lotus Notes Client 开发中心工作。

简介: Lotus Notes/Domino 和 WebSphere Portal 是 IBM Lotus 家族中的两大产品。本文将向读者介绍一个 WebSphere Portal 与 Lotus Notes/Domino 集成的实例 - 如何创建一个迷你型的日历 Portlet。该 Portlet 能够从 Lotus Domino 中获取用户的会议数据并将其显示出来,其大小可以改变。用户还可以通过显示出来的会议记录访问其在 iNotes 上的具体内容。

发布日期: 2009 年 9 月 04 日
级别: 中级
访问情况 : 4926 次浏览
评论: 


实例场景

本文将向读者展示一个 WebSphere Portal 与 Lotus Notes/Domino 集成的实例 -- 创建迷你型日历 Portlet,主要有以下功能:

  1. 可变化大小。
  2. 能够从 Lotus Domino Server 获取用户的日历数据。
  3. 点击日历上某一日期,显示当日的会议邀请记录列表。用户点击列表上的任一条目可以在 iNotes 上打开该条目的详细情况。

读者至少需要拥有 Lotus Domino Server V7 以上 , WebSphere Portal V6 以上,并完成 Portlet 与 Domino Server 之间单点登陆的配置。

关于 Portlet 与 Domino Server 之间的单点登陆,在文章 IBM / Lotus Domino 与 WebSphere Portal: 单点登录 中作了具体的讲解。

如果实际客户环境使用 LDAP 服务器作为 Domino Directory,读者需要配置 Domino Server 和 IBM WebSphere Portal,使得 LDAP 上的用户能够登陆 IBM WebSphere Portal。

由于 WebSphere Portal 和 Lotus Domino 之间的单点登录是通过一种称为轻量级第三方认证 (LTPA) 的机制来实现的。因此,还需要配置 WebSphere Portal 和 Domino 之间的 LTPA 关系。这些在 WebSphere Portal Info center上都有详细的文档,读者可以参考这些材料完成配置。

下面将介绍该实例的原理图,如图 1 所示。部署在 WebSphere Portal 上的 Portlet,显示一个日历,并通过 DIIOP 去访问 Domino Server 得到选定的日期的会议邀请等数据,并在 Portlet 上显示出来。


图 1. 实例原理图
图 1. 实例原理图

创建日历

可能大家都知道,用 JavaScript 创建一个日历,简单而快捷。由于在互联网上相关的实例和讲解众多,这里我只是简单的介绍一下日历实现的主要思想。

首先创建一个 7 × 7  的表格,第一行填充 [ 星期一,…,星期天 ],如图 2 所示。然后按照下面的规则填充表格单元。

  • 得到该月 1 日是星期几(假如是第 X 列),然后从第 2 行第 X 列开始填充 [1,2,…,Y] (假如该月有 Y 天)。
  • 填充第 2 行第 1 列到第 X-1 列。
  • 填充剩下的表格单元。

图 2. 日历示意图
图 2. 日历示意图

各个表格单元的属性可以通过样式文件来显示,例如周末用红色背景,今天用白色背景并加粗等等。


Portlet 与 Domino Server 之间的通讯

此实例一个重要的功能是能够获取 Domino Server 上的会议记录。在我们的实例当中,我们通过 DIIOP 访问 Domino。因此,我们必须确保所使用的 Domino Server 启动了 DIIOP 服务。具体方法是:打开 Domino 安装目录下的 notes.ini,将 DIIOP 到 ServerTasks 中,保存文件并重启 Domino Server。

下面介绍如何获取 Domino Server 上用户的会议邀请等。前文已经提到,我们的应用中,一个重要功能是对 SSO 的支持。用户登陆了 WebSphere Portal 之后,我们需要根据 WebSphere Portal 上的登陆信息找到用户在 Domino Server 上的信息(Mail Server 和 DIIOP 端口是用户单独配置的,具体见创建 Portlet 小节),最后获取 Domino Server 上该用户的会议邀请纪录,这里主要包含几个重要的步骤:

  • 获取 LTPA cookie 信息。清单 1 中变量 sessionToken 存储的值是 LTPA cookie 信息,将作为方法 getItemByDateUsingLTPA ( 见清单 3) 的第二个参数来获取会议邀请纪录。
  • 获取用户的 Notes 账号。清单 3 中开始部分根据 LTPA cookie 信息获取 Session notesSession,然后根据语句 notesSession.getUserName() 来获取用户的 Notes ID。
  • 获取用户的邮件在服务器上存放位置。一旦获得用户 Notes ID (Domino Server 由用户自行配置),我们就可以通过清单 2 获取用户的邮件存放位置,返回的结果类似于 “mail/test.nsf”。
  • 获取用户的会议邀请纪录。清单 3 演示了如何通过 LTPA 信息来获取用户会议邀请条目。其中, CalendarItem 存放的数据结构如清单 4 所示。

清单 1. 获取 LTPA cookie 信息
Cookie[] cookies = null; 
String sessionToken = null; 
cookies = renderRequest.getCookies(); 
if (cookies != null) { 
	for (int i = 0; i < cookies.length; i++){ 
		if (cookies[i].getName().equals("LtpaToken")){ 
	sessionToken = cookies[i].getValue(); 
	break; 
		} 
	} 
} 


清单 2. 获取用户邮件存放位置
public static String getMailFile(Session notesSession, 
String nameServer, String username) throws NotesException {
	String mailFile = null; 
	Database nameDB = notesSession.getDatabase(nameServer, "names.nsf"); 
	if(nameDB != null) { 
		String searchCondition = "Owner = \""+
			username+"\" & Type= \"Person\""; 
		DocumentCollection dc = nameDB.search(searchCondition); 
		if(dc != null) { 
			Document doc = dc.getFirstDocument(); 
			if(doc != null) { 
				Vector<Object> mailfiles = doc.getItemValue("MailFile"); 
				if(mailfiles!=null && mailfiles.size()>0) 
				mailFile = (String)mailfiles.get(0); 
			} 
			nameDB.recycle(); 
			if(mailFile != null) { 
				if(!mailFile.contains(".nsf")) 
					mailFile += ".nsf"; 
				mailFile = mailFile.replaceAll("\\\\", "/"); 
			} 
		} 
	} 
	return mailFile; 
} 


清单 3. 获取用户会议邀请条目
/**
* Retrieve the specific calendar items list
 * @param mailServer: mail server and DIIOP port, 
 *    e.g. dominodemo.company.com:63148
 * @param ltpaToken: LTPA token
 * @param startDate: start date, e.g. "03/23/2009"
 * @param endDate: end date, e.g. "03/23/2009"
 * @return calendar items list.
 * 
*/    
public static List<CalendarItem> getItemByDateUsingLTPA(String mailServer, 
String ltpaToken, String startDate, String endDate) {
    ArrayList<CalendarItem> list = new ArrayList<CalendarItem>();
    Database mailDB = null;
    Session notesSession = null;
    try {
        notesSession = NotesFactory.createSession(mailServer, ltpaToken);
        String []tmpArray = mailServer.split(":");
        String directory = getMailFile(notesSession,tmpArray[0],
			notesSession.getUserName());

        mailDB = notesSession.getDatabase(tmpArray[0], directory);
        String searchCondition = "@IsAvailable(" + 
			NotesCalendarFields.calendarDateTime + 
			") & @IsMember(\"" + startDate 
			+ "\";@Explode(StartDateTime; \",\"))";
        DocumentCollection dc = mailDB.search(searchCondition);
        Document doc = dc.getFirstDocument();
        long startDateTime = format.parse(startDate).getTime();
        long endDateTime = format.parse(endDate).getTime();
        while(doc != null) {
            Vector<Object> vec = 
				doc.getItemValue(NotesCalendarFields.calendarDateTime);
            for( int i = 0; vec != null && i < vec.size(); i ++) {
                Date date = ((DateTime)vec.get(i)).toJavaDate();
                long elem = date.getTime();
                if(elem >= endDateTime)
                    break;
                else if(elem >=  startDateTime) {
                    CalendarItem calItem = new CalendarItem();
                    if((vec = doc.getItemValue(NotesCalendarFields.subject))
						.size() > 0)
                            calItem.setSubject(vec.get(0).toString());
                    calItem.setStartDate(date);
                    vec = doc.getItemValue(NotesCalendarFields.endDateTime);
                    calItem.setEndDate(((DateTime)vec.get(i)).toJavaDate());
                        
                    if((vec = doc.getItemValue(NotesCalendarFields.description))
						.size() > 0)
                            calItem.setDescription((String)vec.get(0));
                    if((vec = doc.getItemValue(NotesCalendarFields.calType))
						.size() > 0)
                            calItem.setCalType(Integer.parseInt(vec.get(0)
						        .toString()));
                    URL url = new URL(doc.getHttpURL());
					//For SSO reason, we need to replace it's host
                    String strURL = url.toString().replaceAll(url.getHost(),
						tmpArray[0]); 
                    calItem.setHttpURL(strURL);
                    list.add(calItem);
                }
            }
            Document temp = dc.getNextDocument();
            doc.recycle();  // recycle the one we're done with 
            doc = temp; 
        }            
    }
    catch(Exception e) {
        e.printStackTrace();
    }
    finally {
        try {
            if(mailDB != null)
                mailDB.recycle();
            if(notesSession != null)
                notesSession.recycle();
        } 
        catch (NotesException e) {
            e.printStackTrace();
        }
    }
    
    return list;
}


清单 4. CalendarItem 数据结构
public class  CalendarItem {
    private Date startDate;
    private Date endDate;
    private String subject;
    private String description;
    private String httpURL;
    /**
    0 - Appointment
    1 - Anniversary
    2 - All Day Event
    3 - Meeting
    4 - Reminder
     */
    private int calType;
    public CalendarItem() {
        subject = "";
        description = "";
        calType = 0;
    }
    
    public Date getStartDate() {
        return startDate;
    }
    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }
    public Date getEndDate() {
        return endDate;
    }
    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public int getCalType() {
        return calType;
    }
    public void setCalType(int calType) {
        this.calType = calType;
    }

    public String getHttpURL() {
        return httpURL;
    }

    public void setHttpURL(String httpURL) {
        this.httpURL = httpURL;
    }
}


创建 Portlet

完成上述几个步骤之后,接下来我们需要创建一个 Portlet 来显示日历,当用户点击某一日期时,Portlet 能够调用清单 2 和 3 中的代码来获取用户的日历邀请条目并显示出来。能够创建 Portlet 的工具很多,IBM 也不缺乏这样的工具,例如 Rational Application Developer(简称 RAD)。用 RAD V7 创建 Portlet 十分简单,如图 3 和图 4 所示,创建一个名为 PortletExmple 的 Portlet,选择查看和编辑两个视图。

在文件 PortletExamplePortletEdit.jsp 中添加 2 个编辑框,让用户输入:Domino Server,DIIOP 端口(默认为 63148)。另添加一个 button 按钮,能够让用户保存数据。如清单 4 所示。

在 PortletExamplePortlet.java 中定义变量如下:

public static final String mailServer = "dominoCalendarmailServer";
public static final String portnumber = "dominoCalendarportnumber";
public static final String saveAction = "saveaction";
			

在方法 processAction 中实现处理 Portlet 编辑视图中的按钮事件。代码如清单 5 所示。

接下来我们来介绍如何实现 Portlet 查看视图。在文件 PortletExamplePortletView.jsp 中,其主要功能是生成一个带有日历以及选定日期的页面。我们用 preferences.getValue(String, “”) 获取 Domino Server 以及其端口值,然后调用清单 2 方法 getItemByDateUsingLTPA 可以获取会议邀请信息列表,每条记录包含开始时间、结束时间、描述、主题以及 iNotes 上该条目的 HTTP 链接,效果图如图 5 所示。


图 3. 创建 Portlet 示意图 1
图 3. 创建 Portlet 示意图 1

图 4. 创建 Portlet 示意图 2
图 4. 创建 Portlet 示意图 2

清单 5. Portlet 编辑视图代码
<%@ page session="false" contentType="text/html; charset=gb2312" 
import="java.util.*,javax.portlet.*, com.company.*"%>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
 
<%
PortletPreferences prefs = renderRequest.getPreferences();
if (prefs != null) {
    String mailServerValue = 
	    prefs.getValue(PortletExamplePortlet. mailServer, "");
    String portValue = prefs.getValue(PortletExamplePortlet.portnumber, "");
%>
 
<FORM ACTION="<portlet:actionURL/>"METHOD="POST">
Mail Server:<INPUT NAME="<%=PortletExamplePortlet. mailServer %>" 
	VALUE="<%= mailServerValue %>" TYPE="text"><BR>
Port:<INPUT NAME="<%=PortletExamplePortlet. portnumber %>"
    VALUE="<%= portValue %>"TYPE="text"><BR>
<input type="submit" value="Save" 
		name="<%= PortletExamplePortlet.saveAction %>" />  
<%
}
 %>
<input type="submit" value="Cancel" 
onclick="javascript:location.href='<portlet:renderURL portletMode="view"/>';"
/> 
</FORM> 
<%
    } else {
%>
Error: PortletPreferences is null.
<%
    }
%>


清单 6. Portlet 编辑视图事件处理函数
public void processAction(ActionRequest request, ActionResponse response) 
    throws PortletException, java.io.IOException {
    PortletPreferences prefs = request.getPreferences();
    try {
        if(request.getPortletMode() ==  PortletMode.EDIT ) {
            if(request.getParameter(saveAction)!=null)  {
                prefs.setValue(mailServer,request.getParameter(mailServer));
                prefs.setValue(portnumber,request.getParameter(portnumber));
                prefs.store();
            }
            response.setPortletMode(PortletMode.VIEW);
            response.setWindowState(WindowState.NORMAL);
         }
    }
    catch( ReadOnlyException roe ) {
    }
    catch( ValidatorException ve ) {
    }
}


图 5. Portlet 运行效果图
图 5. Portlet 运行效果图

结论

通过对上述实例的介绍,读者应该对如何实现 Lotus Notes/Domino 与 WebSphere Portal 的集成有一个大概地了解。读者可以结合 Lotus Notes/Domino 和 WebSphere Portal 的优点,开发出一些集成程序,更好的发挥它们的作用和价值,这也是本文的主要目的。


参考资料

作者简介

刘奇是 IBM 中国软件工程师,现在 IBM 中国软件开发实验室 Lotus Notes Client 开发中心工作。

梁骞是 IBM 中国高级软件工程师,现在 IBM 中国软件开发实验室 Lotus Notes Client 开发中心工作。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Lotus, WebSphere
ArticleID=425714
ArticleTitle=Lotus Notes/Domino 与 WebSphere Portal 集成实践
publish-date=09042009
author1-email=liuqibj@cn.ibm.com
author1-email-cc=
author2-email=liangq@cn.ibm.com
author2-email-cc=

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。