Working with JSON in your XPages application


In order to develop more inline with leading web standards more and more Domino and XPages developers find themselves attracted to use JSON as the standard to describe and transport their application data.

There are many excellent JSON libraries out there. With XPages we have immediately access to

I intend to write a series of posts and tell how I will rewrite an existing XPages application and introduce Java and JSON as the new working horses in this application.

JSON and XPages

More people have written about JSON in XPages so I do not have to deep dive in that. I especially like Jeff Byrd’s post on using the JSONJavaObject class to create a JSON object from an array.

A simple first example

First let me demonstrate a simple example. We setup a simple construction we will extend in the following steps of our application modernization.

Building blocks

Here is what our construction will contain:

  • a Notes view with a first column for sorting and a second column containing a JSON string
  • a Java class defined as a managed bean in the faces-config file
  • an XPage to display the received ArrayList with JSONObjects

Notes view

Our view looks nothing spectaculair:



  • The first column is used for sorting purpose.
  • The second column constructs the JSON string.

The formula for the second column can be as followed:

REM {This column builds a JSON string};

varUNID := @Text(@DocumentUniqueID);
varCategory:= Photo_Category;
varTitle := Photo_Title;

jsonOpener := “{“;
jsonClosure := “}”;
jsonSeparator := “\”,”;
jsonLastItem := “\””;

jsonOpener +
“\”docUNID\”: \”” + varUNID + jsonSeparator +
“\”author\”: \”” + @Name([CN]; varAuthor) + jsonSeparator +
“\”category\”: \”” + varCategory + jsonSeparator +
“\”subject\”: \”” + varTitle + jsonSeparator +
“\”descr\”: \”” + varDesc + jsonSeparator +
“\”created\”: \”” + @Text(@Date(varCreated)) + jsonSeparator +
“\”thumb\”: \”” + varThumb + jsonLastItem +

Alternatively you can use a normal view (plain column values) and construct the JSON string later, something described here.

JAVA class

Our class has one public method called loadPictures which will call a private method that will return an arraylist of jsonjavaobjects. You notice the library will be used.

Don’t worry about the hard-coded server and notes view references now. This will be polished later.

package com.quintessens;

import java.util.ArrayList;
import java.util.Vector;

import lotus.domino.NotesException;

import lotus.domino.Database;
import lotus.domino.Session;
import lotus.domino.View;
import lotus.domino.ViewEntry;

import lotus.domino.ViewEntryCollection;


public class SimplePictures implements Serializable{
public static final long serialVersionUID = 1L;
public SimplePictures(){

public ArrayList<JsonJavaObject> loadPictures() throws NotesException{
ArrayList<JsonJavaObject> PictureCollection = new ArrayList<JsonJavaObject>();

NotesContext nct = NotesContext.getCurrent();
Session session = nct.getCurrentSession();

String ServerName = “dev1”;
String DatabaseName = session.getCurrentDatabase().getFilePath();
String ViewName = “$v-pixJSONSingle”;
String Key = “”;
Integer ColIdx = 1; //0 means first column

try {
PictureCollection = loadJSONObjects(ServerName, DatabaseName, ViewName, Key, ColIdx);

} catch (NotesException e) {
// TODO Auto-generated catch block
return PictureCollection;

private ArrayList<JsonJavaObject> loadJSONObjects(String ServerName, String DatabaseName, String ViewName, String Key, Integer ColIdx) throws NotesException {

ArrayList<JsonJavaObject> JSONObjects = new ArrayList<JsonJavaObject>();

NotesContext nct = NotesContext.getCurrent();
Session session = nct.getCurrentSession();
Database DB = session.getDatabase(ServerName, DatabaseName);

if (!(DB==null)) {

View luView = DB.getView(ViewName);

if (!(luView == null)) {

JsonJavaFactory factory = JsonJavaFactory.instanceEx;
ViewEntryCollection vec = luView.getAllEntries();

ViewEntry entry = vec.getFirstEntry();
while (entry != null) {

Vector<?> columnValues = entry.getColumnValues();
String colJson = String.valueOf(columnValues.get(ColIdx));

JsonJavaObject json = null;

try {
json = (JsonJavaObject) JsonParser.fromJson(factory, colJson);
if (json != null) {

} catch (JsonException e) {
System.out.println(“ERROR: PP.loadJsonObjects 1: colJson “);

ViewEntry tempEntry = entry;
entry = vec.getNextEntry();
return JSONObjects;


Managed Bean

We register the class as a managed bean so we can call it easily from our XPage:



And then last but not least our XPage. Here we will display the list. The XPage contains:

  • A (Bootstrap) table.
  • A Repeat control
  • A Pager control.

By calculation the values for the Repeat control on page load and using a partial refresh for the pager pagination becomes really fast.

The result will be something as followed:


<?xml version=”1.0″ encoding=”UTF-8″?>
<xp:view xmlns:xp=””&gt;

<link href=”; rel=”stylesheet” integrity=”sha256-MfvZlkHCEqatNoGiOXveE8FIwMzZg4W85qfrfIFBfYc= sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ==” crossorigin=”anonymous” />

<xp:pager layout=”Previous Group Next” partialRefresh=”true”
id=”pager1″ for=”repeat1″>

<table class=”table table-hover”>
<xp:repeat id=”repeat1″ rows=”15″
value=”${javascript:PictureProvider.loadPictures();}” var=”pix”>
<xp:text escape=”false”>
getAttachmentURL and getBaseURL from:

function getAttachmentURL(docID:java.lang.String, attachmentName:java.lang.String) {
var base = getBaseURL();
var middle = “/xsp/.ibmmodres/domino/OpenAttachment”;
if (base.substr(0,4) == “/xsp”) {
middle += base.substr(4);
} else {
middle += base;
var result = base + middle + “/” + docID + “/$File/” + attachmentName + “?Open”;
return result;

function getBaseURL() {
var curURL = context.getUrl();
var curAdr = curURL.getAddress();
var rel = curURL.getSiteRelativeAddress(context);
var step1 = curAdr.substr(0,curAdr.indexOf(rel));

// Now cut off the http
var step2 = step1.substr(step1.indexOf(“//”)+2);
var result = step2.substr(step2.indexOf(“/”));
return result;
var thumb = pix.thumb;
var id = pix.docUNID;

return “<img src='” + getAttachmentURL(id, thumb) + “‘>”;
<xp:text escape=”true” value=”#{pix.subject}”>
<xp:text escape=”true” value=”#{pix.category}”>
<xp:text escape=”true” value=”#{pix.descr}”>
<xp:text escape=”true” value=”#{}”>
</tr><!– /.row –>



Next step

In a next blog I will explain some other (basic) methods that the application will be using to generate collections of documents (by key or restrictbycategory) and based upon these methods we will reconstruct our current XPages app. Untill then.

Bildr on Extension Library (work in progress)

In the last week before vacation I have some time left for some experiment. So I decided after reading the extension library guide to start rewriting the Bildr project on OpenNTF. Untill now I have come pretty far and the first results look promising. Not sure if I can manage to finalize the project before the end of the week, but let’s think positive!

Below some screenshots so far…

Bildr in Gurus of XPages webcast

While working on the next version of Bildr I was listening to the Gurus of XPages webinar (I am not sure where you can get a download of the webinar but it’s out there).

I was happy surprised when I heard at about 21:40 Bildr mentioned as a great XPages app!

Thanks for the nice words! We’ll make sure that Bildr:

  • remains free
  • gets stuffed with more XPages goodies in the future =)

Also thanks to everyone who has contributed to the project. Please update your ideas / feature requests etcetera on OpenNTF.

Bildr – Work in progress

It’s been a hard day’s night… there is some work in progress for Bildr on OpenNTF.

I have added a bookmark functionality and separate page to read comments.

Figure: Button to create a bookmark for a picture document.

Figure: Bookmark overview on profile page.

Figure: Comments overview page.

I have not submitted the code yet, will do that later this day/weekend. Anyway, if you have some feature request, please let me know. Enjoy your weekend!


added the option to update picture details in the browser