Send a message from your XPage application to a Slack channel


While everyone is ‘waiting in vain’ for the delivery of Project Toscana organizations have start using Slack as a modern way to send messages within departments.

For an example a operation team is using an instructions quality book build on XPages and it would be great to get notified in your Slack channel when new instructions come in or have been updated. Or you want to highlight a specific instruction just to create extra attention to it (e.g. an increasing number of incoming incidents).


Be creative with use-cases🙂

Slack integration points

Incoming Webhooks are a simple way to post messages from external sources into Slack. They make use of normal HTTP requests with a JSON payload, which includes the message and a few other optional details described later.

JSON, HTTP request… this sounds doable with XPages! So what are the steps you must take?

Setup your integration

Go to and click on Incoming Webhooks, then select a channel or user you want to post your messages to.

Setup your message

You have two options for sending data to the Webhook URL above:

  • Send a JSON string as the payload parameter in a POST request
  • Send a JSON string as the body of a POST request

Simple message

For a simple message, your JSON payload could contain a text property at minimum. This is the text that will be posted to the channel e.g.:

payload={"text": "This is a line of text in a channel.\nAnd this is another line of text."}

You can decorate your message with text formatting. You will find descriptions in the custom integration page on Slack.

Message attachments

To display a richly-formatted message attachment in Slack, you can use the same JSON payload as above, but add in an attachments array. Each element of this array is a hash containing the following parameters:

	"fallback": "Required text summary of the attachment that is shown by clients that understand attachments but choose not to show them.",

	"text": "Optional text that should appear within the attachment",
	"pretext": "Optional text that should appear above the formatted data",

	"color": "#36a64f", // Can either be one of 'good', 'warning', 'danger', or any hex color code

	// Fields are displayed in a table on the message
	"fields": [
			"title": "Required Field Title", // The title may not contain markup and will be escaped for you
			"value": "Text value of the field. May contain standard message markup and must be escaped as normal. May be multi-line.",
			"short": false // Optional flag indicating whether the `value` is short enough to be displayed side-by-side with other values

Send the message

With a simple post request you send the message in JavaScript:

function postMessageToSlack(url){
webhook_url = url;
payload= JSONStr;
var xmlhttp = new XMLHttpRequest();'POST', webhook_url, false);
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');


This whole approach I have added as an XSnippet on OpenNTF:

You can customize it to your needs. Basically I have a script block and a button on a custom control. Via the Property Definition tab you can set the desired values. In my example I am sending a message to a Slack channel about a picture / document in my Bildr application (shameless plug).

Here is how the message could look like:


Since my XPages app is running on a local development machine it is of no use to send sampel thumbnails of the page, but I could. This also refers to the user icon, which could be the icon of the application.

So grab the snippet and start integrating your XPages with Slack (untill Toscana arrives) !

FYI: I am not aware of any restrictions on the number of message you may send to Slack. Please let me know if you have details on this.

Add 20 years of experience to your workforce

You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: and get in contact.

I am happy to work WITH you !


Using Apache POI to create Presentations from your XPages application


Apache POI is perhaps THE Java API for Microsoft Documents, if you do not live in the Microsoft bubble. It inspired people to build the Poi4XPages plugin to easily generate Word and Excel Files out of XPages (using data from Notes documents).

Yeah but Microsoft Office has so many other great types of documents you might think. Take for example PowerPoint presentations. Have you ever met a sales guy without one?


It turns out that it not that hard to use Apache POI to create powerpoint slides. I will describe how you can start developing your own solution in a few steps.

Step 1 – Download and install Apache POI

You have the link so download the library. While I was developing my application a new release (v3.15, September 21) came out so this project is alive an kicking.

I added the following jar files to my webcontent/web-inf/lib folder and added them to the build path so they appear as referenced libraries:


Step 2 – Write some code

In my application I want to use data that is stored in Notes documents in the presentation slides. I also want to import a template first, so I have some styling for the slides e.g. background image.

Note that I am not a PowerPoint export, so my template might be far from correct. I store the presentation in my NSF so in order to import it into my PPT object I am using Sven Hasselbachs Domino Napi Utility class. For this class I need to add the lwpd.domino.napi.jar file on my Domino server to the build path of my application,

With this in place I could write my Output class:

package org.quintessens;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.ServletOutputStream;
import lotus.domino.NotesException;
import lotus.domino.Session;
import lotus.domino.Document;

import org.apache.poi.xslf.usermodel.SlideLayout;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFHyperlink;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
import org.apache.poi.xslf.usermodel.XSLFSlideMaster;
import org.apache.poi.xslf.usermodel.XSLFTextBox;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
import org.apache.poi.xslf.usermodel.XSLFTextShape;


import ch.hasselba.napi.NAPIUtils;

public class Output {

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

public void createPptx(String docId) {
try {

Document doc = session.getCurrentDatabase().getDocumentByUNID(docId);
DateFormat dateFormat = new SimpleDateFormat(“yyyy/MM/dd HH:mm:ss”);
Date date = new Date();

XMLSlideShow ppt;
try {
ppt = new XMLSlideShow( NAPIUtils.loadBinaryFile( session.getServerName(),session.getCurrentDatabase().getFilePath(), “Duffbeers.pptx”));
int slideCounter = ppt.getSlides().size();
System.out.println(“contains ” + slideCounter + ” number of slides”);
// first see what slide layouts are available :
System.out.println(“Available slide layouts:”);
for (XSLFSlideMaster master: ppt.getSlideMasters()) {
for (XSLFSlideLayout layout: master.getSlideLayouts()) {

XSLFSlideMaster defaultMaster = ppt.getSlideMasters().get(0);
XSLFSlideLayout defaultLayout = defaultMaster.getLayout(SlideLayout.BLANK);

* Add a slide based on TITLE_ONLY layout
defaultLayout = defaultMaster.getLayout(SlideLayout.TITLE_ONLY);
XSLFSlide slide01 = ppt.createSlide(defaultLayout);
XSLFTextShape title01 = slide01.getPlaceholder(0);

* Add a slide based on TITLE_AND_CONTENT layout
defaultLayout = defaultMaster.getLayout(SlideLayout.TITLE_AND_CONTENT);
XSLFSlide slide02 = ppt.createSlide(defaultLayout);
XSLFTextShape title02 = slide02.getPlaceholder(0);
XSLFTextShape body02 = slide02.getPlaceholder(1);
Vector < String > strength = doc.getItemValue(“refStrength”);
for (int i = 0; i < strength.size(); i++) {

* Add another slide based on TITLE_AND_CONTENT layout
XSLFSlide slide03 = ppt.createSlide(defaultLayout);
XSLFTextShape title03 = slide03.getPlaceholder(0);TutorialsPoint
XSLFTextShape body03 = slide03.getPlaceholder(1);
Vector <String> weak = doc.getItemValue(“refWeakness”);
for (int i = 0; i < weak.size(); i++) {

* Add another slide based on TEXT layout
defaultLayout = defaultMaster.getLayout(SlideLayout.TEXT);
XSLFSlide slide04 = ppt.createSlide(defaultLayout);
XSLFTextShape title04 = slide04.getPlaceholder(0);
title04.setText(“Link(s) of interest”);TutorialsPoint
XSLFTextShape body04 = slide04.getPlaceholder(1);

XSLFTextRun textRunLine2 = body04.addNewTextParagraph().addNewTextRun();
XSLFHyperlink link04 = textRunLine2.createHyperlink();

// 0-based index of a slide to be removed
for (int i = 0; i < slideCounter; i++) {

String filename = doc.getItemValueString(“refName”) + “.pptx”;

TutorialsPointFacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ex = fc.getExternalContext();
XspHttpServletResponse response = (XspHttpServletResponse) ex.getResponse();

try {
ServletOutputStream writer = response.getOutputStream();
response.setHeader(“Cache-Control”, “no-cache”);
response.setHeader(“Content-Disposition”, “inline; filename=” + filename);
response.setDateHeader(“Expires”, -1);
} catch (Exception e) {

} catch (NotesException e1) {
// TODO Auto-generated catch block
} catch (IOException e1) {
// TODO Auto-generated catch block


} catch (NotesException e2) {
// TODO Auto-generated catch block


In this example I am creating new 4 slides, with different layouts and content. You can be creative as you like and for example format text and present them as hyperlinks or include images.

Step 3 – Register a managed bean and call the code

With the java class Output written I can register it as a managed bean in the faces-config file:


This makes it easy to call the code from anywhere. The only think I need to provide is an universal ID of a document:

<xp:button id=”button4″ value=”Download as Presentation” styleClass=”pull-right btn-primary”
style=”margin-right:5px;”><i class=”fa fa-slideshare” aria-hidden=”true”></i>

<xp:eventHandler event=”onclick”
submit=”true” refreshMode=”complete”>

In my button the ReferenceController.objectId will provide the universal Id of a Notes document. I am using a controller class to get the value from a document, instead of a DominoDocument data-soruce.

With this in place. We are basically good to go! With just 1 click any sales guy can now create a corporate presentation from a Notes document and start spreading the word!


If you want to know more about Apache Poi, Powerpoint files and XPages I am happy to answer your questions. I can also recommend to read the XSLF Cookbook or the Apache Poi PPT tutorial on TutorialsPoint.

Add 20 years of experience to your workforce

You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: and get in contact.

I am happy to work WITH you !

I Like Bubble Commenting

Strange subject title isn’t?

I have created a repository of my bubble/social speech layout, so if you want to have a closer look and implement it yourself then you are free to go.

I updated the @mention implementation so you get a nice icon in front of the name:


In order to have icons I updated my LotusScript agent to add a URL to an image in the PhotoURL field of the Person form in the FakeNames.nsf. For now I stored the icons in the NSF but in case you have a directory you use the reference to images from there.

I have also added an updated version to Like/Unlike comments, in stead of SSJS now most of the logic resides in the LikeController class. When you hover over the icon you get a list presented with people who have liked the comment.


Ofcourse nothing is stress-tested but I have not seen major issues so far. I hope you like it and get inspired to modernize your IBM Notes applications !

Add 20 years of experience to your workforce

You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: and get in contact.

I am happy to work WITH you !

Adding @mention autocomplete like Facebook, Twitter & Google+ to your XPages app


For an application I was asked to add a feature to add commenting on main topics. In order to stimulate discussions it should be easy to include people in the stream, similar as in Twitter. So writing an @sign should invoke a type-ahead or auto-complete to a user-list and provide suggested users to address.

In XPages you have type-ahead option, but that is only for inputText controls, not for inputTextArea controls. So how to solve this?

A search after “lightweight wrappers for adding @user mention functionality to Twitter Bootstraps Typeahead plugin” brought me to this library. The provided examples looked promising and were just what I needed, even the option to include a profile icon, similar to IBM Connections Smartcloud.


Basic setup

I will guide you setting up a basic structure to add “@Mention” to your XPages app and use a REST service to provide a list of users from your directory.

Step 1 – get the resources in

Not that difficult. Just drop the files somewhere (ordered) in your WebContent folder e.g:


Step 2 – Reference your resources

Next we are going to make these resources available via a Theme design element:mention_impl2

Step 3 – Add an inputTextArea control and bind it to the library

We want to have the @Mention function available to an inputTextArea control so we must not forget to add that to the XPage:


When the document is ready we want to bind the @Mention library to our inputTexArea. I use the infamous XSnippet “x$ jQuery selector for XPages”. Since we will be using the Bootstrap theme in the Extension Library we have jQuery available:


Step 4 – Add REST service

Wait, did we just add $.getJSON(‘REST.xsp/users’, function(result)? What does that provide us?

REST.xsp is an XPage that contains a REST service control from the Extension Library. It calls a serviceBean


The serviceBean is a simple service that will go to a database and collect column values from a view. In this case I am using the also infamous fakenames NSF but that could be your ordinary Domino Directory (names.nsf)


If you open your developer tools in your browser you see the service provides as data:


We have to strip that down with line x$(“#{id:comment}”).mention({}).

Since we are also using the bootstrap theme for @Mention the result looks like:


Splendid! So how is your social application modernization doing?

Add 20 years of experience to your workforce

You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: and get in contact.

I am happy to work WITH you !


Show / hide columns dynamically

To show or hide columns dynamically is a nice feature in the jQuery dataTables component. With a few simple steps you can deliver something similar in your XPages application as I demonstrate in the video.

The technologies used: XPages, Extension Library, Bootstrap.

Add 20 years of experience to your workforce

You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: and get in contact.

I am happy to work WITH you !

FlipSwitch style for your checkboxes

A flip switch is an alternative look for a checkbox or the two-option select menu. It can be toggled by a click or a swipe.


I am not sure if it’s originated from mobile interfaces, at least it is there where they are most common. So if you modernize an application and optimize it for mobile access you might consider adding flip switch behaviour to these form elements.

Here is an example how to do this with XPages:



Ofcourse you have to provide the CSS. The CSS depends on your theme. There are handy sites that might help you with it.

Here is my CSS:

.onoffswitch {
position: relative; width: 90px;
-webkit-user-select:none; -moz-user-select:none; -ms-user-select: none;
.onoffswitch-checkbox {
display: none;
.onoffswitch-label {
display: block; overflow: hidden; cursor: pointer;
border: 2px solid #999999; border-radius: 20px;
.onoffswitch-inner {
display: block; width: 200%; margin-left: -100%;
transition: margin 0.3s ease-in 0s;
.onoffswitch-inner:before, .onoffswitch-inner:after {
display: block; float: left; width: 50%; height: 30px; padding: 0; line-height: 30px;
font-size: 14px; color: white; font-family: Trebuchet, Arial, sans-serif; font-weight: bold;
box-sizing: border-box;
.onoffswitch-inner:before {
content: “ON”;
padding-left: 10px;
background-color: #34A7C1; color: #FFFFFF;
.onoffswitch-inner:after {
content: “OFF”;
padding-right: 10px;
background-color: #EEEEEE; color: #999999;
text-align: right;
.onoffswitch-switch {
display: block; width: 18px; margin: 6px;
background: #FFFFFF;
position: absolute; top: 0; bottom: 0;
right: 56px;
border: 2px solid #999999; border-radius: 20px;
transition: all 0.3s ease-in 0s;
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
margin-left: 0;
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
right: 0px;

I hope you find this tip useful…



Add 20 years of experience to your workforce


You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: and get in contact.

I am happy to work WITH you !

Draggable modal

For a project a request was to make a Bootstrap modal (a Dialog control in the Extension Library) as draggable. By default, the modal does not have that feature. So can you make it draggable again?

In xsp-mixin stylesheet the class xsp-responsive-modal is using !important for the left and top properties which prevents that the modal is draggable. A work-around can be achieved by replacing these class properties with your own that does not use !important.

To replace the default class add for the onShow event of the dialog:


Your custom class could look as followed:

.draggable-responsive-modal {
display: block;
width: auto;
left: 0;
top: 0;
z-index: 1050 !important;

The x$() function is the infamous utility function from Mark Roden to work with JQuery.

I added the code to GitHub Gist:

Add 20 years of experience to your workforce


You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: and get in contact.

I am happy to work WITH you !

Question: Is it possible to set via a resource via a theme so it is applied to any XPage in an application?

I received a question if it is possible to set (or add) a resource via a Theme resource so it will become available to any XPage or Custom control?

Yes ofcourse you can e.g. via:


but you should keep in mind is that a Theme is ONLY applied in the Render Response phase. So if for example you include an SSJS library to the Theme, you will not be able to use it in the beforePageLoad or afterPageLoad event. A mistake that is common made.

My recommendation would therefor be to use a Theme more for applying default settings or to overwrite properties to a specific type of component, e.g. a default pageName property on the ViewRoot component.

In terms of adding resources I would advice to use a Custom control design element. SSJS that will be computed dynamically only run once per page load / refresh in a theme (just in Render Response), compared to every phase of the lifecycle in a Custom control.

Happy development =)

navigationPath & selection properties


Once in a while you move back in time and understand why you have forgotten certain rules. Mostly because you have stopped using them or you experience the same pitfalls as others do and you just want to forget them to move ahead.

navigationPath and selection properties

One of those things are the navigationPath from the Application Layout control and the selection property in it’s navigation nodes.


The navigationPath allows you to control the currently selected titlebar Tab and the selection appearance of any Navigator control on the XPage.


The selection property is nothing more than a regular expression used to select an item. The expression is matched against the navigationPath, described above.


Selected is a property that indicates if a node is selected or not. This property often causes confusion.

Mix them together

So if you mix these properties above you can establish some nice usability improvement for your app-user. It can visualize (via style classes) when a certain titlebar should be highlighted or not.

Example Aap Noot Mies

The follwoing example will demonstrate it’s basic feature (and shows some oddness in the Dutch education system while Mies is nothing more than a cat).

As titlebar tabs I have: Aap, Noot and Mies.

As Navigator nodes I have Aap, Noot, Mies and Apes/Gorilla, Apes/Chimp.

Each Navigator links points to an individual XSP but the last two nodes belong to the Aap titlebar tab.


I have a custom control with the application layout control on it. For the navigationPath property I have set up a propery definition so I can adjust it for eac XSP:


The titlebar nodes are defined as follwed:

<xe:pageTreeNode label=”Aap” selection=”/Aap/.*”
page=”/aap.xsp” selected=”true”>
<xe:pageTreeNode label=”Noot” selection=”/Noot/.*”
page=”/noot.xsp” selected=”true”>
<xe:pageTreeNode label=”Mies” selection=”/Mies/.*”
page=”/mies.xsp” selected=”true”>

Here I have set a regex for the selection property.

Navigator control

On the same custom control I also have a Navigator control:

<xe:navigator id=”navigator1″>
<xe:pageTreeNode label=”Aap” page=”/aap.xsp”></xe:pageTreeNode>
<xe:pageTreeNode label=”Noot” page=”/noot.xsp”></xe:pageTreeNode>
<xe:pageTreeNode label=”Mies” page=”/mies.xsp”></xe:pageTreeNode>
<xe:basicContainerNode label=”Apes”>
<xe:pageTreeNode label=”Gorilla”
<xe:pageTreeNode label=”Chimp” page=”/chimp.xsp”></xe:pageTreeNode>

Here I do not have to define anything. The control will know itself when a selected node needs to be highlighted.

Gorilla XPage

In the app I have multiple XPages, in the gorilla xpage I have set the navigationPath property as follwed:

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

<xc:ccLayout navigationPath=”/Aap/Gorilla”>
<xp:image url=”/aap.jpg” id=”image1″ xp:key=”facet_1″></xp:image>

As a result the Aap titlebar Tab is highlighted:


Not really something that opens your mind but at least I have written it down (with a repo) in the hope I won’t have to re-learn it next time I have to use the application layout control.




Building a search function with DataTables plugin


In Domino you have multiple options how to provide a search function for an application. I have seen many examples where a FT search query is build for a database, where the form type is defined, which fields should be used in the search etcetera. Most of them are a maintenaince nightmare, layout is little flexible and usability is lacking (e.g. perform a search towards a query which will result in zero hits).

What if you make it easier to maintain, more flexible for user specific desires and add facetted search principles? A win situation?


In the following posts I will write how to use the jQuery DataTables plugin to provide a quick search function for your Domino apps. I assume you use XPages.

Stage 1 – Getting & presenting the data

In the initial stage we just try to get and present the data we need. As example I will be using the FakeNames application. I have created a public repo which has at the moment:

  • an xpage to present the data (dtPersons.xsp)
  • an xpage (api.xsp) which will contain rest services
  • a Java class that generates the data in JSON format
  • a CSJS library to transform the HTML table on dtPersons.xsp to  DataTables object
  • the required resources from
  • a Theme resource to have the resources available
  • a Notes view to use as data source.

In order to create some fake documents I have set up an LS agent to do so.

If you bind this all together, you have already a search function:


Right on top you have a search field where you can query the columns in the table. The columns are sortable too. Probably it is matching most of the search functions you have seen for Domino. But wait! There is more possible…