Registration Node-RED application with Cloudant

In my last blog post, I shared my newest Node-RED lab, Custom Nodes in Node-RED. I showed how to create a custom node to sort an array, use a HTML PDF node from the Node-RED community, and build a registration application in a Node-RED application running on IBM Buemix.

customnodes7

At the end of the lab I leave a challenge to the developer to make the application persistent. Let me explain a bit more.

Node-RED has a global context that lives in memory. When you store data, such as with the JavaScript in the following code, it isn’t written to disk, to a database, or any persistent storage.

global.set('attendeelist', ['Joe', 'Alex', 'Mary']);

When the Node-RED application stops, this data goes bye-bye. A Node-RED application could stop for a number of reasons:

  • Cloud Foundry restarts the application instance
  • you bind a new service and restage the application
  • you intentionally shut down the instance
  • Node-RED crashes

Using the global context in this case isn’t the best idea after all. In this blog post, I’ll show how a couple of changes to the flows can utilize a Cloudant NoSQL database and make the list live on.

If you’re running Node-RED on IBM Bluemix, the good news is you don’t have to create any new services. Behind the scenes, Node-RED uses a Cloudant NoSQL database to store the flows, for a similar reason as I mentioned above. You see, if Node-RED kept the flows in memory, they would disappear on a restart. If Node-RED stored the flows in the filesystem, as a locally installed Node-RED application does, when IBM Bluemix redeploys the application the flows would be lost as the filesystem isn’t retained. So, keeping the flows in Cloudant makes a lot of sense.

rostercloudant2

Using the Cloudant nodes that are included in the node-red-node-cf-cloudant npm package, we can add them into the flow and select a database.

For the flow connected to the POST /register node, we’ll add three nodes and modify two existing nodes.

Add a change node to move the name property from the payload to the msg object. This saves the name from being overwritten in the msg.payload object. Set the id property to set the id of the document id we’ll pull from Cloudant.

rostercloudant3

Connect a cloudant in node, using a database name such as names.

rostercloudant4

Modify the existing node labeled Add Attendee to List. Instead of using the global context, we’ll check to see if the attendee list document exists in Cloudant. If not, we’ll create one. Instead of storing the list back into the global context, we’ll append it the msg.payload.attendeelist property.

// If no document was found, create a new one.
if(!msg.payload) {
    msg.payload = {
        attendeelist: [], 
        _id: 'attendeelist'
    };
}

msg.payload.attendeelist.push(msg.name);

return msg;

rostercloudant5

Add a Cloudant out node which will take the msg.payload and store it in a JSON document in the Cloudant database.

rostercloudant6

Lastly, modify the Display Confirmation template and change {{payload.name}} to {{name}} to read the msg.name property.

rostercloudant7

The modified flow should look like the one shown below.

rostercloudant8

If we submit a name or two and look at the document in the Cloudant dashboard (access the dashboard through the service tile in your IBM Bluemix account), we’ll see the document expanding.

rostercloudant9

For the flow connected to the GET /roster node, we’ll add a couple of new nodes.

Add a change node to set the id of the document we’ll pull from Cloudant.

rostercloudant10

Add a Cloudant out node which gets the document, if it exists, from our database.

rostercloudant11

Add a switch node. This will check to see if the document exists and was returned.

rostercloudant12

For the case that the document does exist, add a change node to move the attendeelist into the msg.payload property.

rostercloudant13

For the case that the document doesn’t exist, add another change node to set the msg.payload to an empty array.

rostercloudant14

This will make sure the msg.payload is an array, empty or populated with names. Both this scenarios are then passed to the sort node with the completed flow shown below.

rostercloudant15

Go visit the /roster endpoint of your Node-RED application.

rostercloudant16

To see what happens if the Bluemix application restarts, open a new window and go to the application overview. Click on the restart icon. When the application comes back online, the list will remain.

Oh, and there’s one more thing that’s left. How do you clear out the list?

I added a /roster/reset endpoint that fetches the attendeelist document in Cloudant, and if it exists, sets it to an empty array and stores in back into Cloudant. The JSON is shown below.

[{"id":"5b4b22dc.61ee4c","type":"http in","z":"91de3816.0cb58","name":"","url":"/roster/reset","method":"get","swaggerDoc":"","x":120,"y":600,"wires":[["51bbe093.193fd"]]},{"id":"ea2d7463.bdc538","type":"template","z":"91de3816.0cb58","name":"List Cleared","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"\n    \n        

List is cleared. Register

\n \n\n","x":960,"y":605,"wires":[["1a2d5124.ce8247"]]},{"id":"1a2d5124.ce8247","type":"http response","z":"91de3816.0cb58","name":"","x":1141,"y":605,"wires":[]},{"id":"11ff7f50.11b839","type":"cloudant out","z":"91de3816.0cb58","name":"","cloudant":"","database":"names","service":"","payonly":true,"operation":"insert","x":910,"y":540,"wires":[]},{"id":"ae78ad10.af961","type":"cloudant in","z":"91de3816.0cb58","name":"names","cloudant":"","database":"names","service":"","search":"_id_","design":"","index":"","x":470,"y":600,"wires":[["3cde74b8.0ad03c"]]},{"id":"51bbe093.193fd","type":"change","z":"91de3816.0cb58","name":"","rules":[{"t":"set","p":"payload.id","pt":"msg","to":"attendeelist","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":600,"wires":[["ae78ad10.af961"]]},{"id":"3cde74b8.0ad03c","type":"switch","z":"91de3816.0cb58","name":"","property":"payload","propertyType":"msg","rules":[{"t":"nnull"},{"t":"else"}],"checkall":"false","outputs":2,"x":590,"y":600,"wires":[["dae60c18.2c6058"],["ea2d7463.bdc538"]]},{"id":"dae60c18.2c6058","type":"change","z":"91de3816.0cb58","name":"Empty List","rules":[{"t":"set","p":"payload.attendeelist","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":734,"y":571,"wires":[["11ff7f50.11b839","ea2d7463.bdc538"]]}]

rostercloudant17

rostercloudant18

The completed Node-RED application is shown below. You can find the completed flow in my GitHub repo.

rostercloudant19

Posted in Node-RED | Comments Off on Registration Node-RED application with Cloudant

Custom Nodes in Node-RED

Since I first saw Node-RED at a hackathon last year, I’ve been intrigued with what it could do. From simple nodes that make a webpage, to using Watson services like Language Translation and Text to Speech, to pulling in Weather Company Data, to analyzing a body of text or images with AlchemyAPI, oh, and of course the Internet of Things, Node-RED makes prototyping together an application quickly really easy.

However, I often get asked by developers who come to my workshops about how extensible Node-RED can be. Often times Node-RED is compared to other block programming tools that are used to teach kids how to think logically. In reality, Node-RED is for kids of all ages.

Node-RED either wins the developer over, or developers get lost in the “too basic for a real coder” mindset. Some developers are pretty adamant about writing code, and aren’t satisfied with the simple function node available. True, Node-RED abstracts out the code, but on purpose. Being able to wire something up quickly can save some time for other more important things.

In my latest lab, Custom Nodes in Node-RED, I wrote a tutorial to show how to write your own custom node in Node-RED running on IBM Bluemix. It’s a powerful responsibility, so use the force wisely. Although the example is simple, sorting an array, it shows how simple it is behind the scenes.

customnodes

I used the IBM Bluemix DevOps Service editor to create the two files (a JavaScript file and a HTML file) for the node, and then deployed the changes to the Node-RED application in IBM Bluemix.

customnodes2

customnodes3

I also show how to install nodes from the community like the HTML PDF node. I came across this node as I was planning this lab, and it didn’t disappoint. I should go back and create my reports in a PDF file for my manager from Node-RED, eh?

customnodes4

The lab finishes off with a sample registration application. It uses the global context to store names of attendees who check in, and then displays the list in alphabetical order in a PDF file.

customnodes5

customnodes6

The completed flows are shown below.

customnodes7

I left a challenge up to the developer to make the list of attendees persistent using a Cloudant NoSQL database. When the application restarts, the in-memory global context list of attendees is wiped out. Since Node-RED uses Cloudant to store the flows, there are only a couple of changes in the flows that are necessary to make this happen. Stay tuned for my next blog post where I show my solution to this challenge.

Posted in Node-RED | Comments Off on Custom Nodes in Node-RED