Integrating a Lotus Notes application with Exchange

I recently finished a project with the purpose of integrating a Lotus Notes CRM application with Microsoft Outlook and Microsoft Exchange. The customer has moved their mail handling to Exchange and Outlook and still uses Lotus Notes for their application handling including this CRM application. The CRM application had functionality to import mails from Notes, send mail from Notes, and create and maintain meeting invitations. My task was to make this functionality work with Exchange and Outlook instead.

In order to integrate with Exchange I used the Exchange Web Services (EWS) Java API and created a Java class with the necessary jar files imported that is responsible for the interface between the existing Lotusscript logic and the EWS API. The Lotusscript logic then uses LS2J to use the methods in the Java class.

With Exchange Web Services installed on the Exchange server the Java API can access the web services using the WSDL at /EWS/Service.wsdl (through an endpoint called /EWS/exchange.asmx).

To allow the Lotus Notes client to communicate with the Exchange server I needed to change the java.policy file in order to add: permission java.net.NetPermission “setCookieHandler”, “write”;. To automate this I used this Lotusscript code by Darren Oliver that checks the java.policy file for a specific permission policy and if not found adds the permission policy.

At first I wanted to use Exchange Impersonation to allow a single Windows Active Directory account to be able to act on behalf of others users on a Exchange mailbox. This decision was later changed to use the individual users own credentials. The user is prompted for their password and this is stored encrypted for their use only in a profile document. The following code snippet shows how communication with the Exchange server is set up in Java using the EWS API:

service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
// service.setTraceEnabled(true); // enable to trace the web service communication in the Java debug console
service.setUrl(new java.net.URI(server));
ExchangeCredentials credentials = new WebCredentials(userid, password);
service.setCredentials(credentials);

A meeting is simply created using the Appointment class. Time zone support is achieved by using UTC as the time zone for date details. To format dates as UTC I used the LSGMTTime  property of the NotesDateTime class.

Appointment appointment = new Appointment(service);
appointment.setSubject(subject);
appointment.setBody(MessageBody.getMessageBodyFromText(body));
appointment.setStart(formatter.parse(startDate));
appointment.setEnd(formatter.parse(endDate));
appointment.setLocation(location);
// Save as appointment - and not as a meeting with participants
appointment.save(SendInvitationsMode.SendToNone);

Importing mails is done by presenting the user with a list of mails from the users Exchange mailbox. The list is retrieved by looping through the Inbox folder:

ItemView view = new ItemView(100);
view.getOrderBy().add(ItemSchema.DateTimeReceived, SortDirection.Ascending);
FindItemsResults<Item> findResults;
findResults = service.findItems(WellKnownFolderName.Inbox, view);
service.loadPropertiesForItems(findResults.getItems(), new PropertySet(BasePropertySet.IdOnly, EmailMessageSchema.Subject, EmailMessageSchema.DateTimeReceived, EmailMessageSchema.Sender));

The user then selects a mail from the list and the corresponding mail in Exchange is retrieved with the unique item id as identifier.

EmailMessage message = EmailMessage.bind(service, new ItemId(mailItemId));

Rich text support between Notes and Outlook is handled using Lotusscript stream and mime classes:

Set stream = session.CreateStream
Call stream.WriteText(mailBody)
Set mime = doc.CreateMIMEEntity("Body")
Call mime.SetContentFromText (stream, "text/html;charset=UTF-8",ENC_NONE)

When sending mails from the Notes CRM application the user can access their Outlook contacts. The list of Outlook contacts is retrieved by looping through the Contacts folder:

ItemView view = new ItemView(2000);
view.getOrderBy().add(ContactSchema.DisplayName, SortDirection.Ascending);
FindItemsResults<Item> findResults;
findResults = service.findItems(WellKnownFolderName.Contacts, view);

The Microsoft Outlook client is launched when a meeting invitation is created in order for the user to finish the meeting invitation in Outlook. This is achieved by using the Shell Lotusscript command together with the fact that Outlook can be launched with a parameter that indicates what item to open when launched:

Shell( getOutlookPath() + " /select outlook:" + Ucase(doc.OutlookUniqueId(0)) )

The use of LS2J led to some performance issues at the customer site in the form of 10-20 seconds load times before a document was opened. The reason for this is that the Java code is extracted to disk whereby the Antivirus program at use at the customer site started to check all files for virus before the document could be opened. The customer modified the Antivirus settings to remove this check whereby the documents opened within reasonable time again.

DanNotes: The 46th Danish LUG conference is in November

DanNotes is the Danish Lotus user group. It started as a Lotus user group back in 1993 and has since then organized 2 day conferences for the Danish Lotus community with a schedule of 2 a year. The next conference in November is conference number 46! That’s an impressive number of conferences.

I am proud to have been selected as member of the board at the spring conference in May and I am thereby part of the group of organizers that plan the next conference.

I am really looking forward to meet Anders Holm Petersen who is the new country manager for IBM Collaboration Solutions in Denmark, to meet our great lineup of speakers: Niklas Heidloff, Stuart McIntyre, Ulrich Krause, and Chris Connor – and also to meet the many members of the Danish Lotus community.

If you are interested in joining the conference, then head over to the DanNotes website and register. There is a LinkedIn event and a Lanyrd event for the conference if you are interested in tracking the conference using social tools.

PHL Consult supports OpenNTF and open source

My company, PHL Consult, became member of OpenNTF in August and thereby supports OpenNTF and the use of open source within the Lotus Domino/XPages community. This means that I support the idea of open source in general (and support OpenNTF as an organization) – and that I both contribute code to and reuse code from OpenNTF. I have so far contributed 2 open source XPages custom controls to OpenNTF:

At the time of writing this blog post OpenNTF has 23 company members. Members according to OpenNTF are “companies with the common interest to provide open source for IBM Lotus Notes and Domino and to encourage broad industry use of these applications. To achieve these goals members are willing to devote resources or participate in other ways”.

I am teaching two XPages courses in August

I will be teaching two 3-day courses in August, 2011 on basic XPages application development. The courses are arranged by Intravision.

The first 3-day course starts August 23 at IBM in Lyngby. Seats are still available if you are interested in signing up for the course. Please see the course details (in Danish) for more information on how to sign up.

The second 3-day course takes place the week after and is a closed course for a group of developers from the same company.

XPages: only show content for authorized users

Today I was asked: how do you make sure that anonymous users do not see content that only logged on (and thereby authorized) users must see?

I often use a simple solution of having a xp:panel for anonymous users and another xp:panel for authorized users (both on the same XPage). Only one of the two panels are rendered based on whether the user is logged or not. So the two xp:panels would look like this:

Panel 1: for anonymous users

<xp:panel>
<xp:this.rendered><![CDATA[#{javascript:@UserName() == "Anonymous"}]]></xp:this.rendered>
You must log on to see contents.
</xp:panel>

Panel 2: for authorized users

<xp:panel>
<xp:this.rendered><![CDATA[#{javascript:(@UserName() != "Anonymous"}]]></xp:this.rendered>
This is the secret content.
</xp:panel>

You can combine this with the XPages Dojo Login Custom Control available on OpenNTF so that the user can stay on the page when logging on instead of going to a seperate login page.

XPages Web Analytics custom control on OpenNTF

What a great weekend for open source contributions from me! 🙂 Yesterday I created the XPages SEO custom control – and today I have created a new XPages custom control for the OpenNTF development contest called XPages Web Analytics custom control: the custom control makes it easy to add web analytics to your XPages web site.

In the first release the custom control supports Google Analytics and Woopra Web Analytics.

In order to use the custom control you download it from OpenNTF, unzip the downloaded file and open the included Notes database. In the database you will find a custom control called “WebAnalytics” that you can include in your own XPages application. Once included you just drag the custom control to your XPage and add the custom properties for the specific web analytics providers that you would like to use.

XPages SEO custom control on OpenNTF

I have contributed to the OpenNTF development contest by creating an open source XPages Custom Control for Search Engine Optimization (SEO). The custom control makes it easy to add the following search engine friendly tags to your XPages web site:

  • page title
  • meta description
  • meta robots
  • meta keywords

With these SEO tags bundled in a custom control it also increases your chances of remembering to add these tags to your XPages web pages 🙂

Installation is easy:
Just download the SEO custom control, unzip the downloaded file and open the included Notes database. In the database you will find a custom control called “SEO” that you can include in your own XPages application. Once included you just drag the custom control to your XPage and add the custom properties for the specific XPage (either as static or computed values).

Controlling the HTTP response status code in XPages

This is a follow-up to my post on how to create custom 404 and error pages in XPages.

A very useful improvement to catching controlled errors such as “page not found” errors is to send the related HTTP status code in the response. So for “page not found” errors the HTTP response code 404 should be sent. This helps search engine crawlers understand that the page is not available whereby the search index can be updated accordingly.

The HTTP status code can be controlled with the facesContext response object by using setStatus. The following code example will generate a HTTP status code of 404 when added to the afterRenderResponse event of an error message XPage. The code example assumes that the source XPage sets the requestScope statusCode variable to “404” if the source XPage fails to find a document:

try {
	// The external context gives access to the servlet environment
	var exCon = facesContext.getExternalContext();

	// The servlet's response, check the J2EE documentation what you can do
	var response = exCon.getResponse();

	// Return HTTP status code 404 if necessary
	if (requestScope.statusCode = "404") {
		response.setStatus(404);
	}

	facesContext.responseComplete();
} catch(e) {
	_dump(e);
}

Client project: XPages CMS for company website

My company PHL Consult completed another client project last week involving XPages. The purpose of the project was to modernize an existing Lotus Domino company website by creating a new XPages solution with a related Lotus Notes client CMS for article editing and related content handling (such as menus, graphics, and meta data) – and by using XPages to allow the website to utilize CSS for cross browser compatibility.

The client is Mediaplus.dk and this is an interesting company that takes advantage of Lotus Notes and Domino to offer a CRM solution called Mediaplus CRM targeted at supermarket and grocery store suppliers.

The Mediaplus.dk website

The design for the website was created by Thomas Arendt from Make Your Mark. Based on his design guide I was then responsible for creating the necessary CSS to allow the design to be implemented. The CSS extends the IBM OneUI v2 CSS (although you need to look in the HTML and CSS source to tell).

The CMS includes functionality to improve search engine ranking by providing a sitemap for e.g. Google Webmaster Tools, by using meta tags such as description and robots and by providing useful page titles. These are all small but useful extensions to a website if you want to improve search engine rankings.

DanNotes – Danish Lotus User Group – 45th conference

DanNotes logo

The Danish Lotus user group DanNotes is hosting its 45th conference on May 11 and May 12, 2011.

I am participating in the conference as a member since PHL Consult is a member of DanNotes. I have created a LinkedIn event for the conference. Will I see you there?

Update May 9: I have accepted to be the moderator for the Developer BOF session on Thursday. I am looking forward to a great discussion of developer topics.