Thursday, April 16, 2015

Sample code for Nodejs + Mysql REST service on IBM Bluemix

Carry on from my previous post. 

The following code provides a sample or a template for writing your own REST services which uses Nodejs to save data in MqSql database. It uses data connection pooling provided by mysql package.

Basically, this code is meant to be deployed on IBM Bluemix PaaS environment. For local execution, you would not need "cfenv" package. Instead, just run it with "express" server. The same code would work on any PaaS platform that uses Cloud Foundry underneath.

==============START OF CODE============

// This application uses express as it's web server
// for more info, see: http://expressjs.com

var express = require('express');
var http = require('http');
var mysql= require('mysql');

var pool      =    mysql.createPool({
    connectionLimit : 100, //important
    host     : 'hostname_OR_IP',
    user     : 'dbuser',
    password : 'dbuser_password',
    database : 'dbname',
    debug    :  false
});

// cfenv provides access to your Cloud Foundry environment
// for more info, see: https://www.npmjs.com/package/cfenv

var cfenv = require('cfenv');

// create a new express server
var app = express();

// serve the files out of ./public as our main files
app.use(express.static(__dirname + '/public'));


//Service method that searches for any user with firstname
app.get('/customers/:firstname', function (req, res) {
    var queryStr = "SELECT * FROM AD_CUSTOMER WHERE FNAME = '"+req.params.firstname+"'";
    console.log(queryStr);
  
    pool.getConnection(function(err,connection){
        if (err) {
          connection.release();
          res.json({"code" : 100, "status" : "Error in connection database"});
          return;
        } 

        console.log('connected as id ' + connection.threadId);
      
        connection.query(queryStr,function(err,rows){
            connection.release();
            if(!err) {
                res.json(rows);
            }         
        });

        connection.on('error', function(err) {     
              res.json({"code" : 100, "status" : "Error in connection database"});
              return;   
        });
  });
});


// get the app environment from Cloud Foundry
var appEnv = cfenv.getAppEnv();

// start server on the specified port and binding host
app.listen(appEnv.port, appEnv.bind, function() {
 

// print a message when the server starts listening
console.log("server starting on " + appEnv.url);
});



==============END OF CODE============

Once deployed, this web service can be invoked with following endpoint URL:


http://<mybluemixURL>/customers/John

NOTE: In my blog, I will try to add a separate post on how to deploy these kind of Nodejs apps on Bluemix. That's altogether a different topic.



Tuesday, April 14, 2015

Sample code for Nodejs + Mongodb REST service

Hi,

In a recent assignment, I was supposed to create a PoC of how Nodejs would work with Mongodb to offer RESTful web services. I was very new to Javascript programming as well as Nodejs platform. Then I started reading about Nodejs and went through couple of tutorials and a ebook to understand what it stands for.

Here are few things I noticed and remember after completing my PoC.

1.)    It’s built using Chrome’s Javascript runtime

2.)    It’s lightweight and efficient because of it’s event driven and non-blocking I/O architecture

3.)    Best for data intensive realtime applications like web services, analytics, dashboard service etc.

Benefits and possible usage:

1.)    Great Performance – it’s all javascript running with chrome’s javascript engine.

2.)    Fast development – You don’t need a lot of software setup the way you need for Java or Microsoft projects.

3.)    Huge flexibility to do both high level and low level functionality.

4.)    It is natural choice for developing a backend system which needs to be scaled faster and still maintain it’s performance.

5.)    Good choice to create various collaborative components like chat room or message boards.

6.)    You can achieve both scalability and performance on commodity servers. You don’t need high end servers in order to achieve these features for your apps.

7.)    A good choice for developing web services with Mongodb, because both of them understand JSON like their first language.

8.)    For any web portal using extensive Javascript (be it Angular or ExtJS or any other form), Nodejs can be very natural and obvious choice since using Javascript on both sides would give you better performance & flexibility.

9.)    Nodejs community publishes various kinds of packages (like express and others), which can be plugged into your development and reused like never before. Since it’s plain javascript, more and more packages are coming out faster & often. This, in turn supports faster development as well as it support community development.

10.) More and more Mobile apps and sites are being developed using various Javascript libraries like JQuery and AngularJS instead of Notive code. Hence, Nodejs becomes obvious choice for all such mobile app projects for their backend services.

11.) In a recent trend, Nodejs is increasingly being used to create backend components to analyze log files, convert images/videos and sending out communications like emails and SMSs (also push notifications).

Then the code that I first developed for my PoC. A RESTful service with Nodejs and Mongodb.

This Nodejs web service is deployed on IBM Bluemix PaaS (Platform as a Service).

//following content go into app.js file

// This application uses express as it's web server
// for more info, see: http://expressjs.com
var express = require('express');
var http = require('http');
//var express = require('express');
var mongo = require('mongodb');
var MongoClient = mongo.MongoClient;
var connectionString = 'mongodb://<username>:<password>@<mongodb-host-name>:<mongodb-port>/dbname';

// cfenv provides access to your Cloud Foundry environment
// for more info, see: https://www.npmjs.com/package/cfenv
var cfenv = require('cfenv');

// create a new express server
var app = express();

// serve the files out of ./public as our main files
app.use(express.static(__dirname + '/public'));

app.get('/test', function (req, res) {
  res.send('Hello World');
});

app.get('/users/:username', function (req, res) {
  MongoClient.connect(connectionString, function (err, db) {
  if (err) throw err;
  if (!err) {
    console.log("Connected to database");
    var collection = db.collection('users');
    var uname = req.params.username;

    //retrive user
    collection.find({"username": uname}).toArray(function (err, result) {
      if (err) {
        console.log(err);
        res.send(err);
      } else if (result.length) {
        console.log('Found:', result);
        res.send(result);
      } else {
        console.log('No document(s) found with defined "find" criteria!');
        res.send('No document(s) found with defined "find" criteria!');
      }
      //Close connection
      db.close();
    });
  }
})
});

//This one updates password or creates new username in DB
app.post('/users/:username/:password', function (req, res) {
  MongoClient.connect(connectionString, function (err, db) {
  if (err) throw err;
  if (!err) {
    console.log("Connected to database");
    var collection = db.collection('users');
    var uname = req.params.username;
    var pwd = req.params.password;
   
    //create JSON for insert
    var user = {"username": uname, "password": pwd};
   
    //First try to update
    collection.update({"username": uname}, {$set: {"password": pwd}}, function (err, numUpdated) {
      if (err) {
        console.log(err);
        res.send(err);
      } else if (numUpdated) {
        console.log('Updated Successfully %d document(s).', numUpdated);
        res.send('Updated Successfully - ' + numUpdated.nModified + ' document(s).');
      } else {
        console.log('No document found with defined "find" criteria!');
            // Insert one user because its not found
            collection.insertOne(user, function (err, result) {
              if (err) {
                console.log(err);
                res.send(err);
              } else {
                console.log('Inserted document! Thanks!');
                res.send('Inserted document! Thanks!' + result);
              }
            }
            );
      }
      //Close connection
      console.log('Now we are closing the db connection...');
      db.close();
    }
    );
  }
})
});

// get the app environment from Cloud Foundry
var appEnv = cfenv.getAppEnv();

// start server on the specified port and binding host
app.listen(appEnv.port, appEnv.bind, function() {

    // print a message when the server starts listening
  console.log("server starting on " + appEnv.url);
});

Friday, April 10, 2015

Text:CHARACTER:[Microsoft][ODBC Driver Manager] The specified DSN contains an architecture mismatch between the Driver and Application

Last week, while trying to connect my WebSphere Message Broker code (from Compute Node) with a DB2 database on IBM cloud, I encountered following error, which caused my flow to fail.

Text:CHARACTER:[Microsoft][ODBC Driver Manager] The specified DSN contains an architecture mismatch between the Driver and Application

Searching around the web, I could understand that this error is because my ODBC connection is 64-bit and my WMB is setup with 32-bit architecture.

The Solution:

In order to get rid of this issue, both ODBC DSN as well as the Application using this DSN (in my case the WMB) should use same architecture (either 32 or 64 bit).

So, I decided to use 32-bit ODBC manager instead of 64-bit. You can do this, by running following exe file in windows 7.

c:\windows\system32\odbcad32.exe

When you run this exe, it opens the 32-bit ODBC Manager. Create your DSN here.

In my case, the WebSphere Message Broker flow started working when I created the DSN using 32-bit ODBC Manager.

Hope this helps!!

Tuesday, November 11, 2014

Find current directory in standalone Java Program

Sometimes, we have to load a properties file in a Java Program and specially when you have to export a Jar file out of the Java Project, this becomes little difficult. The reason is, depending upon how you run your Java Application, the default directory changes. For an example, if you run it from command-line, it looks under current directory from where you are running the app. But in eclipse, its looks under Project folder (where .classpath file resides). In order to find default directory in Java Program, we can execute following line of code:

                   System.getProperty("user-dir");

This will give you default directory under your current runtime environment.


Friday, November 7, 2014

Eclipse doesn't start with error - java was started but returned exit code=13

Once you install 64-bit JDK (usually in order to upgrade to latest JDK), you may face this issue that your eclipse doesn't start and it shows error screen with following line at the top:

java was started but returned exit code=13


This is because your latest JDK is 64-bin version and Eclipse would need 32-bit JDK. If you haven't uninstalled previous version of JDK which worked for your eclipse, all you have to do is - open the eclipse.ini file and enter following two lines:

-vm
C:/Program Files/Java/jdk1.6.0_43/bin


 
Once you do this, your eclipse will start just normally like it used to be :-)

Enjoy.


Wednesday, November 5, 2014

Convert JSON String into Java Object using Jackson APIs

Guys,

In one of my tasks, today I converted a JSON response (in form of a string) coming from REST service into a Java object so that I can then execute rest of my logic on that data.

It turned out to be really simple with JACKSON APIs. Here are two lines of code that you need to write:


       ObjectMapper mapper = new ObjectMapper();
       obj =  mapper.readValue(resp, DTestConnection.class);



Here is how the JSON looked like:


     {
        "success": true,
        "connected": true
     }


And here is how my Java class looked like:


public class DTestConnection {
    String success;
    String connected;
   
   
    public String getSuccess() {
        return success;
    }
    public void setSuccess(String success) {
        this.success = success;
    }
    public String getConnected() {
        return connected;
    }
    public void setConnected(String connected) {
        this.connected = connected;
    }

}


 

Friday, October 31, 2014

Enable J2EE project or Java Web Project for Scala Code

Now a days, it has been very common to use SCALA programming language in Java based project. This may be chosen to get advantage of SCALA's multithreaded nature or this can also be done to slowly migrate Java based Web application from Java to Scala.

Recently, I had to integrate scala in a J2EE web project having JSP pages and Java classes. Here is what I could find out about integrating scala in J2EE project in Eclipse:

Pre-requisites:
1.) You have Eclipse platform with J2EE project setup.
2.) Your eclipse is enabled for SCALA

How to enable your J2EE project so that it can also run SCALA code?

Right click your Dynamic Web project --> Configuration --> Add Scala Nature.




Once you do this, the Eclipse will add SCALA libraries to your web project and your project will be able to compile and run the SCALA code just like Java Code.

Good Luck!

Tuesday, October 28, 2014

MDB did not pick message from queue with error: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2010' ('MQRC_DATA_LENGTH_ERROR')

You have a Message Driver Bean (MDB) which is not picking up message arriving on MQ queue and it gives following error?

MDB did not pick message from queue with error: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2010' ('MQRC_DATA_LENGTH_ERROR')


Caused by: com.ibm.msg.client.jms.DetailedJMSException: JMSWMQ2002: Failed to get a message from destination 'EVENT.OUT'. WebSphere MQ classes for JMS attempted to perform an MQGET; however WebSphere MQ reported an error. Use the linked exception to determine the cause of this error.


I also got this error. This error occurs because the default message length for any Queue or Channel is set to be 4194304 bytes. And this needs to be changed to accept messages of bigger size.

So, I changed the size to 100MB for my Channel (I was using SYSTEM.DEF.SVRCONN) and restarted the MQ server.



The MDB started picking up message. Let me know if this doesn't work.