How To Use Custom Fonts On Your XPage With CSS – now with IE

Although I wrote in a previous article, that I would not give a shit about IE in my personal life any longer, I could not resist to find out how custom fonts can be used in the browser wannabe and how to convert an existing ttf font to something that the M$ crap could possibly handle.

M$ IE cannot handle a TTF file; it needs an EOT file instead. If your font does not come with different files for IE and modern browsers, you have to convert it. The easiest way I found to convert an existing TTF file is using a service on the web. I tried a few but had the best results.

Not only the font is converted into an EOT file ( plus SVG and WOFF ) , also the CSS is generated for you.

Just upload your TTF file and get the converted files in return.

/* Generated by Font Squirrel ( on September 30, 2012 */

@font-face {
font-family: "myFont";
src: url("accid___-webfont.eot");
src: url("accid___-webfont.eot?#iefix") format("embedded-opentype"),
url("accid___-webfont.woff") format("woff"),
url("accid___-webfont.ttf") format("truetype"),
url("accid___-webfont.svg#myFont") format("svg");
font-weight: normal;
font-style: normal;

font-family: myFont;
font-size: 3em;

I have tested with IE9 and it works. Not sure, if it will work in IE8 and less. It’s up to you to test and leave a reply …

How To Use Custom Fonts On Your XPage With CSS

With CSS (Cascading Style Sheets) you can use custom fonts on your Xpage. Normally you only see the fonts that are already installed on your computer. So if you use a font that is not installed on your XPage user’s computer then his or her browser will show some other font that exists on the computer. That’s why when you are defining a font for an element (such as <p>) you often specify multiple fonts so that if your preferred font is not available your CSS file should use the available alternatives.

Conventional way of using custom fonts for headings and logos etc. is creating the text in a graphic editor and then using the image file. From the perspective of SEO this is not appropriate; you must use text as much as possible.

Now there is a way around in CSS that lets you use custom fonts, downloadable fonts on your XPage. You can download the font of your preference, let’s say my_font.ttf, and import it as a file resource into your application.

Then from within your CSS file (or wherever you are defining your styles) you have to refer to that font in the following manner:

@font-face {
font-family: my_font;
src: url("accid___.ttf");

After that you can use it just like a normal CSS declaration. Here is en example for an xc:label control:

font-family: my_font; /* no .ttf */
font-size: 2em;

This method works in all modern browsers, except IE ( no surprise is that ).
This is because Internet Explorer does not recognize TTF / OTF, it uses a proprietary format called EOT. To make your @font-face declaration works with IE as well, you must prepare two font files, one in TTF / OTF format and the other one in EOT format. To learn more about EOT, and how to convert TTF / OTF to EOT, please refer to this article.

I have decided not to give a shit about IE when blogging.

Display Stackoverflow entries on an XPage

With just a few lines of code, you can display entries from Stackoverflow on an XPage in your custom application. I’ve used  the StackUnderflow library, that is available from here.

StackUnderflow.js is a lightweight JavaScript library that makes retrieving and rendering question summary information from StackExchange sites simple. It supports retrieving questions by Question ID, tags, keyword, and even by Google search results to enable you to search the body of questions, even though the StackExchange API does not support it (currently limited to 8 results).

Here is the code that is needed to render the output


Wrap The Items In A xe:djextListTextBox

We use xe:djextListTextBox in our application to display and edit lists of keywords and we ran into the problem, that the list does not automatically breaks to a new line when the overall length exceeds the table cell the xe:djextListTextBox is placed into.

But with only a little CSS magic, posted by Martin Jinoch on StackOverflow, the issue is no longer an issue.

Simply wrap the xe:djextListTextBox with an div and assign a styleclass to the div. (i.e. myInlineList )

In your CSS file have an entry

.myInlineList span span {

When you now relod the page, the keywords now automatically break and are displayed in a new line.

IBM Connections, a cornerstone of IBM’s social platform

Available on premises, in the cloud, and on a broad range of mobile devices, IBM Connections integrates activity streams, calendaring, wikis, blogs, a new email capability, and more, and flags relevant data for action. It allows for instant collaboration with one simple click and the ability to build social, secure communities both inside and outside the organization to increase customer loyalty and speed business results. The new Connections mail capability provides simplified access to email within the context of the social networking environment.

Now, organizations can integrate and analyze massive amounts of data generated from people, devices and sensors and more easily align these insights to business processes to make faster, more accurate business decisions. By gaining deeper insights in customer and market trends and employees’ sentiment, businesses can uncover critical patterns to not only react swiftly to market shifts, but predict the effect of future actions.

“I am thoroughly enjoying the ability to engage with a variety of employees through micro-blogging,” said Patrick Thomas, CEO, Bayer MaterialScience. “I can get information out quickly, but even more importantly I can encourage two way communication and stimulate an open communication culture by breaking through barriers.”

The new capabilities empower employees from every line of business, such as marketing, human resources and development to gain actionable insight into the information being generated in their social networks.

For example, the Connections landing page features a single location that allows users to view and interact with content from any third party solution through a social interface, right alongside their company’s content, including email and calendar. The embedded experience of the news feed, also known as an activity stream, allows employees from any department inside an organization to explore structured and unstructured data such as Twitter feeds, Facebook posts, weather data, videos, log files, SAP applications, electronically sign documents, and quickly act on the data as part of their everyday work experience.

To learn more about IBM’s social business initiative, participate in a simulcast on September 13, 2012 at  1 PM ET at or sign-up to attend IBM’s Connect conference (t.c.f.k.a. Lotusphere ) in January 2013.

For more information, please visit

Use RegExp with JavaScript split()

Here is a short snippet the came out of a forum post here.

I you have a string that, for whatever reason, is concatenated using different delimiters, you can use regexp with javascript split() to build an array of single values.

var s = "one#two#three~four~five";


The output will be an array containing 5 elements

Simple example of Windows native library declaration and usage in XPages

I would like to share a simple sample on how to access (Windows) DLLs from Java / XPages.

Java’s JVM allows you to do many smart things but sometimes you may be forced to directly use external library or writing code in pure java would be very time-consuming comparing it with something more low-leveled.

So, how does it work? The only thing you have to do is to download and import JNA (Java Native Access) to your project and write a simple class.

package de.eknori.c;

import com.sun.jna.Library;
import com.sun.jna.Native;

public class Beeper {
	private Kernel32 lib;

	public interface Kernel32 extends Library {
		// FREQUENCY is expressed in hertz and ranges from 37 to 32767
		// DURATION is expressed in milliseconds
		public boolean Beep(int FREQUENCY, int DURATION);

		public void Sleep(int DURATION);

	public Beeper() {
		lib = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);

	public void test() {
		lib.Beep(500, 500);
		lib.Beep(1000, 500);

From your XPage you can now make a call to the class in a button

var beep:de.eknori.c.Beeper = new de.eknori.c.Beeper();

For a simple beep, this solution might be a bit of an overkill; but imagine what else you can do with it. Accessing elements in an application using the C-API for example. 🙂

Setting Page Generation Properties to HTML5

I’m playing around with bootstrap. Bootstrap makes use of certain HTML elements and CSS properties that require the use of the HTML5 doctype. To set the doctype in your XPages project do the following:

  • Open Package Explorer
  • Open under WebContent -> WEB-IN
  • Navigate to the Page Generation Properties tab
  • Set the value in HTML doctype
  • Save the changes


Domino Designer – Initially Collapse Comments

If you write tons of code in Java and Javascript, you probably have a huge number of comments in your code. If not, stop reading and review your code …

Sometimes it is a bit annoying when you scroll thru your code looking for a certain piece of code and you also have to scroll thru all the comments. here is a quick tipp that can make your life earsier.

Open the preferences dialog in Domino Designer and search for “Folding” There are two sections for Java and Javascript, where you can configure if comments should be initially collapsed.

Weird issue resulting in application getting corrupt

I had a very bad start into this week. On last week friday, I made some changes to our CRM project. The changes were mostly some modifications to a variable resolver. I removed redundant code by moving some parts of the code to methods within the resolver code. I also added two new methods to an existing bean. All this is far away from rocket science. I then changed the home.xsp to use the new methods from the bean.

After opening the application in the browser, everything looked fine. I refreshed the application in the browser and … BOOOOOOOMMMMMMMMM.

Last thing, I could see on the server console was

err_protected> ERR_PROTECTED ERROR: D:\Programme\IBM\Lotus\Domino\data [nsfsem2.c/ln 1684]
err_protected> ERR_PROTECTED ERROR: D:\Programme\IBM\Lotus\Domino\data [nsfsem2.c/ln 1684]

then the server crashed. I restarted the server and tired again. Same result. Application could be opened and crashed after any other action. To be sure, I removed my modifications. But the server still crashed. I tried everything from compact, fixup , replacing the design with the design of a working copy and even creating a new copy of the application. But nothing helped. The error persists.

The strange thing is, that I could/can open the application in question in Designer and make changes, add, update and delete data documents. The crash only occurs, when working in the browser.

I then replaced the corrupt file with the working copy and everything worked as expected. We made some other modifications to the design and the application stayed stable. Before driving home, I made a copy and put the file onto my Domino at home. As expected, everything was fine.

I then started to implement the same modifications that ended in the file becoming corrupt. And yes, I was able to reproduce the issue.

Phil Riand asked me to send in any crash report and the code that caused the error. I sent him an email yesterday morning. During the night, Phil sent a reply. here is wahat he wrote:

Hey Ulrich,

…. The issue you mention is definitively down in the NSF layer, in the semaphore management code. So I forwarded that to the appropriate team internally, and hope to get feedback soon. The issue might not even happen because of your database, and probably not because of your changes.

This is good news and bad news. Good news because there is something wrong, and it is reproducable. Bad news because if it is not in the database nor in the changes, it can happen again any time. So I hope, that IBM will find the cause and fix it.



XPages – Print RichText to PDF

With iText it is fairly easy to create PDF documents from Notes Documents in the browser. I have already written an article on how to do this.

Today I would like to share a small piece of code that lets you convert NotesRichText into PDF.

The download contains all the neccessary elements.

If you want to use the code in your own application, make sure that the “Store content as HTML and Mime” is checked for your RTItem.

“Create PDF” – Button code:

de.eknori.HTML code:

The result:

It’s not perfect. Embedded images do not work and aslo some styles do not convert well. This does not mean that it is impossible, but you have to write a few extra lines of code to make it work.



Domino Designer Performance – Check your AV

Ok, here is the story. My team and I had a very bad day yesterday. We were not able to work on our project because Domino Designer decided to take more than an hour for the build process. I tried to find out, what was wrong. My other team members in the head office did not reported this issue. So I had a weird network issue in mind bacause the issue occurred on all machines in the brnch office but was not able to find out any hint, what caused Designer to obviously wait for some action to complete when building the project. Even changing the code in a Java class was not possible. Each keyboard action took some seconds up to minutes to reflect the changes.

We are all working on local replicas of the files. And, it worked the day before … So WE did not change anything on the machine. Aside from this, we, the developers do not have proper rights to change ANYTHING on the machine. The is done by our friends, THE ADMINS.

Today, I saw a message when starting my computer that the Sophos AV has been successfully updated some files. Never seen that before … I decided to take also AV in consideration and looked into the settings. And there it was. “SCAN ALL FILES” and “SCAN IN ALL DIRS”. Exclusions? Well …. NO.  I managed to tweak the settings to exclude the Notes dir. And, what do you think? Right, everything now works at full speed again.

Shall I say “Thank you, admins” ?

Getting ‘JDBC driver not found error’ while trying to connect DOMSQL from crystal through jdbc

I could do with some help as i’m pretty well stuck.

I’m trying to connect crystal report 11.5 ( XI R2 )  developer to DOMSQL on a remote server via jdbc.

I have copied into “C:\Program Files\Common Files\Business Objects\3.0\java\lib\external”

I then opened the CRConfig.xml in “C:\Program Files\Common Files\Business Objects\3.0\java\lib” and added “C:\Program Files\Common Files\Business Objects\3.0\java/lib/external/;” after the last semicolon just before ${CLASSPATH}

I then open Crystal reports, standerd report wizard, create new connection, JDBC (JNDI), I then enter my DB URL: “jdbc:domsql://serv01/cois_v2/cois_crm.nsf/crm” and driver class “”.

Then next, username and password. When I try to connect, I get the error:

Failed to Open Connection
Details: JDBC Driver not found

Any idea? I think I’ve done everything right

 UPDATE: The problem is in the JDK that is installed with CR.  I have installed an updated version of the Java JDK (c:\jdk) and changed the path for JavaDir in CRConfig.xml. Now I am able to connect to the DomSQL server

UPDATE 2: I have also successfully tested with JRE instead of JDK. here is the exact version, I used

java version “1.6.0_24”
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode)

What I was working on recently

Aside from doing a lot of XPages development, I recently worked on a tool to add mail signatures. The aim was to provide a solution that adds the signatures on a server to avoid to push information to the profile in the users mailfile.
Using a server based solution also makes sure that the signature will be added to any kind of outgoing mails, regardless if it is send from the Notes Client, WebMail or a mobile device.

A signature configuration can be used for an individual user ( or group of users ), a department ( */dev/emea/us ) or fo all users in the company. Within the signature configuration you can use placeholders that are filled at runtime. You can also use a log0, that can be prepended or appended to the signature. You can also use the logo anywhere inside your signature using a {{LOGO}} tag.

This gives you a high grade of flexibility creating the signature.


There can be another signature that is used when sending mails internally.

Signatures are designed using a RichText item; the content is then “translated” to HTML. If you are familiar with HTML/CSS, you can create and style your signature in the HTML item directly.

The tool runs on Windows 2003/2008 32/64bit and Linux ( tested with SLES 11/32Bit )

@Formula Snippet – Strip leading zeros from @NoteId

We use @NoteId in a view to get the NoteId of a document and display the value in a column. Via NotesNavigator, we access this column ( and others ) Unfortunately, the value, that is returned by the formula is something like NT0000903.

When we pass this value to our function, to open the document in a tabContainer, it fails because the function excepts only the number part wthout the NT and leading zeros. ( = 903 ). So I was looking for a way to stip the unwanted part from the string.

Here is, what I came out with

@Do(tmp := tmp;@While(@Length(tmp) > 1 & @Begins(tmp; "0");tmp := @Middle(tmp; 1; 8));tmp) ;

If there is a better solution, let me know. We tried many things, but to go thru the value from left to right and checking, if the string begins with a “0” seems to be the best way to achieve the aim.

Notes C API – LNK4070 and LNK4199 warnings in compiler

Recently, I had to work with the C-API. Aside from having some problems to compile, link and successfully run the extension manager from the sample code that comes with the Notes C-API, I always got the warnings mentioned in the subject of this article.

1. warning LNK4070: /OUT:ntrigger.dll directive in .EXP differs from output filename ‘output\w32\ntrigger32.dll’; ignoring directive

This is an easy one to fix. Just make sure that the LIBRARY statement in your exports.def has the same value as the output file. So my exports.def contained LIBRARY “ntrigger” ( which was correct at some point of the dev process ) But I changed the output to ntrigger32.dll. So changing ntrigger to ntrigger32 in exports.def will stop the warning from being displayed.

2. warning LNK4199: /DELAYLOAD:OleAcc.dll ignored; no imports found from OleAcc.dll

This warning seems to be a common one and can be ignored. But I do not like to see warnings or errors during the build process. After doing a little research, I finally found the cause and how to avoid the warning.

First I thought that putting OleAcc.dll as an ignored DLL into the “Ignore Specific Lirary” field in the Linker –> Input section of the project properties would do the trick. But then you will get another warning along with the LNK4199 warning.

In the project’s properties Linker –> Input section, click on the button on the Delay Loaded  DLL. You can see a inheritance of OleAcc.dll. Uncheck the inheritance button. It’ll make it.

No more warnings …

[Book Review] – Schrei unter Wasser

Bei Büchern, die als Bestseller bezeichnet werden, bin ich immer sehr vorsichtig. Oft genug wurde ich enttäuscht und die so hoch gelobten Bücher entpuppten sich als Langewiler erster Güte.
Ich bin ehrlich und gebe zu, daß meine Erwartungen an dieses Buch auch nicht besonders hoch waren. Aber irgend einen Lesestoff braucht man ja im Urlaub. Das Buch wurde auf einslive angekündigt und hat allein deshalb meine Aufmerksamkeit geweckt, weil die Handlung im Norden spielt und ich schon mehrere schwedisch/dänische Krimiverfilmungen gesehen habe, die immer sehr spannend waren.

Schrei unter Wasser baut auf ein gängiges Schema auf. Ein Mord, mehr oder weniger intelligente Ermittler, und irgendwann im Laufe der Erzählung wird der Fall gelöst.

Und doch ist Schrei unter Wasser etwas anders gestrickt. Gleich zu Beginn wird in einer Art Rückblende die glücklicherweise nicht vollendete Ermordung eines Kleinkindes geschildert. Diese Rückblenden erscheinen mehrfach im Laufe der Erzählung. Zwar erkennt man den roten Faden der Entwicklung des Kleinkindes zur erwachsenen Frau, doch ist eine zeitliche Einordnung der Geschehnisse in die eigentliche Geschichte nicht möglich. Die Autoren achten peinlich genau darauf, nicht zu viele Details zu verraten.
Und kaum glaubt der Leser, die Geschichte nun in allen Zügen verstanden zu haben, schon wird er auf den nächsten Seiten eines Besseren belehrt, nimmt die Geschichte doch eine Wendung in eine Richtung, die der Leser nicht erwartet hat.

Schei unter Wasser hat einen lebendigen Erzählstil. Die Einzelheiten der Ermittlung sind in sich schlüssig. Auch hier achten die Autoren sehr genau darauf, den Leser zwar bei der Stange zu halten, aber nicht zuviel zu verraten.
Ohne die Spannung zu nehmen sei soviel verraten, daß man auch als gewiefter Krimileser bei einer überschaubaren Anzahl von Verdächtigen nicht auf den wahren Täter kommt. Zwar hegt man einen Verdacht, doch will es nicht gelingen, das Motiv zu entschlüsseln.

Erst auf den letzten 40 Seiten wird Story in einem dramatischen und temporeichen Finale aufgelöst. Unaufgelöst bleibt allerdings das Schicksal des zunächst des Mordes Verdächtigten.

Schrei unter Wasser ist empfehlenswerter Lesestoff. Es bleibt abzuwarten, wann die Geschichte verfilmt wird. Die Story taugt gut und gerne für 90 – 100 Minuten und wird so manche deutsche Tatort Produktion in den Schatten stellen.

Review: XPages Extension Library from IBM Press

Over the past few days I managed to read the “XPages Extension Library” book that has recently been published by IBM Press. The list of authors, contributing authors, technical editors and others reads like a who-is-who in XPages.

I’m very proud to know many of them and also had the chance to attend their sessions at conferences.

The book is very up-to-date, it targets the December 2011 release of the ExtLib, be it in the form of the Notes and Domino 8.5.3 Upgrade Pack 1 or as download of the ExtLib from OpenNTF.

The samples in the book refer to the teamroom template and the ExtLib sample application. So I recommend to download the latest ExtLib from OpenNTF as the download contains both templates.

The aim of the “XPages Extension Library” book is to collate the knowledge of the ExtLib and communicate it to the reader.

Although all authors have a different style of presenting content during conference sessons, the book reads in a very consistent way.

To get the most out of the book, you should at least be familiar with the XPages basics and perhaps, you already have read the Mastering XPages book that will give you a firm ground to understand the ExtLib.

“XPages Extension Library” from IBM Press is a must have, must read.

I strongly recommend that this book, together with Mastering XPages and XPages Portable Command Line Guide should be given to every developer starting with XPages.


xGrid And Performance Optimization

Yesterday, I took a closer look at the xGrid custom control, that has recently been posted on OpenNTF by Pablo Solano.
The control uses jqGrid, a jQuery plugin. It lets you display data from a view in a grid. jqGrid has some very nice features. For more details take a look at the demo page.
The download from OpenNTF also contains a set of demo data ( 40.000 person documents ).

I copied the sample application to my server ( Domino 8.5.3 64bit, 16GB RAM, 4 Core AMD ), opened every view in client to create the indexes, signed application and finally opened xContactsSSJS.xsp in Firefox 12.

Next, I took a closer look at the design.

xContactsSSJS.xsp contains a duplicate line of code, which can be deleted
var docs:NotesDocumentCollection =;


Although the grid was rendered almost immediately in the browser, I wanted to do some time measurement to see how long the retrieval of 40.000 documents would last and if there is some room for optimization.
So I added two lines of code into xJsonContacts.xsp at the beginning and the end of the code that simply calculates the time difference in milliseconds from start to end.

	var start = new Date().getTime();
	var externalContext = facesContext.getExternalContext();
	var writer = facesContext.getResponseWriter();
	var response = externalContext.getResponse();

	// Set content type
	response.setHeader("Cache-Control", "no-cache");

	// Get all Contacts
	var query = 'Form = "Contact"';

	var docs:NotesDocumentCollection =;

	json = "";
	var doc = docs.getFirstDocument()

	while (doc != null) {
		json = json + '{"@unid":"'+ doc.getUniversalID() + '","FirstName":"' + doc.getItemValueString("FirstName") +
		 '","LastName":"' + doc.getItemValueString("FirstName") +  '","State":"' + doc.getItemValueString("State") +
		 '","City":"' + doc.getItemValueString("City") + '"},'		

		// Get next doc and recycle
		tempdoc = docs.getNextDocument();
		doc = tempdoc;

	json  = "[" + @Left(json, @Length(json) - 1) + "]";	

	var elapsed = new Date().getTime() - start;
	print("xContactsSSJS.xsp ->" + elapsed +" ms");

} catch(e){

I then opened the page 10 times in the browser. here are the results

The code builds a JSON string at runtime. So, for every element, it has to access a document from the document collection and get the item values one after the other from the document.

I changed the code; first of all, I copied the Contacts view an deleted all columns except one. I put the following code into the column formula.


+ @Implode (
@Transform (
_fld; "_fn" ; "\"" + _fn + "\":\"" + @Text ( @GetField ( _fn) ) + "\"" ) ; "," ) + "},"

The formula computes a JSON string for every document in the view. This avoids the need to build the string at runtime in javascript.

The code for the XAgent looks like this:

	var start = new Date().getTime();
	var externalContext = facesContext.getExternalContext();
	var writer = facesContext.getResponseWriter();
	var response = externalContext.getResponse();

	// Set content type
	response.setHeader("Cache-Control", "no-cache");
	json = ""
	  var v:NotesView = database.getView("ContactsSingleCol");
	  //do not do AutoUpdates
	  v.AutoUpdate = false;
	  var nav:NotesViewNavigator = v.createViewNav();
	  //enable cache for max buffering
	  nav.BufferMaxEntries = 400
	  var entry:NotesViewEntry = nav.getFirst();

	  while (entry != null) {
	    json=json + entry.getColumnValues().elementAt(0).toString();
	    var tmpentry:NotesViewEntry = nav.getNext(entry);
	    entry = tmpentry;

  	writer.write('[' + @Left(json, @Length(json) - 1) + ']');
	var elapsed = new Date().getTime() - start;
print("xContactsSSJSViewNav.xsp ->" + elapsed +" ms");

} catch(e){

As you can see, the code uses a NotesViewNavigator to iterate thru the view entries and concat the values from the first column of the view containing the pre-build JSON string.

Once again, I opened the page in the browser; here are the results from my simple time measurement.

Conclusion: Building the JSON in advance and using a NotesViewNavigator speeds up the loading of the data.

In the above code, the new value is added to the existing JSON String using the “+” sign. Using the ‘+’ operator for concatenation isn’t bad per se though.

It’s very readable and it doesn’t necessarily affect performance. Each time you append something via ‘+’ a new String is created, the old stuff is copied, the new stuff is appended, and the old String is thrown away. The bigger the String gets the longer it takes – there is more to copy and more garbage is produced.

An alternative way to concat strings is using a java.lang.StringBuilder. As you might know, you can use Java in your server-side javascript.

xJsonContactsViewNavSb.xsp shows, how to use a stringbuffer

	var start = new Date().getTime();
	var externalContext = facesContext.getExternalContext();
	var writer = facesContext.getResponseWriter();
	var response = externalContext.getResponse();

	// Set content type
	response.setHeader("Cache-Control", "no-cache");

	  var json:java.lang.StringBuilder = new java.lang.StringBuilder();
	  var v:NotesView = database.getView("ContactsSingleCol");
	  //do not do AutoUpdates
	  v.AutoUpdate = false;
	  var nav:NotesViewNavigator = v.createViewNav();
	  //enable cache for max buffering
	  nav.BufferMaxEntries = 400
	  var entry:NotesViewEntry = nav.getFirst();

	  while (entry != null) {
	    json.append( entry.getColumnValues().elementAt(0).toString());
	    var tmpentry:NotesViewEntry = nav.getNext(entry);
	    entry = tmpentry;

  writer.write('[' + @Left(json.toString(), @Length(json.toString()) - 1) + ']');
	var elapsed = new Date().getTime() - start;
print("xContactsSSJSViewNavSb.xsp ->" + elapsed +" ms");

} catch(e){

Opening the page in the browser shows the following results

Impressive, isn’t it?

As a fazit, even in XPages programming there is room for views and @formulas.

Uses these elements to pre-calculate values and move away this work from the runtime. Use a NotesViewNavigator to access data from the view. Read this article to find out more about NotesViewNavigator.
Conclusion: If you have to concat a large number of strings, use a java.lang.StringBuilder instead of the “+” operator.

Having done all these steps to optimize performance, it is only a small step to use Java instead of javascript to do the heavy lifting.

Here is the code from xJsonContactsJava.xsp

	var start = new Date().getTime();
	var externalContext = facesContext.getExternalContext();
	var writer = facesContext.getResponseWriter();
	var response = externalContext.getResponse();

	// Set content type
	response.setHeader("Cache-Control", "no-cache");
	var out:de.eknori.ViewColumn = new de.eknori.ViewColumn();
	var elapsed = new Date().getTime() - start;
	print("xContactsSSJSJava.xsp ->" + elapsed +" ms");

} catch(e){

The getViewColumnValueJSON() method is located in the de.eknori.ViewColumn class.

package de.eknori;

import static;
import lotus.domino.NotesException;
import lotus.domino.View;
import lotus.domino.ViewEntry;
import lotus.domino.ViewNavigator;

public class ViewColumn {
	private static final String MSG_STRING_ERROR = "ERROR: ";
	private static final String MSG_STRING_NOT_FOUND = " not found";

	public ViewColumn() {

	public String getViewColumnValueJSON(String viewname, int pos) {
		ViewNavigator nav = null;
		StringBuilder json = new StringBuilder();
		String strValue = "";
		try {
			View view = getCurrentDatabase().getView(viewname);
			if (null != view) {
				nav = view.createViewNav();
				ViewEntry entry = nav.getFirst();

				while (entry != null) {
					ViewEntry tmpentry = nav.getNext(entry);
					entry = tmpentry;
				strValue = json.toString();
				strValue = strValue.substring(0, strValue.lastIndexOf(","))
						+ "]";
			} else {
				System.out.println(MSG_STRING_ERROR + viewname
		} catch (NotesException e) {
			strValue = "[{}]";
		return strValue;

As you can see from the entries in the screenshot, there is another gain in performance when using Java.

If your application has a large amount of data, I strongly advice to use Java instead of JavaScript.

I’m doing Java for no longer than 6 month by now. If you are familiar with LotusScript, you will be able to learn the basic java stuff real quick. There is no excuse to not start learning Java right now.

You can download the application including my modifications here.  (design only!)