Web App with Node.js, Express and Aerospike

Let’s get you to write your first “Hello World” like web app using Node.js, Express and Aerospike, shall we? I promise it will only take n minutes of your time. Before we get started though, here’s an overview of what you will build in the next few minutes. A web app that will:

  1. Connect to the Aerospike database
  2. Allow you to enter name on a web page
  3. Store the name you entered into the Aerospike database
  4. Read the name back and display it on the web page like so “Hello Dash!”

In the coming sections we’ll look at the code snippets but you may also download the source from GitHub

Prerequisite: Node.js — if you don’t have it installed, get it done and come back here.

Step 1: Install Aerospike Database

Step 2: Application Setup

  • Create a new folder (e.g. node-express-aerospike-app) for this new little application you’re going to write.

  • Create a new file named package.json and add the following code. Make sure you save this file in the application folder.

    {
    "name": "aerospike-node-express-seed-app",
    "version": "0.0.0-1",
    "dependencies": {
    "express": "~4.0.0",
    "aerospike": "^1.0.7"
    }
    }
    

    What’s going on here? Well, this code suggests that the application will depend on two external libraries: Express and Aerospike Node.js Client.

  • Resolve dependencies — open terminal window, browse to the application folder and type ‘npm install.‘ Assuming there are no errors (fingers crossed!) you’re now all set and can move on to the next step! Note: The dependencies will be installed in a new folder called ‘node_modules.’

Step 3: Let’s Code… Awesome!

  • Config Module – create a new file named ‘aerospike_config.js‘ and add the following code. Make sure you save this file in the application folder.

    'use strict';
    var aerospikeClusterIP  = '127.0.0.1';
    var aerospikeClusterPort = 3000;
    exports.aerospikeConfig = function()    {
    return  {
    hosts: [ { addr: aerospikeClusterIP, port: aerospikeClusterPort } ]
    };
    };
    exports.aerospikeDBParams = function()  {
    return {
    defaultNamespace: 'test',
    defaultSet: 'test'
    };  
    };
    
  • Update aerospikeClusterIP and aerospikeClusterPort variables such that they point to your instance of the Aerospike Server.

    What’s going on here? Well, this module exports two functions: aerospikeConfig() encapsulates and exposes Aerospike Cluster IP and Port settings and aerospikeDBParams() contains attributes such as namespaces and sets. These will be used by the API module illustrated below.

  • API Module — create a new file named ‘api.js‘ and add the following code. Make sure you save this file in the application folder.

    'use strict';
    var aerospike = require('aerospike');
    var asConfig = require('./aerospike_config');
    var aerospikeConfig = asConfig.aerospikeConfig();
    var aerospikeDBParams = asConfig.aerospikeDBParams();
    var client = aerospike.client(aerospikeConfig);
    // Establish connection to the cluster
    exports.connect = function(callback) {
    client.connect(function(response) {
    return callback(response.code);
    });
    };
    // Write a record
    exports.writeRecord = function(k, v, callback) {
    var key = aerospike.key(aerospikeDBParams.defaultNamespace,aerospikeDBParams.defaultSet,k);
    client.put(key, {greet:v}, function(err, rec, meta) {
    // Check for errors
    if ( err.code === aerospike.status.AEROSPIKE_OK ) {
        return callback({status:0,message:'ok'});
    } else {
        // An error occurred
        return callback({status:-1,message:err});
    }
    });
    };
    // Read a record
    exports.readRecord = function(k, callback) {
    var key = aerospike.key(aerospikeDBParams.defaultNamespace,aerospikeDBParams.defaultSet,k);
    client.get(key, function(err, rec, meta) {
    // Check for errors
    if ( err.code === aerospike.status.AEROSPIKE_OK ) {
        return callback({status:0,message:k + ' ' + rec.greet});
    }
    else {
        // An error occurred
        return callback({status:-1,message:'Record not found!'});
    }
    });
    };
    

    What’s going on here? Well, this module exports three functions: connect() encapsulates code related to connecting to the Aerospike Server. It accepts a callback function which is invoked along with connection status code, writeRecord() contains code for writing a record to the database. It accepts key, value and callback function as arguments and readRecord() contains code for reading a record. It accepts key and callback function as arguments.

  • App Module — create a new file named ‘app.js‘ and add the following code. Make sure you save this file in the application folder.

    'use strict';
    var express = require('express'); 
    var http = require('http');
    var api = require('./api');
    var app = express();
    var dbStatusCode = null;
    api.connect(function(response) {    
    dbStatusCode = response;
    if ( dbStatusCode === 0) {
    // handle success
    console.log("Connection to Aerospike cluster succeeded!");
    }
    else {
    // handle failure
    console.log("Connection to Aerospike cluster failed!");
    }
    });
    // setup default/home route
    app.get('/', function(req,res) {
    res.send("HTML FORM GOES HERE... SEE BELOW");
    });
    // setup write route
    app.get('/write', function(req,res) {
    if (dbStatusCode === 0) {    
    api.writeRecord('Hello',req.query.name, function(response) {
        if ( response.status === 0) {
            // handle success
            api.readRecord('Hello', function(response) {
                if ( response.status === 0) {
                    // handle success
                }
                else {
                    // handle failure
                }
                res.send(response.message);
            }); 
        }
        else {
            // handle failure
            res.send(response.message);
        }
    }); 
    } else  {
    res.send("Connection to Aerospike cluster failed!");
    }
    });
    var server = http.Server(app);
    // Start server
    server.listen('9000', 'localhost', function () {
    console.log('App is running on http://localhost:9000. Press Ctrl-C to exit...');
    });
    
  • In the code above, replace  “HTML FORM GOES HERE… SEE BELOW” with this code snippet

<div><form action='/write'><label>Enter your name:</label><input type='text' name='name'/><input type='submit'></input></form></div>

What’s going on here? Well, this module establishes connection to the Aerospike Server using api.connect() It then sets up default/home route which displays the web form for entering a name. The action executed when submitting the form is mapped to /write route which is setup to invoke api.writeRecord() passing it ‘Hello’ as key and the name entered as value. Upon successful write operation, the record is read back using api.readRecord() and displayed on the web page.

Step 4: Let’s Run The Application

  • Open terminal window, browse to the application folder and run ‘node app‘ — you should see the following:

Connection to Aerospike cluster succeeded! App is running on http://localhost:9000. Press Ctrl-C to exit...

Note: If you see “Connection to Aerospike cluster failed!”, make sure the Aerospike Server is running and also confirm aerospikeClusterIP and aerospikeClusterPort are set correctly in ‘aerospike_config.js’.

  • Open browser window – then browse to http://localhost:9000. You should see a simple web page with a form to enter your name.

  • Type your name and click on Submit.

  • You should see “Hello [name]” on the web page!

Done and Done!

Leave a Reply