Exploring the Domino Explorer

Introduction

We live in a connected world today and also the data in your IBM Notes/Domino platform is more connected that you perhaps realise:

I work work for company X at department Y and besides my assignment as “ICS product specialist” I perform in different roles, sometimes as developer, sometimes as a solution architect, sometimes as project manager etc. I own a range of devices to do my work, bought in by different suppliers under different conditions/contracts. Now a external project-leader (they claim they are the best) has became responsible for a new project (Z since it is the final project the company is ever going to run) and to make a huge impact the project-leader want to equip his team (which I have become member of) with the latest and greatest of devices to make our work most convenient and the impact of the project delivery as huge as possible. BUT of course he is unaware about the devices the team owns already and the lifetime of the contracts. He also does not want to make top management angry so he suggest to provide this team with devices just 1 configuration level below top management. So how does the project-leader require the information he need to know (a list of end of lifetime for the current devices the project team owns compared with the list of current devices top management owns) ?

All objects in the story above (organisation, departments, employees, devices, contracts, suppliers) are represented in Notes documents. By connecting them in a Graph DB new information can be gathered!

Graph

Lately I have been exploring Graph data modelling more closely. Mostly because I see many opportunities to connect/model unstructured data in fluid ways. Faster than relational datasources sometimes can.

For now I have been mainly looking at Neo4J because most Graph related education is focussed around this product. But for IBM customers you have IBM Graph (cloud only?) and since recent IBM Notes via the OpenNTF Domino API.

Graph need NoSQL

Graph needs NoSQL databases since NoSQL is capable of describing the variety of objects that are around in enterprise data. As it turns out Lotus Notes is around as one of the first NoSQL databases!

ODA & Tinkerpop

The OpenNTF Domino API has included Tinkerpop and an implementation to store content in a graph database structure.

This is great because as Domino developer you are concerned that your data is stored in an NSF. Probably you want to avoid the hassle of moving your data to another technology first and focus on developing applications directly.

Domino Explorer

Recently Oliver Busse has released Domino Explorer. It scans the Domino Directory and the Catalog application to show the capabilities of Graph in an XPages application. Getting the Notes data into a Graph data model is done via the OpenNTF Domino API.

In the next part of this post I will focus on how this is was implemented…

Document: Exploring the Domino Explorer

This document describes the setup of the Domino Explorer (DE) application (app) available on OpenNTF (link). The DE app demonstrates the Graph db capabilities via the OpenNTF Domino API (ODA) (link).

By exploring the architecture of the app better understanding of the Graph technology is aimed to achieve and how to implement it in XPages applications.

Presumptions

It is presumed that the reader of this document has advanced level of understanding of XPages technology, intermediate level of Java programming language, medium level of understanding of IBM Notes data and low level of the graph data model.

If not turn around or educate yourself on these topics😉

Graph glossary

The view design element “graph” group it’s containing documents into the two basic units in the Graph Data Model (Graph/GDM): Edges and Vertices.

Vertices

Vertices (singular:vertex) are the objects in a graph.

Edges

Each edge has two (or in hypergraphs, more) vertices to which it is attached, called its endpoints. Edges may be directed or undirected; undirected edges are also called lines and directed edges are also called arcs or arrows.

IBM Notes data

When we translate this to IBM Notes data, vertices are mostly objects that contain values or properties (edge). E.g. a user is member of a group. An order has a date-stamp etcetera. With graph you can make queries to find different types of objects connected via shared properties e.g. A car-leasing company may have a fleet of rental-cars which may have present or past drivers.

General overview

Design elements in scope of the dissection

To have some sort of start we will start easy and give an overview of the design elements involved:

Design element Purpose Scope
Views Used to store documents that are used in the graph data model.
Documents are of type Edge or Vertex(Vertices).
X
XPages Used to initiate business logic and present the result to the user in a web interface. X
Custom controls Used to break parts of XPages into reusable pieces. X
Script libraries Client-side javascript libraries used to interact with the web presentation. X
Java Java classes that contain the business logic. X
Images Used to enhance the web presentation.
Style sheets CSS definitions used to enhance the web presentation.
Themes Use to set rules for the application regarding style, behaviour, resources
faces-config.xml Configuration file for the application, mostly used for registering managed beans.

For the rest of this document we will only focus on design elements that are marked with X under the Design elements will most likely be discussed in the logical order how the graph data model is implemented in the DE app.

Managed Beans

Managed Bean (link) is a regular Java Bean class registered by the XPages framework. Important beans registrered in the DE app for Graph are:

Bean name Class
config net.notesx.domex.controller.ConfigurationController
scanner net.notesx.domex.controller.ScannerController

Config

The ConfigurationController class controls the configuration for the GDM. It  sets which databases are in scope for the GDM (Names.nsf, catalog.nsf).

It uses the:

 

Java class Usage
net.notesx.domex.graph.GraphHelper Setup of the Graph
net.notesx.domex.graph.Configuration Configuration of the Graph

DFramedTransactionalGraph<DGraph> configGraph = GraphHelper.getGraph();

Configuration configuration = configGraph.addVertex(“configuration”, Configuration.class);

configuration.setApplicationName(applicationName);

configuration.setNamesPath(namesPath);

configuration.setCatalogPath(catalogPath);

configGraph.commit();

In the code above the Graph db is loaded and the configuration added as a Vertex.

Configuration class

The configuration class contains the following properties:

  • $$Key (??? identifier for current configuration)
  • ApplicationName (name for the application, display only)
  • namesPath (location of the names.nsf)
  • catalogPath (location of the catalog.nsf)

GraphHelper class

The GraphHelper class sets up the Graph in the following order:

  • Setup an element store for configuration
  • Add the types (Vertices) to the element store
  • Create a configuration for the Graph
  • Add the element store to configuration and set the default element store (= filepath of current database)
  • Setup the Graph by using the configuration
  • Return it

// set element store for configuration

DElementStore configStore = new DElementStore();

Database currentDatabase = Factory.getSession(SessionType.CURRENT).getCurrentDatabase();

configStore.setStoreKey(currentDatabase.getFilePath());

// setup the type

configStore.addType(Configuration.class);

configStore.addType(DXDatabase.class);

// create a graph config

DConfiguration config = new DConfiguration();

DGraph graph = new DGraph(config);

// add the config element store

config.addElementStore(configStore);

config.setDefaultElementStore(configStore.getStoreKey());

// setup the graph

DFramedGraphFactory factory = new DFramedGraphFactory(config);

DFramedTransactionalGraph<DGraph> fg = (DFramedTransactionalGraph<DGraph>) factory.create(graph);

// return the graph

return fg;

Scanner

This class adds the database, user and group objects to the Graph according the specified class for each object.

Important methods:

  • scanPeopleAndGroups
  • scanDatabases
  • scanAcl
  • scanMember

scanDatabases

  • Get the path of the catalog db via the ConfigurationController class
  • Initiate the Graph datamodel via the GraphHelper class
  • Put all documents from View $ReplicaID into a document collection
  • For each document add a vertex to the graph using the DXDatabase class
    • Set properties for the vertex
    • Commit it to the Graph
    • Run the scanAcl method for the databaseVertex object

scanPeopleAndGroups

  • Get the name of the names db via the ConfigurationController class
  • Initiate the Graph datamodel via the GraphHelper class
  • Put all documents from View $VIMPeople into a document collection
  • For each document add a vertex to the graph using the DXUser class
    • Set properties for the vertex
    • Commit it to the Graph
  • Put all documents from View $VIMGroups into a document collection
  • For each document add a vertex to the graph using the DXGroup class
    • Set properties for the vertex
    • Commit it to the Graph
    • Run the scanMember class for the groupVertex object

scanAcl

  • For the given database (vertex object) get the database object
    • Grab the ACL
    • For each ACL entry add a vertex using the DXACLEntry class
      • Set properties for the vertex
      • Add the ACL entry vertex as an Edge to the DB vertex (the label “hasAcl” will be used)
      • Commit it to the Graph

scanMember

  • For the given group (DXGroup class object):
    • For each member in groupmembers list:
      • Check if it contains a “/” ( This is a user)
        • Create a user object with the DXUser class from the Graph
        • If the user object is not null (in the Graph) add it to the group
      • If not (this is a group)
        • Create a group object with the DXGroup class from the Graph
        • If the group object is not null add it to the group
      • Set a property for the vertex
      • Commit it to the Graph

Other classes

DE contains more classes stored under several packages:

  • Common
  • Domex
    • Controller
    • Graph
    • Rest

Common package

Classes under the common package are used for setting properties for application e.g. navigation, page behaviour etc. They are out of scope for this document.

Domex \ controller package

Classes under the domex \ controller package are ConfigurationController and ScannerController and available as described earlier as managed beans.

Domex \ graph

Classes under the domex \ graph package are directly related to the Graph data model and describe the Graph data objects (vertexes):

  • Configuration
  • DXDatabase
  • DXACLEntry
  • DXGroup
  • DXUser

Each class describes the type of the object, the properties the object has and how to get & set them, the edges the object has and in which direction they go.

Annotation Description Example
@TypeValue Interface annotation for marking the Element property-value that may contain type information. @TypeValue(“DXACLEntry”)
@Property Property annotations are for getter and setters to manipulate the property value of an Element. @Property(“$$Key”)

public String getKey();

@Property(“name”)

public void setName(String s);

@AdjacencyUnique Adjacency annotate getters and adders to represent a Vertex incident to an Edge. AdjacencyUnique extends this idea to ensure that there is only one instance of an Edge with a specific label between any two specific Vertices. This allows the user of the graph to call an “add” method and return the existing adjacency if it already exists. @AdjacencyUnique(label = “hasAcl”, direction = Direction.OUT)

public Iterable<DXDatabase> getDatabases();

Below is as example of the definition of the DXUser.java class:

package net.notesx.domex.graph;

import org.openntf.domino.graph2.annotations.AdjacencyUnique;

import org.openntf.domino.graph2.builtin.DVertexFrame;

import com.tinkerpop.blueprints.Direction;

import com.tinkerpop.frames.Property;

import com.tinkerpop.frames.modules.typedgraph.TypeValue;

@TypeValue(“DXUser”)

public interface DXUser extends DVertexFrame {

@Property(“$$Key”)

public String getKey();

@Property(“username”)

public String getUserName();

@Property(“username”)

public void setUserName(String s);

@AdjacencyUnique(label=”member”, direction=Direction.OUT)

public Iterable<DXGroup> getMembershipInGroups();

}

The GraphHelper class is described earlier in this document and is used to setup the Graph.

Domex \ Rest package

The classes under the domex \ rest package create collections of json objects for the objects in the Graph data model. Some classes take in parameters, some don’t. Each class defines what type of graph object is in scope.

The way these classes are initiated is as follow:

  • On XPages rest service(s) of type customRestService are defined. The servicebean property directs to which class the service is bound to.
  • The XPage contains JavaScript libraries.
    • In a library can be defined which rest service should be called when the document is ready e.g. to build a collection of database objects.
    • In a library can be defined which rest service should be called when a link is being clicked e.g. a row in a data table control and if a parameter should be send (e.g. the replica Id of the database). Also is defined what should be done with the data returned from the rest service.

XPages

The design elements described above come together in the XPages design elements. We will demonstrate by describing an XPage.

Alldbs.xsp

Elements:

Type Name Purpose
Custom Control _layoutBS3 Reusable layout for application.
JavaScript library alldbs.js Calling Rest Services.

On document ready: data

On click table row: acl

Rest service control Pathinfo: data Bound to Java class net.notesx.domex.rest.AllDatabasesService
Rest service control Pathinfo: acl Bound to Java class net.notesx.domex.rest.AclService
HTML table datatable Placeholder for result from rest service under pathinfo data
Div acl Placeholder for result from rest service under pathinfo

XPage logic explained

On document ready:

  1. When the document is ready an AJAX call is made to the rest service under pathinfo data. This initiates Java class net.notesx.domex.rest.AllDatabasesService.
  2. The class gets the Graph data model and collects all objects/vertexes of the type specified in the DXDatabase class.
  3. For each vertex a JsonJavaObject is created which is being filled by properties from the vertex.
  4. Each JSON object is a JSONJavaArray.
  5. The array returned to the rest service which returns it to the AJAX call.
  6. When the data is returned the HTML table is updated. Note that the table is of type datatable. This is a Bootstrap plugin. When the data is returned to the datatable object it knows how to update the content (rows and columns) of the table.

Below you find the process visualize:

Screen Shot 2016-05-16 at 11.09.02

When clicking a row:

  1. When the document is ready a listener is registered for each time a table row (TR) element is clicked.
  2. When such a TR is clicked an AJAX call is made to the rest service available under pathinfo acl. As data the replicaid value is send with the call. This value is stored in the data-set for each row.
  3. The AJAX call initiates class net.notesx.domex.rest.AclService. Here with the value of the given request parameter replicaid once again the Graph datamodel is opened and searched for the DXDatabase vertex that has a matching replicaid property.
  4. The returned vertex is bound to the DXDatabase class (name = db).
  5. If the DXDatabase is not null a collection is setup of type Iterable and filled with objects of type DXACLEntry for each item from the method db.getACLEntries.
  6. Then the collection is walked through and for each item a JSONJavaObject is created and filled with properties from the DXACLEntry object.
  7. The JSONJavaObject is placed in a JSONJavaArray. This array put as a string in a new JSONJavaObject which is returned to the rest service.
  8. The rest service returns the data back to the AJAX request.
  9. The AJAX request clear the DIV with id acl and fills it with the data received from the rest service. For each JSON object in the array a line with values is written in the DIV.

The process is visualized below:

Screen Shot 2016-05-16 at 11.11.07

The processes described above are the most basic types. The Graph is called for basic objects, not correlated.

As a result the following information is displayed on your screen:

Screen Shot 2016-05-16 at 11.17.13

Summary

Perhaps you are thinking: what the fuzz?! I can do something similar with document collections, perhaps showing a single category from a categorized column or perhaps create a jsonarray containing jsonjavaobjects and iterate through them and find a match.

Perhaps you can for THIS example. But I rather would avoid to create an unnecessary amount of design elements for it. Also in this example a very basic query is performed. Rethink the story in the beginning of this post. How are you gonna search your data under those conditions?

Also the combination to display your result data with the DataTables plugin you can build on the fly custom tables and reduce the amount of Notes views to a minimum.

In a future post I will describe more enhanced queries. Stay “connected”!

Links of interest

 

 

Stress testing with ODA Graph

I am very interested in Graph data modelling and with the Graph capabilities in OpenNTF Domino API I decided to setup some demo environments just to get my head around the subject and how you can implement it in XPages and use Notes data.

To my opinion reading Notes data in the Graph database structure can bring interesting new opportunities, far beyond what we can deliver with Views and Collections today.

Oliver Busse has provided a great starting point with his SUTOL demo application so I started with that one.

Besides the implementation and Graph capabilities I am also curious about performance.  So I run some tests on my working demo app. With the help with a simple agent I decided to be gentle and create a set of only 20.000 user documents.

The first test was about returning user profiles (nodes) matching certain properties (relations), presented in a repeat control. Below the list the time to load the filtered set is displayed.

stress01

stress02.JPG

When I compare the result with a normal view filter (by category or FT search) the results where a bit disappointing.

I also noted that navigating through the list was very slow (20 seconds or more returning a new set of rows of 10 documents). More than I expected I received timeouts.

stress03

The reason for this performance is still unknown. I guess there is no index created yet for the user node in the graph db structure. Why navigating through the list is so latent in performance is also a mysterie.

Nevertheless, my demo is up and running so expect more results on Graph in XPages with Notes data in the future on this blog.

Below are sampels of performance using the “traditional” FT search filter capacity in Notes. Notice the difference.

stress04.JPG

stress05.JPG

I would like to thank Oliver Busse for his guidance getting the demo app up and running and for explaining some basic concepts of the implementation.

 

 

 

 

I’ve got the bower

As I am trying to get my XPages development workflow more in line with other development teams, my next step was to implement bower so I can skip dragging, copying, removing, updating (too many verbs already) in order to manage my projects.

First stop was Frank van der Linden’s post on bower4xpages. Most of the commands are described in his post so I skip to repeat them here..

Step 1 – Install Node.js

You can install bower with the Node package manager.  So step 1 was to install Node.

Step 2 – Install Bower

With the node package manager I installed bower.

Web sites are made of lots of things — frameworks, libraries, assets, and utilities. Bower manages all these things for you.

Step 3 – Setup the bower files

When Bower runs it needs 2 files: bower.json and .bowerrc file. In the json file you list the dependencies and the rc file points to the location where the files will be copied to. Here is a tip how to create a nameless file in notepad.

Having placed these files in the root of my repository location I was ready for the next step.

Step 4 – Install Git

Since I have been using SourceTree as Git client for Windows I needed to install Git client because Bower makes use of it.

Post Step 4 – Set Windows Environment Variables

When trying to run bower I got message that Git was not installed. Here is a description how to set your Windows environment variables.

Step 5 – Run bower run

Now with everything installed and set the last thing to do was to open the Command Prompt and cd to the root directory of my repository and run the ‘bower install’ command.

As a result I got all the dependencies in my project downloaded and installed.

bower_result

Once again achieved “a new(er) way of working”.

We have a release

Hahaha no not a date for Domino-next but last week I received a message from OpenNTF’s IP Manager that my Bildr project is finally released.

Quite interesting to learn about all those licenses and what consequences one might have for your project.

I thank Peter Tanner for his patience and assistance!

Next step perhaps setting up a video how to quickly install the project on your Domino server…

 

Working with JSON in your XPages application – Refined view

In a previous post I wrote how you could use a Notes view as the data source for JSONObjects. In a recent project I needed to minimize the data amount to transfer so I had to exclude the fields that contain no value. Here is the @formula I can up with for the column value:

REM { Patrick Kwinten

Quick way to deliver ‘cached’ JSON objects from Notes documents

};

REM {JSONObject bricks};

jsonOpener := “{“;

jsonSeparator := “,”;

jsonClosure := “}”;

REM {String helper};

src := “\\”:”‘”:@NewLine:”\””;

dst :=  “\\\\”:”\\'”:”\\n”:”\\\””;

REM {Define which fields to exclude/include in JSON object};

REM {“Idea taken from http://www.eknori.de/2012-06-01/use-transform-to-build-json-and-consume-the-output-in-an-xagent/&#8221;};

_exclude:=”$FILE”:”$Fonts”:”form”:”$Revisions”:”ID”:”ModifiedBy”:”$TUA”;

_fld:=@Trim(@ReplaceSubstring(@DocFields;_exclude;@Nothing));

REM {Output for “custom” fields. Empty values are excluded};

_fldOutput := “”;

@For(

n := 1;

n <= @Elements(_fld);

n := n + 1;

@Do(

_fldVal := @Text ( @GetField ( _fld[n] ) );

@If(_fldVal != “” ; _fldOutput := _fldOutput + “\”” + _fld[n] + “\”:\”” + @ReplaceSubstring( _fldVal; Src; Dst )  + “\”” + @If(n != @Elements(_fld); jsonSeparator;””); “”)

)

);

REM {Prepare output};

outputStr := “”;

outputStr := outputStr + jsonOpener;

REM {Output for “default” fields};

tmpUNID:= @Text(@DocumentUniqueID);

outputStr := outputStr + “\”docUNID\”:\”” + tmpUNID  + “\”” + jsonSeparator;

outputStr := outputStr + _fldOutput;

REM {Finalize JSONObject};

outputStr := outputStr + jsonClosure;

REM {Return output};

@Return(outputStr)

As a result I have “lesser” JSON Objects in my view:

Screen Shot 2016-03-01 at 10.20.40

Born Social available on GitHub

A long, long time ago I wrote about a project to deliver small building blocks to deliver features from the IBM Connections in XPages application. The posting can be found here: https://quintessens.wordpress.com/2015/04/16/born-social-create-a-social-notes-application-from-scratch/ .

Here and then I was asked to share the project or asked about the progress but since I rarely work with the Connections  platform anymore I thought it could be helpful to upload the Born Social project on GitHub so people can make use of it if they like to.

Unfortunately in the meantime I did no hear or read so much about integration between Connections and IBM Domino so I am not sure if this is a (hot) topic anymore. My initial thought with the project was that it would be ‘cool’ to utilize data in Connections in XPages applications.

I also wrote a small document that helps you to get the application up and running and explains how to use the re-usable custom controls.

The project is available here on GitHub.

I just modernized an application

Introduction

While following the buzz from IBMConnect16 remote I have been working in spare time on my Bildr project available on OpenNTF.

This time I have been focussing on improving the UI by adding more material design principles which should make it easier to distinguish content on a page. Beside that it is just good fun to work with UI sometimes it forces you to improve the back-end logic also.

Capture02

The image above demonstrates the display of related content on a single page where a profile contains lists of related documents.

NoSQL is a party

The following image demonstrates the information (e.g. categories) abstracted from a list of documents and on the right a random selected document from that list and showing some abstracted information from that document.

Capture04

Here you can see well IBM Notes works as a nosql database where documents are loosely coupled and may contain almost anything (well I try to avoid rich text). Especially in a rapid application development paradigm I like the flexibility of nostrict data structure at the time you start developing.

I have not heard much news about NSF from IBMConnect (Solr? Graph features? Performance improvements?) to make it competitive to other nosql options (why do I not see NSF back in this list?).

I hope IBM is aware of NSF’s image problem and admits steps need to be taken to improve it.

Bluemix

I am not sure what the next step for the app will be but I haven’t tried it on Bluemix yet, which could be interesting. The XGallery demo on YouTube shows some great potential.

 

Modernizing a Notes application

Introduction

The quickest way of modernizing your application build on Notes is probably by keeping it on that sublime application platform and provide a new user-interface and updated business logic to it.

As a demonstratable example I would like to bring up my own Bildr project on OpenNTF.

A brief history

The application started initially as a web browser display only and create content via the Notes client application in the early 2000’s. From that the application was updated in a create content via the web browser too features.

Later the oneUI was implemented in a later step also utilizing the Application Layout control. With the Bootstrap4XPages plugin a responsive UI could be delivered a couple of years ago.

Nowadays the Application Layout control is no longer used but the Bootstrap responsive features and components are used further through the application.

The application still relies on XPages and Notes data (allthough used mainly in JSON format). The business logic resides mainly in Java Classes. With the separation of design and data the application could be hosted on Bluemix (not tested, please do).

Modernization

Looking back at this application story I believe the application will change also in the future (or die) perhaps a challenge could be to have the data optional in a different source (e.g. MongoDB) or exchange XPages for Angular and run it on Node.js.

So if you have experience moving data from Notes to MongoDb, applying a similar ACL and Roles security model on your application I would be happy to hear your experiences.

Or if you are still on the Notes client only level and want to bring your application to a (mobile) browser I am happy to exchange ideas with you and learn from your situation.

New release

Why am I saying this? Today I uploaded a new version on OpenNTF and for many Notes developers who a) not have taken the XPages path yet b) unfamiliar with Java and JSON the application could be a great starter example.

Lately there are not that many (new, updated) projects (applications) available at OpenNTF so the chance to find a working demo to see and understand the code and data running are a bit scarce (I am sorry).

I remember in the days of Superhuman Software a quote about Notes and collaboration was “dare to share” so I would challenge more developers to do so. We can learn a lot from examples from others and I thank those people who (still) do and from which I can learn from!

I wish you a wonderful learning experience at IBMConnect 2016!

Capture04

 

Bildr 5 released on OpenNTF

Announcement

Today I released a new version of Bildr on OpenNTF ! There have been spent quiet a few long evenings coding but it was fun (I may drink at home) and interesting!

So just before the holiday season and January’s  IBM Connect buzz I thought it would be a proper moment for a release. So consider it my Xmas present to the community:-)

Modernization

I label this version 5.0 since I (almost) completely rewrote the application from scratch. Lot of the logic I have placed in Java classes and the data format is mainly JSON.

I also separated the design from the data so in principle you should be able to place the app in the IBM Bluemix environment.

Because of these decisions there is no backward compatibility so a simple replace design will not work for your existing installation.

Below you can find some screenshots of the new interface. I hope you like it.

Screenshots

startpage

uploadprofilepicture

Thank you

I would like to thank all the teachers in our community who post their presentations, code samples and answers on the platforms out there.

I have tried to post the code on Github but this failed with the Github desktop client. If some can get me started with that I will distribute the project there too.

For now:

A Merry Christmas and fortune in 2016 !