RAD Table walker

For a project I received some very unclear description for a change. After a conversation I came up with the suggestion to rebuild the UI and present a Bootstrap table with add and delete buttons. Something what developers would call a table walker.

So how did I do this?

First I had to extend the Model object of my MVC model. The table repeats rows with persons details so I added:

The Person class is simplified as followed:

On my model object I also added getters and setters and and an add method:

Then I had to build the table with the following important elements:

  • a repeat control to represent my arraylist of Person objects
  • input fields bounded to the Person name and email
  • a button for each row to remove the Person from the arraylist
  • a button to display a new blank row to register a new Person

The code is not that long or complicated. I highlighted the important parts with bleeding yellow:

In the next phase I decided to replace the input field the name field with namespickers (by first name or by last name) wrapped as Bootstrap field add-ons. Here is the rough code:

This all resulted in a nice BS table with add / remove buttons:

Now I am just waiting for customer approval. That is mostly the longest part in Rapid Application Design.

Fiddling with jax-rs and getting frustrated

Today was probably not the best day for development. After getting the Jakarta EE project to work on the development server by a miraculous second signing of the plugins in the update site NSF and restart of HTTP on Domino (v10) my next step was to actually getting to get some code running.

Curious as I am I found some code samples here , here and here but after trying some of the samples in my NSF I keep on running on errors:

[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM: ERROR i18n RESTEASY002025: Unknown exception while executing GET /sample/counter
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM: org.jboss.weld.exceptions.AmbiguousResolutionException: WELD-001318: Cannot resolve an ambiguous dependency between: 
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:   - Managed Bean [class servlet.Sample] with qualifiers [@Any @Default],
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:   - Managed Bean [class servlet.Sample] with qualifiers [@Any @Default]
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.weld.manager.BeanManagerImpl.resolve(BeanManagerImpl.java:1164)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.cdi.CdiConstructorInjector.construct(CdiConstructorInjector.java:66)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.cdi.CdiConstructorInjector.construct(CdiConstructorInjector.java:73)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.plugins.server.resourcefactory.POJOResourceFactory.createResource(POJOResourceFactory.java:67)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:309)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:439)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:229)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher$$Lambda$95.0000000046F8EF20.run(Unknown Source)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:135)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher$$Lambda$96.0000000046F8F8D0.get(Unknown Source)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:355)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:227)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.openntf.xsp.jaxrs.impl.FacesJAXRSServletContainer.service(FacesJAXRSServletContainer.java:96)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.ComponentModule.invokeServlet(ComponentModule.java:600)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.domino.xsp.module.nsf.NSFComponentModule.invokeServlet(NSFComponentModule.java:1352)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.ComponentModule$AdapterInvoker.invokeServlet(ComponentModule.java:877)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.ComponentModule$ServletInvoker.doService(ComponentModule.java:820)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.ComponentModule.doService(ComponentModule.java:589)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.domino.xsp.module.nsf.NSFComponentModule.doService(NSFComponentModule.java:1336)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.domino.xsp.module.nsf.NSFService.doServiceInternal(NSFService.java:662)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.domino.xsp.module.nsf.NSFService.doService(NSFService.java:482)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.doService(LCDEnvironment.java:357)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.service(LCDEnvironment.java:313)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.domino.xsp.bridge.http.engine.XspCmdManager.service(XspCmdManager.java:272)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM: org.jboss.resteasy.spi.UnhandledException: org.jboss.weld.exceptions.AmbiguousResolutionException: WELD-001318: Cannot resolve an ambiguous dependency between: 
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:   - Managed Bean [class servlet.Sample] with qualifiers [@Any @Default],
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:   - Managed Bean [class servlet.Sample] with qualifiers [@Any @Default]
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:257)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:193)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:455)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:229)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher$$Lambda$95.0000000046F8EF20.run(Unknown Source)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:135)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher$$Lambda$96.0000000046F8F8D0.get(Unknown Source)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:355)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:227)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.openntf.xsp.jaxrs.impl.FacesJAXRSServletContainer.service(FacesJAXRSServletContainer.java:96)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.ComponentModule.invokeServlet(ComponentModule.java:600)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.domino.xsp.module.nsf.NSFComponentModule.invokeServlet(NSFComponentModule.java:1352)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.ComponentModule$AdapterInvoker.invokeServlet(ComponentModule.java:877)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.ComponentModule$ServletInvoker.doService(ComponentModule.java:820)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.ComponentModule.doService(ComponentModule.java:589)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.domino.xsp.module.nsf.NSFComponentModule.doService(NSFComponentModule.java:1336)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.domino.xsp.module.nsf.NSFService.doServiceInternal(NSFService.java:662)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.domino.xsp.module.nsf.NSFService.doService(NSFService.java:482)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.doService(LCDEnvironment.java:357)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.service(LCDEnvironment.java:313)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at com.ibm.domino.xsp.bridge.http.engine.XspCmdManager.service(XspCmdManager.java:272)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM: Caused by: 
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM: org.jboss.weld.exceptions.AmbiguousResolutionException: WELD-001318: Cannot resolve an ambiguous dependency between: 
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:   - Managed Bean [class servlet.Sample] with qualifiers [@Any @Default],
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:   - Managed Bean [class servlet.Sample] with qualifiers [@Any @Default]
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.weld.manager.BeanManagerImpl.resolve(BeanManagerImpl.java:1164)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.cdi.CdiConstructorInjector.construct(CdiConstructorInjector.java:66)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.cdi.CdiConstructorInjector.construct(CdiConstructorInjector.java:73)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.plugins.server.resourcefactory.POJOResourceFactory.createResource(POJOResourceFactory.java:67)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:309)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:439)
[14EC:0011-0484] 2020-02-12 21:24:57   HTTP JVM:  ... 23 more

Here is the code that I am running:

Domino2025 webinar – a technology U-turn?

In the last webinar around #Domino2025 time was spent on announcing NodeJS to/for/on Domino, a new search engine, NSF improvements but very little was discussed about the AppDev environment.

Today we have XPages as AppDev tool. Nothing about the lifecycle of this was announced. Or embracing an open source UI framework for JSF like Primefaces.

Some words about an “open IDE” environment which might be good to have the option to choose your favorite development environment. But the main problem I have that the whole webinar sounded like a complete U-turn in technology.

What will be your options as a Java developer?

Should you dump your learned skills and switch over to JavaScript and React, Angular or Vue?

Is there hope that JSF on Domino will be upgraded to a recent version so you can bring in new opportunities to your applications?

What must companies do with their existing XSP applications? Re-write them (again)?

To me it sounded IBM is keeping its hands of from developing and maintaining any development framework. The “traditional” Domino development framework with forms, views, pages, subforms is left dead. The “Web 2.0” Domino development framework with XPages and Java will be left for dead. The only thing that remains is a platform where applications reside, services like mail, replication, http, etc runs on. BUT WHAT ABOUT APPDEV?

I am not aware if there are any drag and drop IDE’s for react or angular but the power to Notes was and has always been rapid application framework. I build applications in close relation to my customer (an IT manager or a LOB manager) which does not have the time or competence to set up and gather all the specifications in front. It is a journey of implementing capabilities and discovering opportunities. I may develop a new idea within an hour or rebuild or remove another idea within another hour.

I heard nothing about this during the webinar!

Lesson learned in ReplaceItemValue vs NotesItem

Introduction

In a project I am working on I am modernizing a Domino application with XPages and JAVA MVC. To support the workflow in the application a “main” document must have at least 1 approved “sub” document for 9 mandatory areas. These “sub” documents appear then in a Notes view and an agent is keeping the overview if all 9 areas have approved documents .

The selection formula for this view is something as followed:

SELECT Form=”formA” & status=”40″ & notAuthorized = “”

replaceItemValue

To add a field to a document I normally use ReplaceItemValue as described in the XPages wiki.  The Help in Designer says about this method:

Replaces all items of the specified name with one new item, which is assigned the specified value. If the document does not contain an item with the specified name, this method creates a new item and adds it to the document.

So that sounded that I was good to go. Except… the documents created by my script did not appear in my view.

Document properties

When I compared the documents with ScanEZ / looked at the Document Properties tab / created on output via Document Viewer I could not find an explanation why the documents should not match the View selection formula 😕

Modifying the selection formula to something outrageous like

SELECT Form=”formA” & status=”40″ & notAuthorized != “SOMEOUTRAGEOUSCONDITION”

resulted that the documents appear in the view.

But I would rather like to keep the current data model of the View as is in place so the current code/UI could not become disturbed in any way.

Notes Item

Then I decided to change my code from

doc.replaceItemValue(“notAuthorized”, “”);

into

Item textItem = doc.replaceItemValue(“notAuthorized”, null);

textItem.setValueString(“”);

textItem.setSummary(true);

and I noticed the documents appear now in the Notes View.

When I compare the two methods in the replaceItemValue method the field notAuthorized is empty but has a data-length of 1. In the Item method the field is also empty BUT the data-length is 0.

So something is added to the field. But what?

IsSummary

First I thought perhaps it’s due to the Summary property but in both methods the Summary property set (at least it looks like that).

Here is some more information from Designer Help:

 

The IsSummary property of the new item defaults to true, which means that the item value can be displayed in a view or folder.

So I am wondering if the replaceItemValue (in Java) is properly setting this property or maybe not?

 

Passing a SSJS function to a custom control

Introduction

I am building a custom control that mimics the viewPanel control but it is a repeat control which data is not a view but a managed bean that returns an arraylist of java objects (representing Notes documents).

I am using a Bootstrap table for display I in a previous post I have demonstrated how I can provide a JSON object to have flexibility in the columns I want to display and the values I want to display.

Next step is the option to provide custom actions to the custom control, in a way that the code under an action button in the custom control is provided via a property. So in one case hitting the button could print all selected documents, in the other case it could remove all documents from the database.

Step 1 – Creating an arraylist of unid’s

Key here is that I have an arraylist of unid’s to work with. The technique how to select documents in a repeat control was demonstrated by David Leedy in Notes in 9 episode 25. Instead of buttons I use a checkboxgroup:

So now I want from my xp:button in my custom control do something with this arraylist of unid’s…

Step 2 – set up the property definition

Next step is to setup the property in the property definition of the custom control:

Not the most common type of class and editor you use for a property.

Step 3 – setup the event handler for the button

In order to have the button to understand that the action to be performed is coming from a action property we need to specify that in the onClick event:

(Note: my property resides in the group property actionButton)

Step 4 – set up the SSJS  function you want to run

So now our button knows it’a action comes from a propert we need to write the SSJS function for the button. I have placed it in a SSJS script library. Here is an example to remove documents from a database:

Step 5 – Add the SSJS to the property

The last step is the most tricky one. In the property you are not allwed to provide any parameters or parentheses for the SSJS function. So our action property becomes as followed:

Result

As a result I have the following UI:

  • A custom control with a button which onClick action is provided via a property on that host xpage.

IBM Champion Nomination

Is this blog-article useful to you? Perhaps you can nominate me as IBM Champion.

A generic approach to display Notes data via a Bootstrap table

This week I became inspired by a question I noticed on Stackoverflow regarding collecting values from Java objects.

For a project we were discussing what to use for display “Notes View data”:

  • jQuery DataTables plugin and use a customRestService via a Java class as data provider for the JSON.
  • a Repeat control and display an Arraylist of Java objects.

Some of the participants liked the jQuery approach because it provides a lot of functionality out of the box (sorting, search, responsiveness,…) and their lack in knowledge regarding Java.

Others were questioning of the Repeat control approach would be flexible enough so we could display easy different sets of data with different number of columns.

So… to the drawing board.

Mostly in Notes views (e.g. via the View Panel control) one column serves as link (often the first) and all others just display data of all kind. In the DataTables plugin the display is flexible because you can define a custom render function for each column which is great. So you could display a button that will call a dialog to interact with the underlying document for example. However this custom render definition resides in a CSJS library so becomes part of the design.

I had already a custom control that could consume properties for the data and how to set a fixed set of columns. So the last part I needed to make flexible.

Because I have an arraylist of Java objects as source for my Repeat control I need to access the fields “on the fly” when rendering the column values. This turned out to be quiet simple because the fields are already in my Java object.

In my approach I provide the columns via a JSON object that could look as followed:

dyntable00

 

And for my columns I repeat it and collect the value from my underlying Java object:

dyntable01

Note: my code is not final, I would to define more types of data and the option to provide a custom render function for each column. So far I only have computation for string and date fields.

I also applied some basic functionality as Pager controls (top + bottom), a Page Sizer control, icon display and row numbering.

Here is what a result might look like:

dyntable001

Nothing special but now now I have just one custom control to display 80% of my tables/views.

Here are the GIST files for the custom control and its configuration xml file.

IBM Champion Nomination

Is this blog-article useful to you? Perhaps you can nominate me as IBM Champion.

Using the beanNamePicker dataProvider for a namepicker

For an application I needed to provide a namepicker with data from a NotesView. Unfortunately I could not use the default dominoViewNamePicker option as the data provider because the column to select from may not be a multi-value field or contain multiple fields. 😕

A search on google provided me an example how to use a beanNamePicker that will read the data from Domino Directories.

I created a GIST for the XPage: https://gist.github.com/PatrickKwinten/0bcc951a8eb1f5ef287c0c9b05a535a3 and for the Java class it uses: https://gist.github.com/PatrickKwinten/4aa15ea09717833bcc9fd1a941d9e5a8 .

Basically here is how you set it up:

<xe:namePicker id=”npDomino” for=”person1″>
<xe:this.dataProvider>
<xe:beanNamePicker dataBean=”org.wordpress.quintessens.demo.app.NamePickerDirectory”
loaded=”true”>
</xe:beanNamePicker>
</xe:this.dataProvider>
</xe:namePicker>

Key is that you return an object of type SimplePickerResult containing a list of objects of type <IPickerEntry>.

For my case I needed to go to a view where all the activities for users for the application where logged. Again I used a similar setup:

<xe:namePicker id=”npDomino” for=”person1″>
<xe:this.dataProvider>
<xe:beanNamePicker dataBean=”org.wordpress.quintessens.demo.app.NamePickerView”
loaded=”true”>
</xe:beanNamePicker>
</xe:this.dataProvider>
</xe:namePicker>

But now I go to a different class which I created a Gist for: https://gist.github.com/PatrickKwinten/c3580344a48704b3589251c0d5bbb8e5 .

Key difference is that my data source has become a Notes view and I check the type of column (columnValue instanceof String, ArrayList, Vector) because I have different type of fields and values in my first column.

So once you understand how you can extend the basic functionality within XPages you gain much flexibility and new opportunities with out of the box controls.

Please IBM provide us with more examples!!!

IBM Champion Nomination

Is this blog-article useful to you? Perhaps you can nominate me as IBM Champion.

 

 

XPages sufficient for line of business type of applications?

Hi there, currently I am following another Angular course since it seems to have become the leading development framework at work. So back to learning all the rules within Angular.

At the moment I am modernizing a Domino application with the help of XPages which:

  1. Implements Model-View-Controller architecture, mostly inspired by the guys at Pipelia since IBM never told us to do so.
  2. Is written in Java to support the MVC architecture and to have close integration with XPages runtime.
  3. Is using Expression Language wherever possible to avoid usage of SSJS.
  4. Uses the lifecycle of JSF in XPages at the max.
  5. To cover support for different devices I am using Bootstrap as front-end framework. So I miss some native behavior which I do not tend to cover-up.

So far so good and I think I have come quiet long in my project so I still dare to call it rapid application development.

The code-base has been reduced dramatically and all exotic upcoming JavaScript libraries from the early 2000 I have been able to replace with just XPages. With my latent UX skills and extending the out of the box Bootstrap I might now even call this application ‘sexy’ 🙂

I know I haven’t touched many areas discussed in the XPages community such as:

  • Websockets (I do not see a use-case yet).
  • Writing Java servlets (please pass me a demo NSF).
  • Watson services (cloud is still a sensitive topic).
  • set up micro-services with smartNSF and consume them in my Java code with an mapper library (requires changes in the environment).
  • Integration with IBM Connections.
  • Redefining my data with the help of a Graph DB.

Either I see little usage, it is not possible or there is no-one to guide me (the information is certainly not provided by the vendor).

So now back to Angular. Learning all these rules, technologies and new tools setup I was wondering what new technical options this framework will bring me at work. Reflecting on the type of customer-orders I receive I am wondering:

Is XPages not sufficient for most of your line of business apps?

Perhaps you have a though about this?

Happy development & enjoy your summer 🙂