A Cloud medley with IBM Bluemix, Cloudant DB and Node.js

Published as a tutorial in IBM Cloudant – Bluemix tutorial and demos

Here is an interesting Cloud medley based on IBM’s Bluemix PaaS platform, Cloudant DB and Node.js. This application  creates a Webserver using Node.js and uses REST APIs to perform CRUD operations on a Cloudant DB. Cloudant DB is a NoSQL Database as a service (DBaaS) that can handle a wide variety of data types like JSON, full text and geo-spatial data. The documents  are stored, indexed and distributed across a elastic datastore spanning racks, datacenters and perform replication of data across datacenters.Cloudant  allows one to work with self-describing JSON documents through  RESTful APIs making every document in the Cloudant database accessible as JSON via a URL.

This application on Bluemix uses REST APIs to perform the operations of inserting, updating, deleting and listing documents on the Cloudant DB.  The code can be forked from Devops at bluemix-cloudant. The code can also be clone from GitHub at bluemix-cloudant.

1) Once the code is forked the application can be deployed on to Bluemix using

cf login -a https://api.ng.bluemix.net
cf push bm-cloudant -p . -m 512M

2) After this is successful go to the Bluemix dashboard and add the Cloudant DB service.  The CRUD operations can be performed by invoking REST API calls using an appropriate REST client like SureUtils ot Postman in the browser of your choice.

Here are the details of the Bluemix-Cloudant application

3) Once the Cloudant DB service has been added to the Web started Node.js application we need to parse the process.env variable to obtain the URL of the Cloudant DB and the port and host to be used for the Web server.

The Node.js Webserver is started based on the port and host values obtained from process.env

require('http').createServer(function(req, res) {
//Set up the DB connection
if (process.env.VCAP_SERVICES) {
// Running on Bluemix. Parse for  the port and host that we've been assigned.
var env = JSON.parse(process.env.VCAP_SERVICES);
var host = process.env.VCAP_APP_HOST;
var port = process.env.VCAP_APP_PORT;
....
}
....
// Perform CRUD operations through REST APIs
// Insert document
if(req.method == 'POST') {
insert_records(req,res);
}
// List documents
else if(req.method == 'GET') {
list_records(req,res);
}
// Update a document
else if(req.method == 'PUT') {
update_records(req,res);
}
// Delete a document
else if(req.method == 'DELETE') {
delete_record(req,res);
}
}).listen(port, host);

2) Access to the Cloudant DB Access to Cloudant DB is obtained as follows

if (process.env.VCAP_SERVICES) {
// Running on Bluemix. Parse the port and host that we've been assigned.
var env = JSON.parse(process.env.VCAP_SERVICES);
var host = process.env.VCAP_APP_HOST;
var port = process.env.VCAP_APP_PORT;
console.log('VCAP_SERVICES: %s', process.env.VCAP_SERVICES);
// Also parse Cloudant settings.
var cloudant = env['cloudantNoSQLDB'][0]['credentials'];
}
var db = new pouchdb('books'),
remote =cloudant.url + '/books';
opts = {
continuous: true
};
// Replicate the DB to remote
console.log(remote);
db.replicate.to(remote, opts);
db.replicate.from(remote, opts);

Access to the Cloudant DB is through the cloudant.url shown above

3)  Once the access to the DB is setup we can perform CRUD operations. There are many options for the backend DB. In this application I have PouchDB.

4) Inserting a document: To insert documents into the Cloudant DB based on Pouch DB we need to do the following

var insert_records = function(req, res) {
//Parse the process.env for the port and host that we've been assigned
if (process.env.VCAP_SERVICES) {
// Running on Bluemix. Parse the port and host that we've been assigned.
var env = JSON.parse(process.env.VCAP_SERVICES);
var host = process.env.VCAP_APP_HOST;
var port = process.env.VCAP_APP_PORT;
console.log('VCAP_SERVICES: %s', process.env.VCAP_SERVICES);
// Also parse Cloudant settings.
var cloudant = env['cloudantNoSQLDB'][0]['credentials'];
}
var db = new pouchdb('books'),
remote =cloudant.url + '/books';
opts = {
continuous: true
};
// Replicate the DB to remote
console.log(remote);
db.replicate.to(remote, opts);
db.replicate.from(remote, opts);
// Put 3 documents into the DB
db.put({
author: 'John Grisham',
Title : 'The Firm'
}, 'book1', function (err, response) {
console.log(err || response);
});
...
...
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write("3 documents is inserted");
res.end();
}; // End insert_records

The nice part about Cloudant DB is that you can access your database through the URL. The steps are shown below. Once your application is running. Click on your application. You should see the screen as below.

1

Click on Cloudant as shown by the arrow.

Next click on the “Launch’ icon

2

This should bring up the Cloudant dashboard. The database will be empty.

3

If you use a REST API Client to send a POST API call then the Application will insert 3 documents.

4

The documents inserted can be seen by sending the GET REST API call.

5

The nice part of Cloudant DB is that you can use the URL to see your database. If you refresh your screen you should see the “books” database added. Clicking this database you should see the 3 documents that have been added

6

If you click “Edit doc” you should see the details of the document

7

5) Updating a document

The process to update a document in the database is shown below

// Update book3
db.get('book3', function(err, response) {
console.log(response);
return db.put({
_id: 'book3',
_rev: response._rev,
author: response.author,
Title : 'The da Vinci Code',
});
}, function(err, response) {
if (err) {
console.log("error " + err);
} else {
console.log("Success " + response);
}
});

This is performed with a PUT REST API call

8

The updated list is shown below

9

This can be further verified in the Cloudant DB dashboard for book3.

10

6) Deleting a document

The code to delete a document in PouchDB is shown below

//Deleting document book1
db.get('book1', function(err, doc) {
db.remove(doc, function(err, response) {
console.log(err || response);
});
});

The REST calls to delete a document and the result  are shown below

11

12

Checking the Cloudant dashboard we see that only book2 & book3 are present and book1 has been deleted

13

7) Displaying documents in the database

The code for displaying the list of documents is shown below

var docs = db.allDocs(function(err, response) {
val = response.total_rows;
var details = "";
j=0;
for(i=0; i < val; i++) {
db.get(response.rows[i].id, function (err,doc){
j++;
details= details + JSON.stringify(doc.Title) + " by  " +  JSON.stringify(doc.author) + "\n";
// Kludge because of Node.js asynchronous handling. To be fixed - T V Ganesh
if(j == val) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write(details);
res.end();
console.log(details);
}
}); // End db.get
} //End for
}); // End db.allDocs

If you happened to notice, I had to use a kludge to work around Node.js’ idiosyncracy of handling asynchronous calls. I was fooled by the remarkable similarity of Node.js & hence  javascript to C language that I thought functions within functions would work sequentially. However I had undergo much grief  trying to get Node.js to work sequentially. I wanted to avoid the ‘async’ module but was unsuccessful with trying to code callbacks. So the kludge! I will work this out eventually but this workaround will have to do for now!

As always you can use the “Files and Logs” in the Bluemix dashboard to get any output that are written to stdout.

Note: As always I can’t tell how useful the command
'cf  logs <application name> -- recent is for debugging.

Hope you enjoyed this Cloud Medley of Bluemix, Cloudant and Node.js!

Disclaimer: This article represents the author’s viewpoint only and doesn’t necessarily represent IBM’s positions, strategies or opinions

You may also like
1. Brewing a potion with Bluemix, PostgreSQL & Node.js in the cloud
2.  A Bluemix recipe with MongoDB and Node.js
3.  Spicing up IBM Bluemix with MongoDB and NodeExpress
4.  Rock N’ Roll with Bluemix, Cloudant & NodeExpress


Find me on Google+

Spicing up a IBM Bluemix cloud app with MongoDB and NodeExpress

In this post I highlight the rudiments for a creating a cloud application on IBM’s PaaS offering Bluemix, using MongoDB and NodeExpress.   Clearly Bluemix allows one to fire up a cloud application with a NoSQL database in a matter of  a few hours which makes it really attractive. The NodeExpress  application was initially created using Enide Studio for Node.js  with a local Mongodb server running on my desktop. (Please see my post Elements of CRUD with Node Express and MongoDB) Once you have ironed out the issues in this local application you are ready to deploy on IBM Bluemix.

The code for this Bluemix application can be forked from bluemix-mongo from IBM Devops.

You can also clone the code from GitHub at bluemix-mongo

Here are the key changes that need to be made for running the NodeExpress Webserver with MongoDB as the backend DB

1) Webserver : Setup the port and host for the Webserver.

  1. app.js

var port = (process.env.VCAP_APP_PORT || 1337);
var host = (process.env.VCAP_APP_HOST || '0.0.0.0');
var app = express();
app.configure(function(){
app.set('port', port);

As seen above the host & port for the Webserver are obtained from the process.env variable.
2) Routes and Middleware
Setup the routes and invoke them appropriately in app.js
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, userlist = require('./routes/userlist')
, newuser = require('./routes/newuser')
, adduser = require('./routes/adduser')
, changeuser = require('./routes/changeuser')
, updateuser = require('./routes/updateuser')
, remuser = require('./routes/remuser')
, deleteuser = require('./routes/deleteuser')

app.get('/users', user.list);
app.get('/helloworld', routes.index);
app.get('/userlist', userlist.list);
app.get('/newuser', newuser.list);
app.post('/adduser',adduser.list);
app.get('/changeuser', changeuser.list);
app.post('/updateuser', updateuser.list);
app.get('/remuser', remuser.list);
app.post('/deleteuser',deleteuser.list);

3) Initialize MongoDB database: Create a set of 3 records when the Webserver starts as follows

if (process.env.VCAP_SERVICES) {
var env = JSON.parse(process.env.VCAP_SERVICES);
if (env['mongodb-2.2']) {
var mongo = env['mongodb-2.2'][0]['credentials'];
}
} else {
var mongo = {
"username" : "user1",
"password" : "secret",
"url" : "mongodb://user1:secret@localhost:27017/test"
}
}
var MongoClient = mongodb.MongoClient;
var db= MongoClient.connect(mongo.url, function(err, db) {
if(err) {
log("failed to connect to the database");
} else {
log("connected to database");
}
var collection = db.collection('phonebook');
//Clear DB and insert 3 records
remove(mycallback);
var user1 = { "FirstName" : "Tinniam", "LastName" : "Ganesh","Mobile": "916732177728" };
var user2 = { "FirstName" : "Darth", "LastName" : "Vader","Mobile": "6666699999" };
var user3 = { "FirstName" : "Bill", "LastName" : "Shakespeare","Mobile": "8342189991" };

  1. insert(user1,function(err,result){});
  2. insert(user2,function(err,result){});
  3. insert(user3,function(err,result){});
  4. find().toArray(function(err, items) {

});
});

3) Home Page: Setup up a Home page with the CRUD operations when the Bluemix cloud application’s route  for e.g. http://bluemix-mongo.mybluemix.net is clicked. This is shown below.

1

 

2

4) Display Users: To display the list of users the route /userlist is invoked. This function gets all the records from the collection and stores them into a toArray element, which is then used for rendering the list of uses with a ‘userlist.jade’ template

userlist.js
var MongoClient = mongodb.MongoClient;
var db= MongoClient.connect(mongo.url, function(err, db) {
if(err) {

  1. log(“Failed to connect to the database”);

} else {

  1. log(“Connected to database”);

}
var collection = db.collection(‘phonebook’);
//Get all records and display them

  1. find().toArray(function(err, items) {
  2.    log(items);
  3. render(‘userlist’, {

“userlist” : items
});
});
});

  1. jade

This template displays the list of users as a table. The code is shown below

extends layout
block content
h1= "Display the list of Users"
p
strong Firstname Lastname   Mobile
table
each user, i in userlist
tr
td #{user.FirstName}
td #{user.LastName}
td #{user.Mobile}
p
p
a(href='/') Home

Note: A link back to the Home page is included in here at the bottom.

7

 

5) Adding a User
There are 2 parts to this
a) Invoking the /newuser route to display the input form through the newuser.jade
b) Invoking the /adduser route to insert the values entered in the form. The changes are shown below
a) app.js
..
newuser = require('./routes/newuser')
adduser = require('./routes/adduser')
..
app.get('/newuser', newuser.list);
app.post('/adduser',adduser.list);

b) newuser.js
exports.list = function(req, res){

  1. render(‘newuser’, { title: ‘Add User’});

};

The newuser jade displays the input form
c) newuser.jade
extends layout
block content
h1= "Add a User"
form#formAddUser(name="adduser",method="post",action="/adduser")
input#inputUserFirstName(type="text", placeholder="firstname", name="firstname")
input#inputUserLastName(type="text", placeholder="lastname", name="lastname")
input#inputUserLastName(type="text", placeholder="mobile", name="mobile")
button#btnSubmit(type="submit") submit
p
p
a(href='/') Home

3

d) adduser.js

The adduser.js gets the mongo url from the process.env.VCAP_SERVICES and  setups up the connection to the DB and inserts the values received in the ‘newuser.jade’ form into the database

exports.list = function(req, res) {
if (process.env.VCAP_SERVICES) {
var env = JSON.parse(process.env.VCAP_SERVICES);
if (env['mongodb-2.2']) {
var mongo = env['mongodb-2.2'][0]['credentials'];
}
} else {
var mongo = {
"username" : "user1",
"password" : "secret",
"url" : "mongodb://user1:secret@localhost:27017/test"
}
}
// Set up the DB connection
var MongoClient = mongodb.MongoClient;
var db= MongoClient.connect(mongo.url, function(err, db) {
if(err) {

  1. log(“Failed to connect to the database”);

} else {

  1. log(“Connected to database”);

}
// Get our form values. These rely on the “name” attributes
var FirstName = req.body.firstname;
var LastName = req.body.lastname;
var Mobile = req.body.mobile;
// Set our collection
var collection = db.collection(‘phonebook’);
// Insert the record into the DB

  1. insert({

“FirstName” : FirstName,
“LastName” : LastName,
“Mobile” : Mobile
}, function (err, doc) {
if (err) {
// If it failed, return error

  1. send(“There was a problem adding the information to the database.”);

}
else {
// Redirect to userlist – Display users

  1. location(“userlist”);

// And forward to success page

  1. redirect(“userlist”);

}
});
});

If the insert is successful the userlist page is displayed with the new user

4

6) Updating a User & Deleting a User: Updating and Deleting users follow the same format as Adding a user.

7) index.jade The Home page is built using index.jade with a hyperlink invoking the route for each database operation
extends layout
block content
h1= title
p Welcome to #{title}
ul
li
a(href='/userlist') Display list of users
li
a(href='/newuser') Add a user
li
a(href='/changeuser') Update a user
li
a(href='/remuser') Delete a user

Tip: “Return of the Jadei : Getting the jade template right is truly an art as Jade is extremely finicky about spaces, tabs, indents and outdents(???). Creating the Jade template had me run into circles. I found out that you can debug the jade template individually by executing

C:> npm install jade -g"
and then  running
C:> jade <template name>

from the command prompt. If the result of the command is “rendered <template name>.html” then you are in luck and you can incorporate this jade template into your views folder for e.g.

C: >jade index.jade
rendered index.html

8) Push changes to Bluemix: Once the changes have been made push the changes on to Bluemix with ‘cf’ as follows

cf login -a https://api.ng.bluemix.net
cf push bluemix-mongo -p . -m 512M
cf create-service mongodb 100 mongodb01
cf bind-service bluemix-mongo mongodb01

 

The last 2 commands can also be performed through the Bluemix dashboard in which you add the mongodb service to your Node.js app/

8) Files and Logs: In the Bluemix dashboard you can check your logs in the Files and Logs

5

 

6

Important tip: Finally if the application fails to start when you  push the application with ‘cf’ for e.g.

cf push <app name> -p . -m 512M
....
.....
----> Writing a custom .npmrc to circumvent npm bugs
----> Installing dependencies
----> Caching node_modules directory for future builds
----> Cleaning up node-gyp and npm artifacts
----> No Procfile found; Adding npm start to new Procfile
----> Building runtime environment
----> Checking and configuring service extensions
----> Uploading droplet (7.6M)
of 1 instances running, 1 down
of 1 instances running, 1 down
of 1 instances running, 1 down
of 1 instances running, 1 down

or if  it crashes when you click a link then your debugging friend is

cf logs <app name > — recent
This will dump the error that was encountered either while the application was being started of why the application crashed.

You can fork this Bluemix application from bluemix-mongo at  IBM Devops or from GitHub at bluemix-mongo

Disclaimer: This article represents the author’s viewpoint only and doesn’t necessarily represent IBM’s positions, strategies or opinions

You may also like
1. Brewing a potion with Bluemix, PostgreSQL & Node.js in the cloud
2. A Bluemix recipe with MongoDB and Node.js
3. A Cloud Medley with IBM’s Bluemix, Cloudant and Node.js
4. Rock N’ Roll with Bluemix, Cloudant & NodeExpress


Find me on Google+

A Bluemix recipe with MongoDB and Node.js

Here is a tasty IBM Bluemix recipe with a dash of MongoDB and a pinch of Node.js. This posts shows the steps needed to perform basic CRUD (Create, Remove, Update & Delete) operations on the MongoDB database using REST APIs of PUT,GET, UPDATE & DELETE.

You can fork the code for the below app from Devops at mymongodb

The code can also be cloned from GitHub at mymongodb

For this,  the first  thing we need to do is to create a Webserver using Node.js as shown below

Webserver

require('http').createServer(function(req, res) {
if ( typeof mongodb !== 'undefined' && mongodb ) {
// Perform CRUD operations through REST APIs
if(req.method == 'POST') {
insert_records(req,res);
}
else if(req.method == 'GET') {
list_records(req,res);
}
else if(req.method == 'PUT') {
update_records(req,res);
}
else if(req.method == 'DELETE') {
delete_record(req,res);
}
} else {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write("No MongoDB service instance is bound.\n");
res.end();
}
}).listen(port, host);

The Webserver users the port and host values obtained as shown above to wait for  HTTP requests.

The REST API calls are handled by individual  Node.js functions to perform the operations of insert, update, delete and select.

Insertions

The code for insertions is shown below. For this a set of 5 documents are created and then inserted using Node.js

var insert_records = function(req, res) {
var MongoClient = require('mongodb').MongoClient;
// Connect to the db
MongoClient.connect (mongo.url, function(err, db) {
//Create a collection test
var collection = db.collection('books', function(err, collection) {
//Create a set of documents to insert
var book1 = { book: "The Firm", author: "John Grisham", qty: 3 };
var book2 = { book: "Foundation", author: "Isaac Asimov", qty: 5 };
collection.remove(mycallback);
//Insert the books
console.log("Insert the books");
collection.insert(book1,function(err,result){});
collection.insert(book2, {w:1}, function(err, result) {
});
collection.insert(book5, {w:1}, function(err, result) {});
console.log('Inserted 5 books');
}); //var collection
}); // End MongoClient.connect
}; // End insert_records

Updating documents in Mongodb

For update 2 documents are changed as shown below

var update_records = function(req, res) {
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect (mongo.url, function(err, db) {
// Update
var collection = db.collection('books', function(err, collection) {
collection.update({book:"Fountainhead"},{$set:{qty:2}}, {w:1},function(err,result) {});
collection.update({book:"Animal Farm"},{$set:{author:"George Orwell"}}, {w:1},function(err,result) {});
console.log("Updated 2 books");

}); // var collection
}); //End MongoClient.connect

}; //End update-records

Deletions

The delete functions requires a callback method which is included

var delete_record = function(req, res) {
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect (mongo.url, function(err, db) {

//Deleting documents
var collection = db.collection(‘books’, function(err, collection) {

collection.remove({book:”Foundation”},mycallback);
collection.remove({book:”The Da Vinci Code”},{w:1},mycallback);
console.log(‘Deleted 2 books’);

});
}); //End MongoClient.connect
}; //End delete-records

Retrieving documents

To retrieve documents the collection.find.stream() method is used as below

var list_records = function(req, res) {
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect (mongo.url, function(err, db) {
//Retrieve documents
var collection = db.collection('books', function(err, collection) {
var stream = collection.find().stream();
console.log("Printing values...");
res.writeHead(200, {'Content-Type': 'text/plain'});
stream.on('error', function (err) {
console.error(err.stack)
});

stream.on(“data”, function(item) {
console.log(item);
res.write(JSON.stringify(item) + “\n”);
});

stream.on(“end”, function() {
console.log(“End”);
res.end();
});
}); //var collection
}); //End MongoClient.connect

The connection between the Node.js & Webserver and the MongoDB is setup using the VCAP_SERVICES as follows

if (process.env.VCAP_SERVICES) {
var env = JSON.parse(process.env.VCAP_SERVICES);
if (env['mongodb-2.2']) {
var mongo = env['mongodb-2.2'][0]['credentials'];
}
} else {
var mongo = {
"username" : "user1",
"password" : "secret",
"url" : "mongodb://user1:secret@localhost:27017/test"
}
}

To get started you can fork the code for the above Bluemix- MongoDB app from Devops from mymongodb

The code can also be cloned from GitHub at mymongodb

After you have forked the code you can clone the code into a local directory on your machine.

Now use the ‘cf’ command to push the code onto IBM Bluemix as shown. In my case I named the app as mymongodb01

cf login -a https://api.ng.bluemix.net
cf push mymongodb01 -p . -m 512M
cf create-service mongodb 100 mongodb
cf bind-service mymongodb01 mongodb

Instead of the last 2 steps you can also use the Add-service in Bluemix dashboard to add the MongoDB service. (Note: You will have to check Experimental at the top and you will see the service under Data Management.) After the MongoDB service is added check if your app is running in the Bluemix dashboard

If the app is running you can check the CRUD operations on MongoDB using the SureUtils-REST API client extension to Chrome.

The CRUD operations performed are shown below

1.POST + GET

Here 5 documents are inserted in the MongoDB and then displayed subsequently

1

2

2.UPDATE + GET

Here 2 records are updated – The quantity of the book ‘Fountainhead’ is set to 2 and the author of ‘Animal Farm’ is set to George Orwell

3

4

3.DELETE + GET

In this set 2 book are deleted and the result is displayed

5

6

If all things went well you should be able to see the app running.

7

You can also get the output o the console.login Files and Logs in the Bluemix dashboard.

8

Important tip:  While executing the Buemix app if you run into problems and you app crashes with the “Health decreased” for your app and its colour turning red you can use the recent history of ‘cf” command to debug your problem

PS C:\Users\IBM_ADMIN\git\mymongodb> cf logs mymongodb01 –recent

Connected, dumping recent logs for app mymongodb01 in org tvganesh.85@gmail.com / space dev as tvganesh.85@gmail.com…

…….

…….

2014-07-27T11:34:26.45+0530 [App/0]   OUT We are connected to DB
2014-07-27T11:34:26.46+0530 [App/0]   OUT Updated 2 books
2014-07-27T11:34:31.17+0530 [App/0]   OUT We are connected to DB
2014-07-27T11:34:31.17+0530 [App/0]   OUT Updated 2 books
2014-07-27T11:34:31.18+0530 [RTR]     OUT mymongodb01.mybluemix.net - [27/07/2014:06:04:31 +0000] "PUT / HTTP/1.1" 200 1
7 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36" 75
.126.70.43:19986 vcap_request_id:4fa831610b6e79455d0257581a51014e response_time:0.009122768 app_id:ed49744f-1a29-4e3f-9e
1c-8b45e85c3310
2014-07-27T11:35:02.75+0530 [App/0]   ERR
2014-07-27T11:35:02.75+0530 [App/0]   ERR /home/vcap/app/app.js:95
2014-07-27T11:35:02.75+0530 [App/0]   ERR       MongoClient.connect (mongo.url, function(err, db)   {
2014-07-27T11:35:02.75+0530 [App/0]   ERR       ^
2014-07-27T11:35:02.75+0530 [App/0]   ERR ReferenceError: MongoClient is not defined
2014-07-27T11:35:02.75+0530 [App/0]   ERR     at delete_record (/home/vcap/app/app.js:95:2)
2014-07-27T11:35:02.75+0530 [App/0]   ERR     at Server.<anonymous> (/home/vcap/app/app.js:165:12)
2014-07-27T11:35:02.75+0530 [App/0]   ERR     at Server.emit (events.js:98:17)
2014-07-27T11:35:02.75+0530 [App/0]   ERR     at HTTPParser.parser.onIncoming (http.js:2108:12)
2014-07-27T11:35:02.75+0530 [App/0]   ERR     at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:121:
23)
2014-07-27T11:35:02.75+0530 [App/0]   ERR     at Socket.socket.ondata (http.js:1966:22)
2014-07-27T11:35:02.75+0530 [App/0]   ERR     at TCP.onread (net.js:527:27)
2014-07-27T11:35:02.80+0530 [RTR]     OUT mymongodb01.mybluemix.net - [27/07/2014:06:05:02 +0000] "DELETE / HTTP/1.1" Mi
ssingResponseStatusCode 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.19

 

Happy cooking with Bluemix, MongoDB & Node.js!

Disclaimer: This article represents the author’s viewpoint only and doesn’t necessarily represent IBM’s positions, strategies or opinions

See also
1. Brewing a potion with Bluemix, PostgreSQL & Node.js in the cloud
2. Spicing up IBM Bluemix with MongoDB and NodeExpress
3. A Cloud Medley with IBM’s Bluemix, Cloudant and Node.js
4. Rock N’ Roll with Bluemix, Cloudant & NodeExpress


Find me on Google+

Brewing a potion with Bluemix, PostgreSQL, Node.js in the cloud

Here is a heady potion made with the key ingredients of IBM’s Bluemix, PostgreSQL & Node.js. In this post I instantiate an app ‘mypgdb01’ on IBM’s Bluemix which uses the services of PostgreSQL in the cloud. This is shown in the picture below.

8

The mypgdb01 is a Webserver running on Node.js in Bluemix and uses the services of PostgreSQL DB. The app mypgdb01 performs basic CRUD (Create, Remove, Update & Delete) on the PostgreSQL.

The code for this can be forked from Devops  from my link mypgdb

The code can also be cloned from GitHub at mypgdb

1) This app uses the Node.js Webstarter kit and the PostgreSQL service.  The Node.js Webserver is created by parsing the VCAP services variable as usual

if (process.env.VCAP_SERVICES) {
var env = JSON.parse(process.env.VCAP_SERVICES);
var credentials = env['postgresql-9.1'][0]['credentials'];
} else {
var credentials = {"uri":"postgre://user:secret1@localhost:5433/db"}
}
var port = (process.env.VCAP_APP_PORT || 1337);
var host = (process.env.VCAP_APP_HOST || '0.0.0.0');
http.createServer(function(req, res) {
console.log("Inside Webserver");
....
....
}).listen(port, host);

The details of VCAP_SERVICES can be see by clicking Runtime for you application and is shown below

9

Note: From above it can be seen that the PostgreSQL DB’s host & port is

"host": "192.155.243.14",
"hostname": "192.155.243.14",
"port": 5433

This different from the host & port of the Node.js Webserver which  can be see in Logs & Files tab (included below) and is

Webserver: host: 0.0.0.0
port:62733

2) Once the Webserver is started the server waits for REST calls of GET,PUT, UPDATE & DELETE as shown below.

// Perform CRUD operations through REST APIs
if(req.method == 'POST') {
insert_records(req,res);
}
else if(req.method == 'GET') {
list_records(req,res);
}
else if(req.method == 'PUT') {
update_record(req,res);
}
else if(req.method == 'DELETE') {
delete_record(req,res);
}

3)  The REST API call  are implements as follows

a) POST:

var insert_records = function(req, res) {
// Connect to DB
var client = new pg.Client(credentials.uri);
client.connect(function(err) {
if (err) {
res.end("Could not connect to postgre: " + err);
}

//Drop table if it exists
client.query("DROP TABLE IF EXISTS emps");
// Creat table and insert 2 records into it
client.query("CREATE TABLE IF NOT EXISTS emps(firstname varchar(64), lastname varchar(64))");
client.query("INSERT INTO emps(firstname, lastname) values($1, $2)", ['Tinniam', 'Ganesh']);
client.query("INSERT INTO emps(firstname, lastname) values($1, $2)", ['Anand', 'Karthik']);

b) GET:

// Select all rows in the table<
var query = client.query("SELECT firstname, lastname FROM emps ORDER BY lastname, firstname");
query.on("row", function (row, result) {
result.addRow(row);
});
query.on("end", function (result) {
// On end JSONify and write the results to console and to HTML output
console.log(JSON.stringify(result.rows, null, "    "));
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write(JSON.stringify(result.rows) + "\n");
res.end();
});

c) UPDATE:

query = client.query("UPDATE emps set firstname = 'Kumar' WHERE firstname='Anand' AND lastname='Karthik'");
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write("Updated record  - Set record with firstname Anand to Kumar\n");

d)DELETE

// Delete the record where the lastname is Karthik
client.query("DELETE FROM  emps WHERE lastname = 'Karthik'");
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write("Deleted record where lastname was Karthik\n");

4) Once the changes are made you can  push the changes to Bluemix using ‘cf’ commands.

The commands are

cf login -a https://api.ng.bluemix.net
cf push mypgdb01-p . -m 512M
cf create-service postgresql 100 pgdb01
cf bind-service mypgdb01 pgdb01

5) In the Bluemix dashboard the app ‘mypgdb01’ should be up and running.

6) To invoke the different database operations we need to make REST API calls to the app.

7) To make the REST API calls you can install Sure Utils -> REST API Chrome extension.  I installed the SureUtils-.REST API Client. This is a Chrome extension and can be installed from Chrome Web Store (search for REST API client). You could choose any REST API client of your choice for the browser you intend to use (Chrome, Firefox)

8) Now we can test the Nodejs-PostgreSQL app with the Sure Utils – Chrome extension

8) The following REST API calls can be made to test the PostgreSQL operations on the database

POST- insert

1

GET – select

2

UPDATE + GET – update + select

The PUT API updates Anand Karthik to Kumar Karthik. This is shown in the GET API call

3

4

.DELETE + GET – delete  + select

5

6

 

Here the DELETE API call deletes the Kumar Karthik record. The GET API call now displays only 1 record.

The console.log output in Bluemix can be see in Files and logs -> stdout.log as shown below

7

The above post shows some basic operations done on a cloud based application that is composed of a Webserver with a PostgreSQL as a backend. The code can be enhanced by adding  front end using Node express.

As mentioned above the code for this can be forked from Devops at mypgdb. The code can also be cloned from GitHub at mypgdb

Disclaimer: This article represents the author’s viewpoint only and doesn’t necessarily represent IBM’s positions, strategies or opinions

You may also like
1. A Bluemix recipe with MongoDB and Node.js
2. Spicing up IBM Bluemix with MongoDB and NodeExpress
3. A Cloud Medley with IBM’s Bluemix, Cloudant and Node.js
4. Rock N’ Roll with Bluemix, Cloudant & NodeExpress


Find me on Google+

Getting started with Node.js and Mongodb

Here is a post in which I try to get my arms around Node.js & MongoDB. This is first encounter with Web programming. There is a veritable universe of frameworks, languages, libraries and modules out there.

There are a gazillion blogs already on this topic so here is one more. When I came across Node.js recently,  I have been  impressed mightily with its ability to quickly cook up Webservers, TCP based server side programming and the like with really brief code. Another alluring fact was that it is based on Javascript which itself smacks of plain C, added to its charm. The experience with Node.js is difficult for a beginner. Also I must add that the Node.js’es callback functions takes a bit of getting used and I have had my share of pain with it.

MongoDB is an open-source document database, and one of the  leading NoSQL databases out there.

First things first – Install Node.js from Nodejs.org. Next install MongoDB for your OS and machine type. You will also need to install the mongodb module for use with Node.js. You can this by opening a command prompt and typing

npm install mongodb -g

This will allow you to access the mongodb module for use within your program. Now you should be good to go and create some basic code to manipulate MongoDB through Node.js.  This code is based on the commands from the following MongoDB wiki

Here are the steps for a basic CRUD (Create,Remove,Update & Delete) operations on MongoDB with Node.js

1. Create a folder c:\node\mongotest

2. Go to the directory where you have extracted the mongodb files and type in

mongod –dbpath c:\node\mongotest

This  will  start the database.

3. Here are the main functions of the code.

Connect to the mongodb database

var MongoClient = require('mongodb').MongoClient;
// Connect to the db
MongoClient.connect(“mongodb://localhost:27017/exampleDb”, function(err, db) {
if(!err) {
console.log(“We are connected”);
}

4. Create a collection of documents

//Create a collection test
console.log(“Creating a collection test”);
var collection = db.collection(‘test’);

5. Insert documents into the collection

//Create documents to insert
var doc1 = {‘hello’:’doc1′};
var doc2 = {‘hello’:’doc2′};
var lotsOfDocs = [{‘hello’:’doc3′}, {‘hello’:’doc4′}];
//Insert the docs
console.log(“Inserting the docs”);
collection.insert(doc1,function(err,result){});
collection.insert(doc2, {w:1}, function(err, result) {});

6. Update the inserted documents as follows

//Updating
var doc3 = {key:1,value:1};
collection.insert(doc3,{w:1},function(err,result) {
if(err) {
console.log(‘Could not insert’);
}
collection.update({key:1},{$set:{value:2}},{w:1},function(err,result) {});
});

7. Delete specific  documents from the database. Note: The remove() command requires a callback which I have included separately instead of the standard anonymous callback style

var mycallback = function(err,results) {
console.log(“mycallback”);
if(err) throw err;
}
//Deleting documents
console.log(“The delete operation”);
var doc4=[{key1:1},{key2:2},{key3:3}];
//Insert the document and then remove
collection.insert(doc4,{w:1},function(err,result) {
collection.remove({key1:1},mycallback);
collection.remove({key4:4},{w:1},mycallback);
});

8. Finally retrieve the inserted/updated records from the database

var stream = collection.find({mykey:{$ne:2}}).stream();
console.log(“Printing values…”);
stream.on(“data”, function(item) {
console.log(item);
});
stream.on(“end”, function() {});

The stream.on(“data”,) retrieves all the data till it encounters a stream.on(“end”).

So if I execute the above code I get the following output

C:\test \mongotest>node app3.js
We are connected
Creating a collection test
Inserting the docs
The delete operation
Printing values…
{ _id: 53c27ecbd5f4c59c1a2a5d39, hello: ‘doc1’ }
{ _id: 53c27ecbd5f4c59c1a2a5d3a, hello: ‘doc2’ }
{ _id: 53c27ecbd5f4c59c1a2a5d3b, key: 1, value: 1 }
{ _id: 53c27ecbd5f4c59c1a2a5d3c, key1: 1 }
{ _id: 53c27ecbd5f4c59c1a2a5d3d, key2: 2 }
{ _id: 53c27ecbd5f4c59c1a2a5d3e, key3: 3 }
mycallback
mycallback

The code can be cloned from Github at node-mongo

Also see
1. A Bluemix recipe with MongoDB and Node.js
2. Spicing up IBM Bluemix with MongoDB and NodeExpress
3. A Cloud Medley with IBM’s Bluemix, Cloudant and Node.js
4. Rock N’ Roll with Bluemix, Cloudant & NodeExpress


Find me on Google+