Tuesday, April 18, 2017

Why should I write Getter/Setter?

Why should I write Getter/Setter?

When I started my career in Java, I was confused about getter and setter. One question always comes to my mind why should I write getter/setter? It looks weird kind of syntax to me.

I learned that by public access modifier one field of a class is accessible to any packages, and by Getter/setter what I am doing is same, make the field private and public the getter/setter method, so it can be accessed by any packages.

So, What is the difference between following two expressions?


public String name=”Shamik”;

Caller
========

String name = X.name;   //(X is a object instance);
X.name=”Shamik Mitra”;
private String name=”Shamik”;

public String getName(){
return name;}

public void setName(String name){
this.name=name;}

Caller
=====
String name = X.getname();
X.setName(“Shamik Mitra”);


confused.jpg
What the heck is getter/setter?




Slowly I realize why we use getter/setter & why it is important.

In this Article, I share that realization.

Realization :

The main difference of making a field public VS expose it through getter/setter is to hold the control to the property.If you make a field  public that means you provide direct access to the caller, caller can do anything with your filed knowingly/unknowingly say, caller can send a null value and if you use that filed in another method it may blow up that method by null pointer exception,

But If you provide getter/setter, you provide them an indirect access while taking full control, because the only way to set a value through setter and get a value through getter, So now you have exact one entry and one exit point of your field and getter/setters are methods!!! (Which allows block of codes) so you can do validation check on them and takes the decision you should set the caller value or not, same in getter method you can take decision should you return the actual reference or clone it and return the same to the caller.


So, getter/Setter are work as fuse or circuit breaker where the current has to be passed through fuse if anything goes abnormal fuse detached from the main circuit, so the circuit is safe. The concept is same here if anything goes wrong setter will not pass the value to class member field.

After reading the explanation, I know still you have one question

I understand all but generally, we do not write anything in getter/setter just return the field and set the field, which is same as exposing a field as public so why are you saying all of this?

To answer this question I say writing getter/setter we create a provision to add any validation method in future, currently, there is no validation but if anything goes wrong in future we just add validation logic in the setter.

But still, it creates a debate who are big follower of YAGNI(You aren't gonna need it),
they can say when there are no such validation constraints for a field why should I write getter/setter, I only expose it as public.

As per my understanding, The crux of YAGNI is to Unnecessary not make your code complex, As someone like to think big and try to make their code base so generic that it welcome any changes but most of the changes he/she thinks will never come.

Conclusion: The  getter/setter does not make your code complex and welcome future validations. So Please go for it blindly.




Tuesday, April 11, 2017

Learn Mongo with java8 : Part 1

Learn Mongodb with java 8


Welcome to my new tutorial series, learn MongoDB with Java 8.

Prerequisite  I hope that you have a basic idea about Bigdata & what are the new features offers in java8 because we use java8 extensively.

Objective: In this Article, we learn

  1. What is MongoDB?
  2. How to setup MongoDB?
  3. How to create a collection in MongoDB.
  4. Insert document in Collection
  5. Write a simple java program where we connect MongoDB and find a value from the collection we have created earlier.


Here is short & crisp details about Mongodb

MongoDB

MongoDB is a NoSQL database where we can store data as BSON format where, key represent the property and value represent, the property value stored against a key.

Document :  In Mongo, The Document represents a data structure which can hold any number of key and values. You can think Employee can be represented as a document where the name, address, age are the keys and their value as value stores in that document. Please note that document stores in binary JSON format generally we called it BSON(Binary JSON).


Example of a Document:

{ "_id" : { "$oid" : "58eb8c2b1de2b36bfcc74326"} , "name" : “Shamik Mitra”}

Collection :
In mongo generally same structured documents are logically put into a bucket, we called the same as the collection. You can think collection as a table in the relational database where every row represents a document. So we can say Employee collection holds Employee document. Note that this is logical, theoretically, a collection can contain any document, for example, a collection can contain Employee document as well as Car document no restrictions there.
NB: while designing, it is preferable to create a collection basis on same structure data.

No Schema :
This is the key difference between a SQL an NoSQL database although I don’t like those term it would be better to say relational and non-relational database. By NoSQL databases, it means it has no predefined schema it can hold anything in BSON format. To be specifically no data structure is defined so it is suitable for storing a Non Structured data.

It makes life easy to developer,  as in relational database there is a fixed schema,
If an Employee table contains the name, age, address column  It stores all data in the same format if we want to add gender we need to change the schema all together to fit new property but in Mongo, there are no such restrictions so it is schema free we can able to put any Employee with any properties.

NB: Although MongoDB is schema free but while designing we logically divide document based on collection so it maintaining an implicit schema!!!



Horizontal Scaling:

The success of Big Data lies in Horizontal scaling as Mongo is a part of Big Data stack,  it supports the same, By Horizontal Scaling MongoDB can distribute the data to multiple nodes, here each node represent a commodity machine i.e a low-cost computer, and we can add and remove node easily. So when we need to store more data we can add new nodes without impacting architecture, wherein Vertical scaling we need a super-computer and data reside in a single centralized source.
NB: Please note that by distributing data in multiple nodes mongo make itself fault tolerant but in Vertical scaling, as data reside in one centralized source if that goes down we lose out data so it is considered as the Single point of failure.



Sharding :

Sharding is a technique by which mongo breaks a gigantic data to small chunks, create a replica of each chunk and distribute those chunk into multiple nodes, when it is time to fetching Mongo holds a metadata information which tells mongo in which node data reside so it fetch contents from those nodes.





Mongo SetUp:


  1. Download the latest mongo Zip distribution from  following link


2. Create a directory D:\InstalledApps  and  Extract the zip in same location.

3. Rename distribution folder to mongodb.
4. Now create a folder named data inside mongodb folder
D:\InstalledApps\mongodb\data
5. Now open a command prompt and go to D:\InstalledApps\mongodb\bin folder using following command
cd D:\InstalledApps\mongodb\bin
6. Start mongodb server using following command
mongod.exe --dbpath D:\InstalledApps\mongodb\data

It will start the server in localhost:27017 port .

Set up Mongo Client :

We will use RoboMongo as our mongo client, it has a nice looking GUI and we can easily create collection add documents using RoboMongo.


Download Robomongo from here


Extract Zip file and click on RoboMongo.exe it will launch RoboMongo GUI

Connect Mongo server using server : localhost and port : 27017 which we started earlier.

Database
Now right click on Right-hand panel computer icon for Create a Database. Give test as a name of the database.



Collection : Now right click on Right hand panel collection icon under created database for create a collection . Create a collection named Employee.

Insert a Document : Now Right click on Employee collection and hit Insert Document and paste the following in text area

{ "name" : "Shamik" , "address" : "1 Nivedita Lane" , "age" : 32}

Hit save that will insert a document in Mongo Server.

Same thing you can achieve through Mongo console also.





Now we are all set for writing a java program to connect Mongodb using java.

Tools Used :
  1. Eclipse Neon
  2. Inbuilt Eclipse maven.
  3. Java 8

Step 1:

We will create a maven project in eclipse call mongoExample set java compiler as java 1.8, Please download java 1.8 if you do not have java 8.

Step 2:
Write a pom.xml like following

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.example</groupId>
 <artifactId>mongoExample</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <dependencies>
 <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>2.10.1</version>
    </dependency>
 
 </dependencies>
</project>

Here we use mongo-java-driver to connect mongo Server using java.

Create a MongoContext:

Next part is to connect Mongo server using Java code so we will create a High-Level class which will abstract the logic of making the connection and also provides utility methods to fetch data from Mongo.

MongoContext.java

/**
*
*/
package com.example.config;

import java.net.UnknownHostException;
import java.util.function.Function;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.MongoClient;

/**
* @author Shamik Mitra
*
*/
public class MongoContext {
   
    private static MongoContext ctx = new MongoContext();
    private  MongoClient client;
    private  DB db;
   
    private MongoContext(){
       
        try{
            init();
        }catch(Exception ex){
            ex.printStackTrace();
        }
       
    }
   
    private void init() throws UnknownHostException{
        this.client = new MongoClient("localhost" , 27017);
    }
   
    public static MongoContext get(){
        return ctx;
    }
   
    public MongoContext connectDb(String dbname){
        if(db !=null){
            throw new RuntimeException("Already conected to " + db.getName() + "can't connect " + dbname);
        }
        this.db = client.getDB(dbname);
        System.out.println("DB Details :: " + db.getName());
        return ctx;
    }
   
    public <T,X> DBCursor findByKey(String collectionName,String key,T value,Function<T,X> convertDataType){
        DBCollection collection = db.getCollection(collectionName);
        BasicDBObject searchQuery = new BasicDBObject();
        searchQuery.put(key, convertDataType.apply(value));
        System.out.println("search Query ::" + searchQuery);
        DBCursor cursor = collection.find(searchQuery);
        return cursor;
    }

}


Explanation of the code :

Here I create a Singleton MongoContext Object, which connects to MongoDB server using mongo java drivers MongoClient class in init method.

this.client = new MongoClient("localhost" , 27017);

Now, we return that Context by the get() method.

At this point, we established a connection with Mongo server.

Next thing is to connect to the test database which we created earlier so I have created a generic method called connectDb(String dbName), Client will pass the database name it wants to connect. Please note that return type of this method is MongoContext itself, here I use Fluent API technique. If you want to know more about Fluent API  go here,


After that ,we want to do a query to fetch any documents from Mongo database.

So I create a Generic method,

public <T,X> DBCursor findByKey(String collectionName,String key,T value,Function<T,X> convertDataType)


This method takes four parameters

collectionName : It takes the collection name from where we want to fetch the document, here Employee is the target collection. You can be thought it as a table name.



Key : Key is the property by which we want to search the collection to fetch multiple documents in a collection, you can think it is the column name in a table which we put in where clause.

Value : It represents the value you search for it is same as the value provided in where clause against a column name.

Function<T,X>  : Here I define a Functional Interface which takes one data type and change it to another datatype T -> X, I need this because when I try to write a generic method findbyKey

I don’t know what will be the datatype of a key beforehand like in Employee collection name is String but age is Integer so If I want to search by name value will be String if age value will be Integer, so I need some strategy which converts the String value to desired Data Type by lambda Expression.

Find the following post for detailed understanding what is lambda Expression.


In that method body, I try to get the collection then create a SearchQuery using BasicDataObject then put key and value in that query.
At last we pass above query to the collection and get the result in a DBCursor Object which internally holds the result.

Time to Test

Create class called Main.java

/**
*
*/
package com.example.mongotest;

import com.example.config.MongoContext;
import com.mongodb.DBCursor;

/**
* @author Shamik Mitra
*
*/
public class Main {
    /**
    *
    */
    public static void main(String[] args) {
        DBCursor result = MongoContext.get().connectDb("test").findByKey("Employee", "age", 32,
                (value) -> new Integer(value));
        while (result.hasNext()) {
            System.out.println(result.next());
        }
    }
}


Here I get the MongoContext then connect the test DB and call the findByKey method by passing Employee as collection age as key and value as 32 and using lambda expression we tell that consider the datatype as Integer.

Please note that in findByKey,  I took data type of value as T,

So, you may be amazed why I pass a Functional Interface?
I can simply pass T data type to the query but I use functional interface to keep provision for any validation or sanity test of the value provided by the user before passing it to query.

Output :

DB Details :: test
search Query ::{ "age" : 32}
{ "_id" : { "$oid" : "58ecde108b308657b44937b1"} , "name" : "Shamik" , "adress" : "1 Nivedita Lane" , "age" : 32}