panmezihuan0 2010-06-23
http://www.ibm.com/developerworks/cn/lotus/domino-wps/
2009年9月04日
LotusNotes/Domino和WebSpherePortal是IBMLotus家族中的两大产品。本文将向读者介绍一个WebSpherePortal与LotusNotes/Domino集成的实例-如何创建一个迷你型的日历Portlet。该Portlet能够从LotusDomino中获取用户的会议数据并将其显示出来,其大小可以改变。用户还可以通过显示出来的会议记录访问其在iNotes上的具体内容。
实例场景
本文将向读者展示一个WebSpherePortal与LotusNotes/Domino集成的实例--创建迷你型日历Portlet,主要有以下功能:
可变化大小。
能够从LotusDominoServer获取用户的日历数据。
点击日历上某一日期,显示当日的会议邀请记录列表。用户点击列表上的任一条目可以在iNotes上打开该条目的详细情况。
读者至少需要拥有LotusDominoServerV7以上,WebSpherePortalV6以上,并完成Portlet与DominoServer之间单点登陆的配置。
关于Portlet与DominoServer之间的单点登陆,在文章IBM/LotusDomino与WebSpherePortal:单点登录中作了具体的讲解。
如果实际客户环境使用LDAP服务器作为DominoDirectory,读者需要配置DominoServer和IBMWebSpherePortal,使得LDAP上的用户能够登陆IBMWebSpherePortal。
由于WebSpherePortal和LotusDomino之间的单点登录是通过一种称为轻量级第三方认证(LTPA)的机制来实现的。因此,还需要配置WebSpherePortal和Domino之间的LTPA关系。这些在WebSpherePortalInfocenter上都有详细的文档,读者可以参考这些材料完成配置。
下面将介绍该实例的原理图,如图1所示。部署在WebSpherePortal上的Portlet,显示一个日历,并通过DIIOP去访问DominoServer得到选定的日期的会议邀请等数据,并在Portlet上显示出来。
图1.实例原理图
回页首
创建日历
可能大家都知道,用JavaScript创建一个日历,简单而快捷。由于在互联网上相关的实例和讲解众多,这里我只是简单的介绍一下日历实现的主要思想。
首先创建一个7×7 的表格,第一行填充[星期一,…,星期天],如图2所示。然后按照下面的规则填充表格单元。
得到该月1日是星期几(假如是第X列),然后从第2行第X列开始填充[1,2,…,Y](假如该月有Y天)。
填充第2行第1列到第X-1列。
填充剩下的表格单元。
图2.日历示意图
各个表格单元的属性可以通过样式文件来显示,例如周末用红色背景,今天用白色背景并加粗等等。
回页首
Portlet与DominoServer之间的通讯
此实例一个重要的功能是能够获取DominoServer上的会议记录。在我们的实例当中,我们通过DIIOP访问Domino。因此,我们必须确保所使用的DominoServer启动了DIIOP服务。具体方法是:打开Domino安装目录下的notes.ini,将DIIOP到ServerTasks中,保存文件并重启DominoServer。
下面介绍如何获取DominoServer上用户的会议邀请等。前文已经提到,我们的应用中,一个重要功能是对SSO的支持。用户登陆了WebSpherePortal之后,我们需要根据WebSpherePortal上的登陆信息找到用户在DominoServer上的信息(MailServer和DIIOP端口是用户单独配置的,具体见创建Portlet小节),最后获取DominoServer上该用户的会议邀请纪录,这里主要包含几个重要的步骤:
获取LTPAcookie信息。清单1中变量sessionToken存储的值是LTPAcookie信息,将作为方法getItemByDateUsingLTPA(见清单3)的第二个参数来获取会议邀请纪录。
获取用户的Notes账号。清单3中开始部分根据LTPAcookie信息获取SessionnotesSession,然后根据语句notesSession.getUserName()来获取用户的NotesID。
获取用户的邮件在服务器上存放位置。一旦获得用户NotesID(DominoServer由用户自行配置),我们就可以通过清单2获取用户的邮件存放位置,返回的结果类似于“mail/test.nsf”。
获取用户的会议邀请纪录。清单3演示了如何通过LTPA信息来获取用户会议邀请条目。其中,CalendarItem存放的数据结构如清单4所示。
清单1.获取LTPAcookie信息
Cookie[]cookies=null;
StringsessionToken=null;
cookies=renderRequest.getCookies();
if(cookies!=null){
for(inti=0;i<cookies.length;i++){
if(cookies[i].getName().equals("LtpaToken")){
sessionToken=cookies[i].getValue();
break;
}
}
}
清单2.获取用户邮件存放位置
publicstaticStringgetMailFile(SessionnotesSession,
StringnameServer,Stringusername)throwsNotesException{
StringmailFile=null;
DatabasenameDB=notesSession.getDatabase(nameServer,"names.nsf");
if(nameDB!=null){
StringsearchCondition="Owner=\""+
username+"\"&Type=\"Person\"";
DocumentCollectiondc=nameDB.search(searchCondition);
if(dc!=null){
Documentdoc=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("\\\\","/");
}
}
}
returnmailFile;
}
清单3.获取用户会议邀请条目
/**
*Retrievethespecificcalendaritemslist
*@parammailServer:mailserverandDIIOPport,
*e.g.dominodemo.company.com:63148
*@paramltpaToken:LTPAtoken
*@paramstartDate:startdate,e.g."03/23/2009"
*@paramendDate:enddate,e.g."03/23/2009"
*@returncalendaritemslist.
*
*/
publicstaticList<CalendarItem>getItemByDateUsingLTPA(StringmailServer,
StringltpaToken,StringstartDate,StringendDate){
ArrayList<CalendarItem>list=newArrayList<CalendarItem>();
DatabasemailDB=null;
SessionnotesSession=null;
try{
notesSession=NotesFactory.createSession(mailServer,ltpaToken);
String[]tmpArray=mailServer.split(":");
Stringdirectory=getMailFile(notesSession,tmpArray[0],
notesSession.getUserName());
mailDB=notesSession.getDatabase(tmpArray[0],directory);
StringsearchCondition="@IsAvailable("+
NotesCalendarFields.calendarDateTime+
")&@IsMember(\""+startDate
+"\";@Explode(StartDateTime;\",\"))";
DocumentCollectiondc=mailDB.search(searchCondition);
Documentdoc=dc.getFirstDocument();
longstartDateTime=format.parse(startDate).getTime();
longendDateTime=format.parse(endDate).getTime();
while(doc!=null){
Vector<Object>vec=
doc.getItemValue(NotesCalendarFields.calendarDateTime);
for(inti=0;vec!=null&&i<vec.size();i++){
Datedate=((DateTime)vec.get(i)).toJavaDate();
longelem=date.getTime();
if(elem>=endDateTime)
break;
elseif(elem>=startDateTime){
CalendarItemcalItem=newCalendarItem();
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()));
URLurl=newURL(doc.getHttpURL());
//ForSSOreason,weneedtoreplaceit'shost
StringstrURL=url.toString().replaceAll(url.getHost(),
tmpArray[0]);
calItem.setHttpURL(strURL);
list.add(calItem);
}
}
Documenttemp=dc.getNextDocument();
doc.recycle();//recycletheonewe'redonewith
doc=temp;
}
}
catch(Exceptione){
e.printStackTrace();
}
finally{
try{
if(mailDB!=null)
mailDB.recycle();
if(notesSession!=null)
notesSession.recycle();
}
catch(NotesExceptione){
e.printStackTrace();
}
}
returnlist;
}
清单4.CalendarItem数据结构
publicclassCalendarItem{
privateDatestartDate;
privateDateendDate;
privateStringsubject;
privateStringdescription;
privateStringhttpURL;
/**
0-Appointment
1-Anniversary
2-AllDayEvent
3-Meeting
4-Reminder
*/
privateintcalType;
publicCalendarItem(){
subject="";
description="";
calType=0;
}
publicDategetStartDate(){
returnstartDate;
}
publicvoidsetStartDate(DatestartDate){
this.startDate=startDate;
}
publicDategetEndDate(){
returnendDate;
}
publicvoidsetEndDate(DateendDate){
this.endDate=endDate;
}
publicStringgetSubject(){
returnsubject;
}
publicvoidsetSubject(Stringsubject){
this.subject=subject;
}
publicStringgetDescription(){
returndescription;
}
publicvoidsetDescription(Stringdescription){
this.description=description;
}
publicintgetCalType(){
returncalType;
}
publicvoidsetCalType(intcalType){
this.calType=calType;
}
publicStringgetHttpURL(){
returnhttpURL;
}
publicvoidsetHttpURL(StringhttpURL){
this.httpURL=httpURL;
}
}
回页首
创建Portlet
完成上述几个步骤之后,接下来我们需要创建一个Portlet来显示日历,当用户点击某一日期时,Portlet能够调用清单2和3中的代码来获取用户的日历邀请条目并显示出来。能够创建Portlet的工具很多,IBM也不缺乏这样的工具,例如RationalApplicationDeveloper(简称RAD)。用RADV7创建Portlet十分简单,如图3和图4所示,创建一个名为PortletExmple的Portlet,选择查看和编辑两个视图。
在文件PortletExamplePortletEdit.jsp中添加2个编辑框,让用户输入:DominoServer,DIIOP端口(默认为63148)。另添加一个button按钮,能够让用户保存数据。如清单4所示。
在PortletExamplePortlet.java中定义变量如下:
publicstaticfinalStringmailServer="dominoCalendarmailServer";
publicstaticfinalStringportnumber="dominoCalendarportnumber";
publicstaticfinalStringsaveAction="saveaction";
在方法processAction中实现处理Portlet编辑视图中的按钮事件。代码如清单5所示。
接下来我们来介绍如何实现Portlet查看视图。在文件PortletExamplePortletView.jsp中,其主要功能是生成一个带有日历以及选定日期的页面。我们用preferences.getValue(String,“”)获取DominoServer以及其端口值,然后调用清单2方法getItemByDateUsingLTPA可以获取会议邀请信息列表,每条记录包含开始时间、结束时间、描述、主题以及iNotes上该条目的HTTP链接,效果图如图5所示。
图3.创建Portlet示意图1
图4.创建Portlet示意图2
清单5.Portlet编辑视图代码
<%@pagesession="false"contentType="text/html;charset=gb2312"
import="java.util.*,javax.portlet.*,com.company.*"%>
<%@tagliburi="http://java.sun.com/portlet"prefix="portlet"%>
<portlet:defineObjects/>
<%
PortletPreferencesprefs=renderRequest.getPreferences();
if(prefs!=null){
StringmailServerValue=
prefs.getValue(PortletExamplePortlet.mailServer,"");
StringportValue=prefs.getValue(PortletExamplePortlet.portnumber,"");
%>
<FORMACTION="<portlet:actionURL/>"METHOD="POST">
MailServer:<INPUTname="<%=PortletExamplePortlet.mailServer%>"
VALUE="<%=mailServerValue%>"TYPE="text"><BR>
Port:<INPUTname="<%=PortletExamplePortlet.portnumber%>"
VALUE="<%=portValue%>"TYPE="text"><BR>
<inputtype="submit"value="Save"
name="<%=PortletExamplePortlet.saveAction%>"/>
<%
}
%>
<inputtype="submit"value="Cancel"
onclick="javascript:location.href='<portlet:renderURLportletMode="view"/>';"
/>
</FORM>
<%
}else{
%>
Error:PortletPreferencesisnull.
<%
}
%>
清单6.Portlet编辑视图事件处理函数
publicvoidprocessAction(ActionRequestrequest,ActionResponseresponse)
throwsPortletException,java.io.IOException{
PortletPreferencesprefs=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(ReadOnlyExceptionroe){
}
catch(ValidatorExceptionve){
}
}
图5.Portlet运行效果图
回页首
结论
通过对上述实例的介绍,读者应该对如何实现LotusNotes/Domino与WebSpherePortal的集成有一个大概地了解。读者可以结合LotusNotes/Domino和WebSpherePortal的优点,开发出一些集成程序,更好的发挥它们的作用和价值,这也是本文的主要目的。