Ben Langhinrichs

Photograph of Ben Langhinrichs

E-mail address - Ben Langhinrichs






April, 2020
SMTWTFS
   01 02 03 04
05 06 07 08 09 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30

Search the weblog





























Genii Weblog


Civility in critiquing the ideas of others is no vice. Rudeness in defending your own ideas is no virtue.


Wed 8 Apr 2020, 11:25 AM
Inline JPEG image
 
In my previous post, A bigger boat: growing the vision for Domino development, I introduced the idea (with a demo!) of an extensive set of Notes/Domino functionality exposed in different ways, in this case LotusScript and JavaScript with Node.js. The idea is that we need Domino API functionality available where projects are. If a company is using Node.js extensively, we need that functionality there, not in LotusScript. But if a company has invested a lot in LotusScript, we need the functionality there. Likewise, while we might wish everybody would rush to Domino 11, there are companies on 8.5.3, 9.0.1, 10, and 11. We need to reach them where they are if we want widespread adoption,
 
In this post, I wanted to talk about lower level ways in which we reach the developer where she or he is. Some developers are used to LotusScript, so we'd like to make it easy for them to translate their skills even if they have to work in JavaScript. Other developers are coming to this with extensive JavaScript skills, and we'd like to make it easy for them as well. Additionally, there are strengths in JavaScript we don't have in LotusScript, and we'd like to make those available.
 
Let's look at an example:
 
Parameters
rtchunk.appendText("Duck season!", 12, "Bold 12pt");
rtchunk.appendNewLines(1, false);
rtchunk.appendText("Rabbit season!", 14, "Bold 12pt");
rtchunk.appendNewLines(1, true);
 
In LotusScript, methods are called with a series of defined parameters. Some parameters are required, while others are optional. One of the design decisions we made with Exciton Power is to provide more options rather than fewer. It is a risk, as people could get confused or wonder which is "correct", though under a very thin layer, the choices do exactly the same thing. So, we provide the option of using LotusScript-style parameters and validating them the way we would in LotusScript.
 
Objects
But JavaScript developers are often more comfortable with objects, both unnamed and relatively unstructured objects and objects which are part of defined classes. This could could be written as objects using:
rtchunk.appendText({text: "Duck season!", textLen: 12, fontSpecs: "Bold 12pt"});
rtchunk.appendNewLines({count: 1, newParagraph: true});
rtchunk.appendText({text: "Rabbit season!", textLen: 14, fontSpecs: "Bold 12pt"});
rtchunk.appendNewLines({count: 1, newParagraph: true});
 
Slightly more self-documenting, but not terribly different. But let's name those objects and see some differences:
 
var txtObj = {fontSpecs: "Bold 12pt"};
var nlObj = {count: 1, newParagraph: false};
 
txtObj.text = "Duck season!";
txtObj.textLen = txtObj.text.length;
rtchunk.appendText(txtObj);
 
nlObj.newParagraph = 
rtchunk.appendNewLines(nlObj);
 
txtObj.text = "Rabbit season!";
txtObj.textLen = txtObj.text.length;
rtchunk.appendText(txtObj);
 
nlObj.newParagraph = true
rtchunk.appendNewLines(nlObj);
 
At first glance, this is even longer and less clear, but we have separated out how we set the font specs so that can be handled elsewhere according to some other rule, and changed the logic so the textLen property can be calculated instead of hard-coded. We could then take this another step further, and make the txtObj a class where the txtLen was calculated automatically when the text was set, and you could separate out setting point size from setting other attributes, for exampe. 
 
class TextObj {
  constructor() {
    this.ptSize = "10pt";
    this.attribs = "Plain";
    this.color = "Black";
    this.face = "sans-serif";
    this.fontSpecs = this.ptSize+" "+this.attribs+" "+this.color+" "+this.face;
  }
  setText(t) {
    this.text = t;
    this.textLen = this.text.length;
  }
  setPtSize(pt) {
    this.ptSize = pt;
    this.fontSpecs = this.ptSize+" "+this.attribs+" "+this.color+" "+this.face;
  }
}
 
var txtObj = new TextObj();
var nlObj = {count: 1, newParagraph: false};
 
txtObj.setText("Duck season!");
rtchunk.appendText(txtObj);
 
nlObj.newParagraph = 
rtchunk.appendNewLines(nlObj);
 
txtObj.setText("Rabbit season!");
rtchunk.appendText(txtObj);
 
nlObj.newParagraph = true
rtchunk.appendNewLines(nlObj);
 
 
With classes, you can implement rules so that certain things are and aren't allowed. Obviously, all of this can be done in LotusScript in a more cumbersome way, but we wanted to meet JavaScript developers where they are and also take advantage of individual language strengths. With the option of either explicit parameters or a JavaScript object, we go to war with the army we have, whatever army we happen to have.
 
 
If you would be interested in participating in the Exciton beta, or even if you just have questions, contact me by e-mail at 
 

Copyright 2020 Genii Software Ltd.

Tags:

Thu 2 Apr 2020, 04:34 PM
Inline GIF image
 
In this classic scene from Jaws, police chief Martin Brody already knows he is facing a dangerous creature, but when the great white shark finally appears, he realizes has been thinking on the wrong scale. Over the years, the phrase, "You're gonna need a bigger boat" has become a popular way of saying that you have underestimated the problem.
 
HCL is doing wonderful things with Domino, building an infrastructure made for today's world, and especially today's web. But the folks at Iris and later Lotus realized early on that you could build the best platform in the world, but it wouldn't do you any good if people couldn't build their business apps on it. They went all in on APIs to make it possible to do fantastic things, well ahead of the competition. But the competition has had a lot of time to improve. Look around at Microsoft and Google and Amazon and a hundred other smaller tech companies, and you realize that if Domino is going to carve out a place in this world, we need a bigger boat.
 
We at Genii Software have a vision for a comprehensive set of functionality that transcends the traditional Domino development framework. We are not competing with HCL, and won't hesitate to piggyback off of their technology where we can. The goal is not to beat HCL, but to enhance the development landscape along with them for all our sakes. Basically, we want to build a bigger boat together with HCL and other partners.
 
This very brief demo shows a first look at our Exciton Power offering, in beta now. This is a Node.js module with (currently) six classes, over two hundred methods, and over 150 properties, all allowing you to build kick butt business apps combining the wealth of Node.js modules with the power and security of Notes/Domino. If you've seen my recent demos, you'll recognize the functionality shown here, but in JavaScript instead of LotusScript. The code below the demo should look very familiar to those who know and love the Midas LSX, but this is more than a Midas port to JavaScript, and it goes far beyond rich text, including form/view/etc. design, data mining, high fidelity rendering, and more. All available to work with both local and server-based databases using the traditional Notes security model, whether your Notes ID is local or in the ID Vault. Oh yes, and you'll notice the demo is in Notes 9.0.1. Exciton Power is built to work with Notes/Domino 8.5.x/9.x/10.x/11.x on both 32-bit and 64-bit Windows and 32-bit and 64-bit Linux. If you need to build a Node.js app for a Domino customer, you don't want to worry what version or OS they are on. You want to meet them where they are, and then take them where you are going.
 
 
If you would be interested in participating in the Exciton beta, or even if you just have questions, contact me by e-mail at 
 
Source Code for demo:
Let's take a quick look at the code. I am using the really basic approach to fulfilling the HTTP request, but you obviously can grab the results of the GET however you like. Just make sure it is a JSON text stream when it is passed to the methods. (This is a first look of the beta, so don't count on everything being exactly like this.) Not bad for 47 lines of code, eh?
 
const https = require('https');
const useExcitonPower = require('./build/debug/ExcitonPower32');

// *** Initiate a session
const gs = useExcitonPower();

// *** Connect to a rich text item
const rtitem = gs.useGRTItem();
rtitem.connect('', 'UseCases.nsf', '2E92311B5BB4CB168525853D0016F8E5', 'Body', true);
const rtchunk = rtitem.useGRTChunk(rtitem);
rtchunk.defineChunk(rtitem, "Everything");

// *** Define the properties to access the data
const props = "AsTable='horizontal' AsObjectArray='yes' TitleFont='Bold #004080' TableWidth='Fit with margins'";
const col1props = "Text='' TextFont='Bold #004080'";
const col2props = "Text='' TextFont='-Bold #084000'";

// Add the first tab with data about how many tests have been run
https.get('https://covid19-server.chrismichael.now.sh/api/v1/TestsinUS', (resp) => {
  let data = '';
  // A chunk of data has been recieved.
  resp.on('data', (chunk) => {
    data += chunk;
  });

 // The whole response has been received. Add the internal table to tab 1
 resp.on('end', () => {

  // *** Add the title, and make everything Verdana to look better
  rtchunk.setFont("Plain 10pt Default Sans Serif");
  console.log("Adding tabbed table with two tabs.");
  rtchunk.appendTable(1, 1, "RowDisplay='Tabbed' TabFont='14pt Bold' BorderEffects='Drop_Shadow'",
          "CellColor='RGB227,234,240' TabLabel='COVID-19 Testing' Width=4");
  rtchunk.zoomIn("Table 1");
  rtchunk.appendRow(false, 1, "CellColor='RGB227,234,240' TabLabel='World Stats'");
  rtchunk.zoomOut();
  
  // *** Appends the fields to the form and save
  rtchunk.zoomIn("Table 1; Row 1; Inside column 1");
  console.log("Adding nested table inside first tab with Testing stats from one REST API call.");
  rtchunk.appendFieldsWithJSON(data, props+" ChildOf='tests.table'", col1props, col2props);
  rtchunk.zoomOut();

  // Add the second tab with data about how many tests have been run in the U.S.
  https.get('https://covid19-server.chrismichael.now.sh/api/v1/AllCasesInAmerica', (resp) => {
    data = '';
  
    // A chunk of data has been recieved.
    resp.on('data', (chunk) => {
      data += chunk;
    });
  
    // The whole response has been received. Add the internal table to tab 1
    resp.on('end', () => {
    
    // *** Appends the fields to the form and save
    rtchunk.zoomIn("Table 1; Row 2; Inside column 1");
    console.log("Adding nested table inside second tab with World stats from a different REST API call.");
    rtchunk.appendFieldsWithJSON(data, props+" ChildOf='data.table'", col1props, col2props);
    rtchunk.zoomOut();
  
    rtitem.save();
    console.log("Document saved");
  });

  }).on("error", (err) => {
    console.log("Error: " + err.message);
  });
  
});

}).on("error", (err) => {
  console.log("Error: " + err.message);
});

 
 

Copyright 2020 Genii Software Ltd.

Tags:

Thu 26 Mar 2020, 03:47 PM
Yesterday, in my post From REST to Notes db in two seconds, I showed how you could pull data from a REST API and create an "instant" database. But, of course, the devil is in the details, and not all formats work particularly well. I have a special interest in Salesforce as a lot of friends have started to work for them or with the software, so I decided to show how some sample Salesforce data including custom fields would translate.
 
I should note, these demos are currently done in LotusScript with the Midas LSX in an unreleased version. We are building them into Exciton Power for Node.js. Both should be available in a matter of weeks, and any feedback would be greatly appreciated.
 
First, the data itself. Assume that the following was pulled in a query from a Salesforce REST API. It is only one of the records, but they all look like this.
 
Inline JPEG image
 
There are a number of default choices we make for you. There is a display title which is different than the Notes item sometimes, which is yet again different than the JSON value. For example, the "attributes" value is a JSON object, so how should we save it? How should we display it in Notes? Here are a few of the rules we follow:
 
1) For the "attributes"  object, we save two separate internal items:  attributes.type with the value "Merchandise__c", and  attributes.url with the value "/services/data/v20.0/sobjects/Merchandise__c/a00D0000008oWP8IAM". That looks like this:
Inline JPEG image
 
 
2) On the form, we skip object items called "type" even though we save them in the document. We include an editable text field called attributes.url, but we use the name Attributes (url)as the prompt. That looks like:
Inline JPEG image
 
3) In the view, we skip the objects entirely. Thus, the Id is the first column shown, even though the  attributes.url item exists on the documents. 
Inline JPEG image
 
While we are looking at the view, note that the "OwnerId" item has a title Owner Id of but is saved as an item called OwnerId. We use the capitalization to add spacing here if it appears to be proper-cased. Another thing to note is that "Price__c" item has a title of Price but is saved under the name Price__c. We recognize that Salesforce adds those suffixes, and we keep them for data purposes but don't see a need to display them. 
 
4) Another thing to note is that a boolean (true/false) value such as "IsDeleted": true is saved as text "true", In the view, it is centered, and on the form, it shows as a radio button:
 
Inline JPEG image
 
There are many other small assumptions we make, some of which can be overridden with properties, but we are not done. We haven't entirely decided whether presumed date fields should be stored as such (probably), and whether we should be able to handle other special cases like the Salesforce suffix (maybe). The more examples we try, the more we learn and tweak.
 
If you have a REST API data source you use regularly or would be interested in using, let us know and we can see how well it fits.

Copyright 2020 Genii Software Ltd.

Tags:

Wed 25 Mar 2020, 01:51 PM
A few days ago, Karl-Henry Martinsson (aka "TexasSwede") wrote an excellent post showing how you could use the new JSON classes in LotusScript to retrieve current state date on the pandemic. I encourage you to read it, and to see how the classes work and can be used with any JSON data, usually derived from a REST API.
 
As I have been talking about high value methods, I thought I'd show how chaining a few together can take the JSON result of a REST API from almost any system out there that provides one, and turn it into a Notes db with a minimum of effort. But rather than a simple drab form, I show how you can make the form look good and be more functional. 
 
A few advantages to this approach:
 
1) You don't have to learn almost anything about JSON;
2) You don't have to build a custom script for each REST API;
3) You can get down-and-dirty with the business logic, not the logistics.
4) You can develop a spiffy (or corporate-approved) look-and-feel to use over and over
5) You can even use this in Notes 9 (with slight changes to get the data)  because your company is slower than the last hour before quitting time.
 
If you want to skip to the demo, here it is. I'll show the code below it.
 
 
 
 
I'll show the more complex agent first, then the simpler agent.
 
Final agent:
 
Inline JPEG image
 
 
Simpler agent:
 
Inline JPEG image
 
You can see the images in higher resolution by view them by themselves.
 
 

Copyright 2020 Genii Software Ltd.

Tags:

Thu 19 Mar 2020, 01:05 PM
 
Inline JPEG image
 
Talk is cheap, so as a follow-up on my post, Mind the Gap - A mid-level development manifesto, I wanted to show an example that we are adding to both the Midas LSX (LotusScript) and Exciton Power (Node.js and more).
 
A major draw of our Midas LSX has always been its simplicity combined with power. Developers just venturing into LotusScript could build fairly complex applications and do high-level tasks in a few lines of code. Now, we are taking that approach even further, and adding more high value methods that meet the needs of mid-level developers, while being powerful enough for pro coders to use as well. All the mid-level value methods from Midas are still in place, and some of those were pretty high value already, but these high value methods encapsulate a set of tasks into a single call mostly driven by data, not code.
 
Today's example is AppendFieldsWithJSON. This deceptively simply method allows the developer to populate fields on a form in a variety for formats, and allows styling based on a rich set of optional parameters. In the demo below, I start with the form design in the node-demo.nsf sample database from the AppDev Pack 1.3. In that sample, the forms are basic, only really intended to hold data, not to display or edit it. I decided to show how you could dynamically create a form with the same fields (and more) using a simple JSON array of values. The goal is similar to the goal of HCL Volt, but at a level where a mid-level developer can build up a toolkit combining the automatic generation of design with the business logic needed for their individual company. Also, as we'll see in future posts, the resulting form elements can be further manipulated and enhanced with existing mid-level methods.
 
Through the demo, I show how you can tweak the script to build up to a fancier form, all using the same AppendFieldsWithJSON call. I show how you can easily add additional fields just by adding them to the JSON value. For example, the image at the top includes the simple text fields and one number field from the node-demo.nsf Contact form plus a new computed FullName field.
 
Because this process is data-driven, you can make a script that follows company guidelines and includes all sorts of common features and styles, but then dynamically create the form fields wherever you like. There will likely be additional demos for this high value method, as it can actually do much more than I show here.
 
 
 
 

Copyright 2020 Genii Software Ltd.

Tags:

Thu 19 Mar 2020, 10:06 AM
Inline JPEG image
 
Low-Code and Pro-Code Advances
HCL has done a great job building up the infrastructure for Domino 11, and has made good progress toward a micro-services architecture, basic Node.js support, and other goodies for pro coders. Simultaneously, they've been adding value for low coders/citizen developers with HCL Volt. But as they have acknowledged many times, there is too much of a gap between the two. It is difficult to make the leap from citizen developer to pro coder. If anything, the gap is widening, and HCL doesn't seem to have particularly good answers for how to fill that gap. They have plans, but not the grand vision required.
 
The need is great and urgent
This is a problem. As governments and companies grapple with the increasingly long-term implications of the COVID-19 pandemic on their need for running distributed enterprises, they will need developers who are closer to the business end than the tech end, or the very mid-level developers who are left out or marginalized by recent app dev efforts. There is no time to waste, and plenty of other companies trying to meet the needs with solutions and technologies no where near as mature or complete as Domino.
 
Defining what is needed
We need APIs and technologies to bridge the gap. They need to be powerful, yet simple. They need to be intuitive enough that somebody who didn't study software in college can pick it up, but still flexible enough that somebody who did study software in college can use it. We need APIs that focus on Domino-specific functionality, not simply general web or business tech. We need APIs that allow dynamic design, rapid evolution, and a pathway from day one to forever.
 
The Domino development future isn't built around LotusScript and formula language anymore, but a vast amount of LotusScript is still out there. So, we need APIs that bridge the gaps between LotusScript and formula language and the more widely accepted languages, JavaScript, Java, Python, TypeScript, Go, and so forth. We need APIs that allow mid-level and pro-coders to tap into the vast libraries of modules in NPM and Apache Maven and others. We need APIs that allow mid-level and pro-code developers to take results and logic from these shared modules and libraries and use them inside Notes/Domino quickly and completely. We need APIs that allow quick and seamless integration with other software packages and platforms. While the AppDev Pack is a good starting point, it deals with Domino as if it is nothing more than a data store, when it is really a design and application store. We need APIs that recognize those features and use them effectively, inside and outside of Domino. We need APIs that work on any device, that allow both server and client-side logic, and all within a secure framework.
 
If HCL doesn't meet the need, we must
The world is in chaos and will be for a long time. For the sake of our customers, our companies, and ourselves, we need to make this work. At Genii Software, we have a long history of building for the mid-level developer, and helping the citizen developer become a mid-level developer, and eventually a pro-coder. We cannot and will not wait to see if HCL can meet this need all by itself. Keeping businesses intact, functioning and moving forward is our primary goal, and Notes/Domino is the best platform for accomplishing that, but only if we can tap into its strengths. Creative, new applications built around collaboration and distributed, secure enterprises are needed now, today, perhaps even yesterday. Of course, Genii Software isn't the only ISV developing solutions in this area. If you are aware of others, please mention them in the comments so people know. Let's do this! 
 
Update: Watch a demo of one of the API methods we are trying out in my new post: High value methods: AppendFieldsWithJSON.
 

Copyright 2020 Genii Software Ltd.

Tags: