Analysis / Technology / Top Stories / Tutorials /

Walkthrough: Building A Database-Driven Serverless Application on IBM Bluemix

22 Sep 2017 4:00am, by

IBM Bluemix and OpenWhisk are not new to The New Stack readers. We covered various articles covering the overview and architecture of OpenWhisk.

This tutorial helps you configure a Node.js function that is automatically triggered whenever a new row is inserted into a database. We will take advantage of the the integration between Cloudant “DB as a Service” and OpenWhisk “Functions as a Service” in IBM Bluemix PaaS.

Let’s assume we have a database to capture sales orders. Each time a sales manager closes a deal, a new row is added to the table. Our goal is to send out an email alert if the order value is beyond a specific threshold.

Since we are building the notification engine as a serverless application, it is possible for us to extend the alert delivery as a SMS, mobile push notification, or even a Slack channel notification.

There are three steps to this tutorial: Configuring the environment, creating the Cloudant NoSQL database, and finally configuring and deploying an OpenWhisk function.

Configuring the Environment

If you haven’t signed up with IBM Bluemix, go ahead and create an account for yourself. The free tier quota is sufficient for completing this tutorial.

Once you have an active Bluemix account, download and configure the CLI with the following commands:

$ sh <(curl -fsSL https://clis.ng.bluemix.net/install/osx)

$ bx api https://api.ng.bluemix.net

$ bx login

Test the configuration with bx regions command. It should show all the available Bluemix regions.

If Bluemix CLI is working as expected, configure and test the OpenWhisk CLI with the below commands:

$ bx plugin install Cloud-Functions -r Bluemix

$ bx wsk action invoke /whisk.system/utils/echo -p message hello --result

Creating the Cloudant Database Instance

Let’s go ahead and create an instance of Cloudant database that acts as the event source for the OpenWhisk functions:

$ bx cf create-service cloudantNoSQLDB Lite salesdb

We also need to create a set of credentials for OpenWhisk to talk to Cloudant. Let’s call the credentials key as myapp:

$ bx cf create-service-key salesdb myapp

Run the below command and make note of the URL with embedded username and password. We will use that to access the REST API of Cloudant:

$ bx cf service-key salesdb myapp

Let’s fire cURL to test the connectivity to the database. If it works, we will initialize an environment variable that becomes handy for rest of the operations. Please download and install JQ, the command line tool to deal with JSON documents:

$ curl <URL>

$ export CLOUDANT = “<URL>”

Let’s check the availability of databases in Cloudant:

$ curl -s -X GET $CLOUDANT/_all_dbs  | jq .

The list is empty because we haven’t created the database yet. Run the below commands to create a collection called sales:

$ curl -s -X PUT $CLOUDANT/sales

$ curl -s -H "Content-type: application/json" -d "{\"name\":\"John Doe\"}" -X POST $CLOUDANT/sales

Verify that the document is created, and then delete it. Make sure you are capturing the document id and the revision id before attempting the delete operation:

$ curl -s -X GET $CLOUDANT/sales/_all_docs   | jq .

$ curl -s -X DELETE $CLOUDANT/sales/<DOC_ID>?rev=<REV_ID> | jq .

Creating OpenWhisk Function to Send Email Notification

IBM Cloud Functions, the commercial implementation of OpenWhisk comes with pre-defined packages that are integrated with Bluemix PaaS services such as Cloudant, Weather data, Watson Translator, and more. Each package comes with a set of actions, triggers, and feeds to enable easier integration with Serverless environment.

Run the below command to see all the pre-defined packages:

$ bx wsk package list /whisk.system

This command shows the details of Cloudant-specific package:

$ bx wsk package get --summary /whisk.system/cloudant

Since we already created the instance of the Cloudant database in the previous step, we can access the package that’s specific to our database named salesdb:

$ bx wsk package refresh

$ bx wsk package list

We are all set to wire the triggers and actions associated with salesdb with our application. Let’s start by creating the trigger for the changes that occur to the database:

$ bx wsk trigger create data-inserted-trigger --feed Bluemix_salesdb_myapp/changes --param dbname sales

With the trigger in place, we can now create an action to send an email with the order details. Save the below contents to mail.js. We are using SendGrid for sending outbound emails. Refer to this tutorial for further details on using SendGrid with OpenWhisk.

function main(params) {

   return new Promise(function(resolve, reject) {

       if (!params.order || !params.manager) {

           reject("Insufficient number of parameters");

       }

       if (params.order < 10000) {

           console.log(message);

           resolve({

               order: "Low value order"
             });

           return;

       }

       var helper = require('sendgrid').mail

       var sg = require('sendgrid')("<API_KEY>");

       from_email = new helper.Email("<FROM_EMAIL>")

       to_email = new helper.Email("<TO_EMAIL>")
       subject = "High Value Order Alert"

       message = 'High value order worth $' + params.order + ' is closed by ' + params.manager;

       content = new helper.Content("text/plain", message)

       mail = new helper.Mail(from_email, subject, to_email, content)

       var request = sg.emptyRequest({

           method: 'POST',

           path: '/v3/mail/send',
body: mail.toJSON()

});



sg.API(request, function(error, response) {

if (error) {

reject(error);

           } else {

               console.log(response.statusCode)

               console.log(response.body)

               console.log(response.headers)

               resolve({

                   msg: "Message sent!"

               });

           }

       })
   });

}

exports.main = main;

Create an OpenWhisk Action based on the above function:

$ bx wsk action create high-value-order mail.js

We can quickly test the action by passing dummy parameters. Running the below command should send an email to the address mentioned in the function:

$ bx wsk action invoke --blocking --result --param order 10000 --param manager Joe high-value-order

In OpenWhisk, it is possible to chain multiple actions to create a sequence. This is similar to Unix Pipes where the output of one command is passed to the next. Since Cloudant already comes with an action to read the database, we will daisy-chain it to the high-value-order action that we created in the previous step:

$ bx wsk action create high-value-order-sequence --sequence Bluemix_salesdb_myapp/read,high-value-order

It’s time for us to wire up the function with the database trigger, which is invoked when data is inserted. We do this by creating a rule that connects the action with the Cloudant trigger:

$ bx wsk rule create log-high-value-order data-inserted-trigger high-value-order-sequence

We are almost done with the required configuration. Let’s insert data with the order value greater than 10000. This should trigger the email notification:

$ curl -s -H "Content-type: application/json" -d "{\"order\":\"50000\",\"manager\":\"John Doe\"}" -X POST $CLOUDANT/sales

Apart from waiting for the email to get delivered, you can also check the output of the invocation with the below commands. It should show the output as “Message Sent”:

$ bx wsk activation list

$ bx wsk activation result <ID>

You can easily extend this scenario to send a SMS by creating a new action based on Twilio.

Feature image via Pixabay.


A digest of the week’s most important stories & analyses.

View / Add Comments