Thursday, March 26, 2015

asynchronous jquery ajax call

Today there was a case where in we want to do some business validation before form submit on client side and show appropriate message so we decided to use jquery ajax call, we wrote action class which gets called via ajax call but problem was form was also getting submitted and validation was also happening, but it has to happen before form submit so there was two simultaneous calls happening from browser. After few minutes we realized that we need to make ajax call synchronous by adding one more setting parameter async:false which disables ajax call asynchronous capability. Please find below ajax call snippet,


ajaxStart();

    var data={corporateId:selctdCorpId};
        $.ajax({
            url : "checkRequestExists.do",
            type : "post",
            data : data,
            dataType: 'json',
            async: false,
            success : function(response) {
               
                ajaxStop();
               
                if(response.error == 'true' || response.error == true){
                    isError = true;
                    jAlert(response.errorMsg,'Error');
                       return false;
                }
               
            },error:function(response){
                ajaxStop();
                isError = true;
                jAlert('error while checking request exists','Error');
                   return false;
            }
        });

       
Read more about jquery ajax call http://api.jquery.com/jquery.ajax/

Friday, March 20, 2015

Display html from response property using Struts2 and JavaScript escape char problem

Consider we have one action class which return some html string in some property and to get that value of string we are using <s:property value="editResponse" /> in jsp and we want that html string value to be rendered in browser that is we are doing following in our js code,

var result = '<s:property value="editResponse" />';
document.getElementById("onloadTblNode").innerHTML = result;


Problem here is if we use the normal struts2 property element for displaying data, it will escape all the html code, so all your html special chars will get converted into js code, causing html to be not rendered. So solution is use attribute escapeHtml="false" with property tag

var result = '<s:property value="editResponse" escapeHtml="false" />';
document.getElementById("onloadTblNode").innerHTML = result;


Now expected html will get rendered properly.

Thursday, March 19, 2015

Mongo DB Commands

Before we jump on to commands lets see some of the terminologies used.

Mongo db is bit different from our traditional RDBMS, there are no tables, rows or columns instead we will find collections and documents, looks like Object Oriented. Here collections are termed as tables, and table rows as  documents. Some useful terms are
1. database holds a set of collections
2. collection holds a set of documents
3. document is a set of fields
4. field is in form of a key-value pair
5. key is a name
6. value is a any basic type like string, integer, float, timestamp, binary, etc. can be document, or array of values


Step 1 : First open command prompt and navigate to /bin/ directory and start mongo db server by issuing below command on prompt

D:\software\mongodb-win32-i386-2.6.7\bin>mongod.exe --dbpath C:/
2015-03-10T11:06:55.668+0530
2015-03-10T11:06:55.670+0530 warning: 32-bit servers don't have journaling enabled by default. Please use --journal if you want durability.
2015-03-10T11:06:55.672+0530
2015-03-10T11:06:55.683+0530 [initandlisten] MongoDB starting : pid=2420 port=27017 dbpath=C: 32-bit host=CDP011
2015-03-10T11:06:55.684+0530 [initandlisten]
2015-03-10T11:06:55.685+0530 [initandlisten] ** NOTE: This is a 32 bit MongoDB binary.
2015-03-10T11:06:55.685+0530 [initandlisten] **       32 bit builds are limited to less than 2GB of data (or less with --journal).
2015-03-10T11:06:55.687+0530 [initandlisten] **       Note that journaling defaults to off for 32 bit and is currently off.
2015-03-10T11:06:55.688+0530 [initandlisten] **       See http://dochub.mongodb.org/core/32bit
2015-03-10T11:06:55.690+0530 [initandlisten]
2015-03-10T11:06:55.691+0530 [initandlisten] targetMinOS: Windows XP SP3
2015-03-10T11:06:55.693+0530 [initandlisten] db version v2.6.7
2015-03-10T11:06:55.695+0530 [initandlisten] git version: a7d57ad27c382de82e9cb93bf983a80fd9ac9899
2015-03-10T11:06:55.696+0530 [initandlisten] build info: windows sys.getwindowsversion(major=6, minor=1, build=7601, platform=2, service_pack='Service Pack 1') BOOST_LIB_VERSION=1_49
2015-03-10T11:06:55.698+0530 [initandlisten] allocator: system
2015-03-10T11:06:55.699+0530 [initandlisten] options: { storage: { dbPath: "C:/"} }
2015-03-10T11:07:00.037+0530 [initandlisten] waiting for connections on port 27017
2015-03-10T11:07:19.692+0530 [initandlisten] connection accepted from 127.0.0.1:65511 #1 (1 connection now open)
2015-03-10T11:08:00.006+0530 [clientcursormon] mem (MB) res:79 virt:335
2015-03-10T11:08:00.006+0530 [clientcursormon]  mapped:240
2015-03-10T11:08:00.006+0530 [clientcursormon]  connections:1



Step 2 : Then Start mongo shell by executing below command

D:\software\mongodb-win32-i386-2.6.7\bin>mongo.exe
MongoDB shell version: 2.6.7
connecting to: test
Server has startup warnings:
2015-03-10T11:06:55.684+0530 [initandlisten]
2015-03-10T11:06:55.685+0530 [initandlisten] ** NOTE: This is a 32 bit MongoDB binary.
2015-03-10T11:06:55.685+0530 [initandlisten] **       32 bit builds are limited to less than 2GB of data (or less with --journal).
2015-03-10T11:06:55.687+0530 [initandlisten] **       Note that journaling defaults to off for 32 bit and is currently off.
2015-03-10T11:06:55.688+0530 [initandlisten] **       See http://dochub.mongodb.org/core/32bit
2015-03-10T11:06:55.690+0530 [initandlisten]


Step 3 : To list all the available databases use below command

> show dbs

admin    (empty)
company  0.078GB
local    0.078GB
testdb   0.078GB


Step 4 : To create and use new database

> use employee
switched to db employee

Step 5 : Now fire list all database command, to check our db is created or not.

> show dbs
admin    (empty)
company  0.078GB
local    0.078GB
testdb   0.078GB


Our db 'employee' is not listed means it is not physically created yet

Step 6 : Lets insert some data. Mongo db will create database for us, when we will do some operation on it.

> db.record.save({id:"1",name:"abc"})
WriteResult({ "nInserted" : 1 })

This will create collection under our db name record having two fields id and name.  Now check that database named employee created by issuing below command

> show dbs
admin     (empty)
company   0.078GB
employee  0.078GB
local     0.078GB
testdb    0.078GB


We will add more documents/objects or in our database terminology records. Here we will use either document or object interchangeably.

> db.record.save({id:"2",name:"efg"})

WriteResult({ "nInserted" : 1 })

> db.record.save({id:"3",name:"xyz"})
WriteResult({ "nInserted" : 1 })


Step 7: Now we will verify that data is inserted or not by using find command. find() will list all the available documents

> db.record.find()
{ "_id" : ObjectId("54fe86e15cd2094ce66bf7d5"), "id" : "1", "name" : "abc" }
{ "_id" : ObjectId("54fe87a85cd2094ce66bf7d6"), "id" : "2", "name" : "efg" }
{ "_id" : ObjectId("54fe87b25cd2094ce66bf7d7"), "id" : "3", "name" : "xyz" }

>
We can see three document/objects listed in our collection record.


Step 8: Lets search some particular object or record just like out select statement with where clause

> db.record.find({name:"efg"})
{ "_id" : ObjectId("54fe87a85cd2094ce66bf7d6"), "id" : "2", "name" : "efg" }
>


Step 8 : Specify OR criteria using below command, this will list all objects with name equals abc or xyz.

> db.record.find({$or: [{name: 'abc'}, {name: 'xyz'}]});
{ "_id" : ObjectId("54fe86e15cd2094ce66bf7d5"), "id" : "1", "name" : "abc" }
{ "_id" : ObjectId("54fe87b25cd2094ce66bf7d7"), "id" : "3", "name" : "xyz" }


Step 9: Sort the record using sort command by specifying column or key with order -1 for desc and 1 for asc. this will sort output objects descending order.

> db.record.find().sort({name: -1});
{ "_id" : ObjectId("54fe87b25cd2094ce66bf7d7"), "id" : "3", "name" : "xyz" }
{ "_id" : ObjectId("54fe87a85cd2094ce66bf7d6"), "id" : "2", "name" : "efg" }
{ "_id" : ObjectId("54fe86e15cd2094ce66bf7d5"), "id" : "1", "name" : "abc" }
>


Step 10 : Consider a case where find() output a huge set of objects so to limit output we can use limit command as

> db.record.find().limit(2)
{ "_id" : ObjectId("54fe86e15cd2094ce66bf7d5"), "id" : "1", "name" : "abc" }
{ "_id" : ObjectId("54fe87a85cd2094ce66bf7d6"), "id" : "2", "name" : "efg" }


Step 10 : To use limit and offset use skip command along with limit, remember pagination in web page you created long back.

> db.record.find().limit(2).skip(1);
{ "_id" : ObjectId("54fe87a85cd2094ce66bf7d6"), "id" : "2", "name" : "efg" }
{ "_id" : ObjectId("54fe87b25cd2094ce66bf7d7"), "id" : "3", "name" : "xyz" }

Step 11: To update particular object, use below command. This will update object whose id is 2 to 4 and name to efgh.

> db.record.update({id:"2"},{id:"4",name:"efgh"})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

as we can see 1 row affected, to check whether the update happened or not, fire

> db.record.find({id:"4"})
{ "_id" : ObjectId("54fe87a85cd2094ce66bf7d6"), "id" : "4", "name" : "efgh" }

Step 12 : To delete a object use remove method with condition.

> db.record.remove({name:"abcd"})
WriteResult({ "nRemoved" : 1 })

To verify that object is removed or not, fire list all objects using find() command

> db.record.find()

{ "_id" : ObjectId("54fe87a85cd2094ce66bf7d6"), "id" : "4", "name" : "efgh" }
{ "_id" : ObjectId("54fe87b25cd2094ce66bf7d7"), "id" : "3", "name" : "xyz" }
>


Step 13 : To remove all or truncate our collection, use remove() without any condition.

db.record.remove();

Step 14 : Join in mongo db
Please note Mongo db is non RDBMS, so it doesn't support joins but we can achieve the same using MapReduce. If you don't know what is mapreduce then google it fast before proceeding further.

first let's create two collection products with product_id and title fields and prices with product_id and price fields. So here 

db.products.insert({"product_id" : 1, "title" : "Sharpie"});
db.products.insert({"product_id" : 2, "title" : "Sticky"});
db.prices.insert({"product_id" : 1, "price" : 99});
db.prices.insert({"product_id" : 2, "price" : 30});


Then we will create map functions products_map and prices_map

products_map = function() {
  emit(this.product_id, {"title" : this.title});
}

prices_map = function() {
  emit(this.product_id, {"price" : this.price});
};

Then create reduce function r

r = function(key, values) {
  var result = {
      "title" : "",
      "price" : ""
    };

    values.forEach(function(value) {
      if(value.title !== null) {result.title = value.title;}

      if(value.price !== null) {result.price = value.price;}
    });

    return result;
}



Then execute mapReduce command with our created functions namely 'products_map' and 'prices_map'  with reduce function r as below, here mapReduce is built in command which will send output in joined collection, check out syntax from mongo api doc

>
> res = db.products.mapReduce(products_map, r, {out: {reduce : 'joined'}});
{
        "result" : "joined",
        "timeMillis" : 515,
        "counts" : {
                "input" : 2,
                "emit" : 2,
                "reduce" : 0,
                "output" : 2
        },
        "ok" : 1
}



> res = db.prices.mapReduce(prices_map, r, {out: {reduce : 'joined'}});
{
        "result" : "joined",
        "timeMillis" : 43,
        "counts" : {
                "input" : 2,
                "emit" : 2,
                "reduce" : 0,
                "output" : 2
        },
        "ok" : 1
}

>

Now query the result in joined collection using find() command. Looks little complicated first time.

> db.joined.find()
{ "_id" : 1, "value" : { "title" : "Sharpie", "price" : 99 } }
{ "_id" : 2, "value" : { "title" : "Sticky", "price" : 30 } }
>


That's it. Congrats you now know how to start mongo db server and it's shell, and run basics commands.

Wednesday, March 4, 2015

Install and start mongo db server on windows


1. Download a copy of mongodb-win32-i386-2.6.7.zip or installer, we have downloaded archive package.

2. Extract the archive you will find bin directory and read me and license files.



3. Now create db path directory, a location or a physical disk space where in documents or db data will be saved.

>mkdir data
>cd data
>mkdir db

4. Now start mongo db server process using 
D:\software\mongodb-win32-i386-2.6.7\bin>mongod.exe
mongod.exe --help for help and startup options
2015-03-04T17:04:48.848+0530
2015-03-04T17:04:48.851+0530 warning: 32-bit servers don't have journaling enabl
ed by default. Please use --journal if you want durability.
2015-03-04T17:04:48.851+0530
2015-03-04T17:04:49.206+0530 [initandlisten] MongoDB starting : pid=2896 port=27
017 dbpath=\data\db\ 32-bit host=CDP011
2015-03-04T17:04:49.207+0530 [initandlisten]
2015-03-04T17:04:49.207+0530 [initandlisten] ** NOTE: This is a 32 bit MongoDB b
inary.
2015-03-04T17:04:49.208+0530 [initandlisten] **       32 bit builds are limited
to less than 2GB of data (or less with --journal).
2015-03-04T17:04:49.208+0530 [initandlisten] **       Note that journaling defau
lts to off for 32 bit and is currently off.
2015-03-04T17:04:49.208+0530 [initandlisten] **       See http://dochub.mongodb.
org/core/32bit
2015-03-04T17:04:49.209+0530 [initandlisten]
2015-03-04T17:04:49.209+0530 [initandlisten] targetMinOS: Windows XP SP3
2015-03-04T17:04:49.210+0530 [initandlisten] db version v2.6.7
2015-03-04T17:04:49.210+0530 [initandlisten] git version: a7d57ad27c382de82e9cb9
3bf983a80fd9ac9899
2015-03-04T17:04:49.210+0530 [initandlisten] build info: windows sys.getwindowsv
ersion(major=6, minor=1, build=7601, platform=2, service_pack='Service Pack 1')
BOOST_LIB_VERSION=1_49
2015-03-04T17:04:49.212+0530 [initandlisten] allocator: system
2015-03-04T17:04:49.213+0530 [initandlisten] options: {}
2015-03-04T17:04:49.215+0530 [initandlisten] exception in initAndListen: 10296
*********************************************************************
 ERROR: dbpath (\data\db\) does not exist.
 Create this directory or give existing directory in --dbpath.
 See http://dochub.mongodb.org/core/startingandstoppingmongo
*********************************************************************
, terminating
2015-03-04T17:04:49.216+0530 [initandlisten] dbexit:
2015-03-04T17:04:49.217+0530 [initandlisten] shutdown: going to close listening
sockets...
2015-03-04T17:04:49.218+0530 [initandlisten] shutdown: going to flush diaglog...

2015-03-04T17:04:49.219+0530 [initandlisten] shutdown: going to close sockets...

2015-03-04T17:04:49.221+0530 [initandlisten] shutdown: waiting for fs preallocat
or...
2015-03-04T17:04:49.222+0530 [initandlisten] shutdown: closing all files...
2015-03-04T17:04:49.223+0530 [initandlisten] closeAllFiles() finished
2015-03-04T17:04:49.224+0530 [initandlisten] dbexit: really exiting now

4. If you are using for the first time you will surely get above error, carefully read error 
 ERROR: dbpath (\data\db\) does not exist.

5. So always start your db by giving path to dbpath direcory or where it is located
D:\software\mongodb-win32-i386-2.6.7\bin>mongod.exe --dbpath C: 
 2015-03-04T17:05:17.712+0530 warning: 32-bit servers don't have journaling enabl
ed by default. Please use --journal if you want durability.
2015-03-04T17:05:17.712+0530
2015-03-04T17:05:17.724+0530 [initandlisten] MongoDB starting : pid=5752 port=27
017 dbpath=C: 32-bit host=CDP011
2015-03-04T17:05:17.725+0530 [initandlisten]
2015-03-04T17:05:17.725+0530 [initandlisten] ** NOTE: This is a 32 bit MongoDB b
inary.
2015-03-04T17:05:17.726+0530 [initandlisten] **       32 bit builds are limited
to less than 2GB of data (or less with --journal).
2015-03-04T17:05:17.727+0530 [initandlisten] **       Note that journaling defau
lts to off for 32 bit and is currently off.
2015-03-04T17:05:17.729+0530 [initandlisten] **       See http://dochub.mongodb.
org/core/32bit
2015-03-04T17:05:17.731+0530 [initandlisten]
2015-03-04T17:05:17.732+0530 [initandlisten] targetMinOS: Windows XP SP3
2015-03-04T17:05:17.734+0530 [initandlisten] db version v2.6.7
2015-03-04T17:05:17.735+0530 [initandlisten] git version: a7d57ad27c382de82e9cb9
3bf983a80fd9ac9899
2015-03-04T17:05:17.737+0530 [initandlisten] build info: windows sys.getwindowsv
ersion(major=6, minor=1, build=7601, platform=2, service_pack='Service Pack 1')
BOOST_LIB_VERSION=1_49
2015-03-04T17:05:17.739+0530 [initandlisten] allocator: system
2015-03-04T17:05:17.740+0530 [initandlisten] options: { storage: { dbPath: "C:"
} }
2015-03-04T17:05:21.698+0530 [initandlisten] allocating new ns file C:local.ns,
filling with zeroes...
2015-03-04T17:05:22.077+0530 [FileAllocator] allocating new datafile C:local.0,
filling with zeroes...
2015-03-04T17:05:22.078+0530 [FileAllocator] creating directory C:_tmp
2015-03-04T17:05:22.366+0530 [FileAllocator] done allocating datafile C:local.0,
 size: 64MB,  took 0.286 secs
2015-03-04T17:05:22.370+0530 [initandlisten] build index on: local.startup_log p
roperties: { v: 1, key: { _id: 1 }, name: "_id_", ns: "local.startup_log" }
2015-03-04T17:05:22.370+0530 [initandlisten]     added index to empty collection

2015-03-04T17:05:22.371+0530 [initandlisten] command local.$cmd command: create
{ create: "startup_log", size: 10485760, capped: true } ntoreturn:1 keyUpdates:0
 numYields:0  reslen:37 673ms
2015-03-04T17:05:22.373+0530 [initandlisten] waiting for connections on port 270
17
2015-03-04T17:06:21.657+0530 [clientcursormon] mem (MB) res:34 virt:174
2015-03-04T17:06:21.657+0530 [clientcursormon]  mapped:80
2015-03-04T17:06:21.659+0530 [clientcursormon]  connections:0
2015-03-04T17:11:21.687+0530 [clientcursormon] mem (MB) res:34 virt:171
2015-03-04T17:11:21.687+0530 [clientcursormon]  mapped:80
2015-03-04T17:11:21.687+0530 [clientcursormon]  connections:0
2015-03-04T17:16:21.710+0530 [clientcursormon] mem (MB) res:34 virt:171
2015-03-04T17:16:21.711+0530 [clientcursormon]  mapped:80

6. Now your mongo db server is up and ready to serve request.

That's all, no need to install as an application on windows.  



Monday, March 2, 2015

Encrypt plain text password in spring configuration file

We store our database credentials that is username, password and url in spring configuration xml file, which is vulnerability to address this issue we need to encrypt and store credentials in config files. Either we can go for jasypt or custom data source. Disadvantage of jasypt is we need to add dependencies and it comes with bit complexity, we will see custom data source for encoding database password. One can use any type of encryption or encoding here.

In spring to obtain jdbc connection or hibernate session factory we use dataSource bean initialize with appropriate properties with value for dependency injection as follows:

 <!-- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">  -->
<bean id="dataSource" class="com.empays.eibm.util.MyCustomBasicDataSource" >
   
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@192.168.40.104:1521:nodedb" />
        <property name="username" value="EIBM_NODE" />
       
        <!--  <property name="password" value="${jdbc.passworddd}"></property> -->
        <property name="password" value="RUlCTV9OT0RFMQ=="></property>
   
       
        <property name="initialSize" value="30" />
        <property name="maxActive" value="30" />
        <property name="minIdle" value="0" />
        <property name="defaultAutoCommit" value="true" />
        <property name="testOnBorrow" value="true" />
        <property name="testOnReturn" value="true" />
        <property name="testWhileIdle" value="true" />
        <property name="timeBetweenEvictionRunsMillis" value="10000" />   
    </bean>

   
As we can see we have added encoded password value, if we are using database.properties use key with expression.
And we have change standard datasource class from org.apache.commons.dbcp.BasicDataSource to com.empays.eibm.util.MyCustomBasicDataSource follow commented lines in above snippet. Our MyCustomBasicDataSource will extend org.apache.commons.dbcp.BasicDataSource from equivalent common-dbcp-1.2.jar file and override public setPassword() method and assign decoded plain text password to protected variable using this.password to allow him to do actual database connection.

package com.abc.app.util;

import java.io.IOException;

import org.apache.commons.dbcp.BasicDataSource;

import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;

/**
 * Custom data source class impl for decoding the encoded password in config
 * file.
 *
 * @author Nishant
 *
 */
public class MyCustomBasicDataSource extends BasicDataSource {

    public MyCustomBasicDataSource() {
        super();
    }

    /**
     * decode and set password to protected variable.
     *
     *  (non-Javadoc)
     * @see org.apache.commons.dbcp.BasicDataSource#setPassword(java.lang.String)
     */
    public synchronized void setPassword(String encodedPassword) {
        this.password = decode(encodedPassword);
    }

    /**
     * Util method for encoding.
     *
     * @param plainPass
     *
     * @return encodedPass
     */
    public static String encode(String plainPass) {

        BASE64Encoder encoder = new BASE64Encoder();
        String encodedPass = null;
        encodedPass = new String(encoder.encodeBuffer(plainPass.getBytes()));
        return encodedPass;
    }

    /**
     * Util method for decoding.
     *
     * @param encodedPass
     *
     * @return decodedPassword
     */
    public static String decode(String encodedPass) {

        BASE64Decoder decoder = new BASE64Decoder();
        String decodedPassword = null;
        try {
            decodedPassword = new String(decoder.decodeBuffer(encodedPass));
        } catch (IOException e) {
            System.out.println("IOException:" + e.getMessage());
            e.printStackTrace();
        }

        return decodedPassword;
    }
}



Thats all..