Tags

, , , , ,

In this post , i am going to build a blog because lot of people are familiar with that. It will be write with Java.
We will see not how to install MongoDB but how java works in MongoDB.

What is MongoDB ?

It is a non relational data store for JSON documents, it does not store data in tables like a relational database does, however, it stores JSON documents.

So, what’s JSON ?

It is Java script object notation look like with have a key and the value.In the document JSON, we can have also a key with array as the value like this :

{"name":"Madishon","a":4,"b":14,fruit:["apple","apple","banana"]}

In relational database, it is difficult to hava a array like fruit in the same document.This is very usefull when writing programs.
Even MongoDB stores documents but another aspect for MongoDB is schemaless.
What does that mean ? Two documents don’t need to have the same schema, so we can have on the same collection, documents with differents values like below:

{"a":3,"b":7}
{"a":7,"b":9,"c":10}

In conclusion, MongoDB is schemaless and it is document oriented.

Notes:

MongoDB is schemaless but it also sometimes use the term ‘dynamic schema.’ The point is that, unlike in a relational database, we are not constrained to follow any particular schema. If we wish to change our schema, we are free to do any of the following:
Begin inserting documents with the new schema.
Perform a bulk update on the existing documents.
Begin updating old documents to the new schema one by one at an appropriate event (such as getting read from or written to), as coded in the application.
Contrast this with what happens in a relational database, where the table must typically be taken offline in order to add columns.
MongoDB does not support joins as a design decision because they do not scale horizontally, and it does not support SQL because that query language was built around joins and transactions, and tends to assume table structure rather than the flexible document orientation that MongoDB provides.

Overview of building an App with MongoDB:

Now we are going to know how to build an application using Java.So we have MongoDB software installed , then we have mongod process.There are a couple ways to connect to MongoDB, one of the things is the Mongo shell.
It is a standalone program called Mongo that has a JavaScript shell language built inside it and connects via TCP tp MongoDB. And this is a way to manipulate data and inspect data.
Here, i are building an Java application, so we are building a blog with bunch of pages for inserting posts and showing posts, and inserting comments, and showing comments. So this is the blog and this is all going to written in Java.
So, we have a Java application with differents paths of this. Our application itself will be called our cade.
Our Java code is going to use two differents frameworks that are going to make it easier to write web apps.
One is called Spark Java and the other one is called free Marker. So Spark Java is a micro web framework inspired by Sinatra, that will allow us to easily set up routes that map to URLs, so that when a request comes in for a particular URL, we can handle it and we can make a response via HTTP. And then Free Marker is a templeting language that allows us to create HTML views so that we can use Model View Controller type programming where the view, which is the UI part, is separate from the controller, which handles user imput in the model, which is the underlying logic of the application.
Now this all runs inside JVM because this is Java.All this code Spark and Free Framework in order to talk to MongoDB, needs to talk to the Mongo Java driver. And the Mongo Java Driver is a library that’s going to be linked in and that is actually going to be the part that is making the TCP connections to MongoDB for you.So we’re going to write some java code , it’s going to use Spark Java which we’ll go over . And Free Marker, which will go over, which is a tempplating language and then also uses the Mongo Java driver, which is Java code meant to talk to MongoDB and retrieve data and insert data to the database.
And all of this together is going to present this blog.And then the user is on the other side in and he is talking to the process of our code application. Normally for a web request, it would be port 80, but for our example, we’re going to use 8082 because 80 is reserved and difficult to use that port if you’re not root on the computer.And then this might go through some sort of network address translation through a Linksys box or something like that.
So here, we’re going to give most of the code for thge blog that we can make some modification and manipulate data in the database, because the point is not to teach how to be a web programmer but how to use MongoDB.

System Requirements:

we’re using Centos 6.7 and JDK 8.

[hduser@base ~]$ java -version
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b25)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)
[hduser@base ~]$ javac -version
javac 1.8.0_40

Installing MongoDB on Centos 6.7:

We installed MongoDB 3.0.6

[hduser@base ~]$ mongo -version
MongoDB shell version: 3.0.6

We have a cluster with 1 master and 3 replicat set:

[hduser@base ~]$ mongo --host `hostname -I|awk  '{print $1}'`  --quiet
repset:PRIMARY> rs.status()
{
	"set" : "repset",
	"date" : ISODate("2016-01-10T04:25:22.835Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "base.deb.com:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 79960,
			"optime" : Timestamp(1451456145, 1),
			"optimeDate" : ISODate("2015-12-30T06:15:45Z"),
			"electionTime" : Timestamp(1452320253, 1),
			"electionDate" : ISODate("2016-01-09T06:17:33Z"),
			"configVersion" : 14,
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "dn1.deb.com:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 79682,
			"optime" : Timestamp(1451456145, 1),
			"optimeDate" : ISODate("2015-12-30T06:15:45Z"),
			"lastHeartbeat" : ISODate("2016-01-10T04:25:22.543Z"),
			"lastHeartbeatRecv" : ISODate("2016-01-10T04:25:22.494Z"),
			"pingMs" : 0,
			"configVersion" : 14
		},
		{
			"_id" : 2,
			"name" : "dn2.deb.com:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 79669,
			"optime" : Timestamp(1451456145, 1),
			"optimeDate" : ISODate("2015-12-30T06:15:45Z"),
			"lastHeartbeat" : ISODate("2016-01-10T04:25:20.936Z"),
			"lastHeartbeatRecv" : ISODate("2016-01-10T04:25:22.246Z"),
			"pingMs" : 0,
			"configVersion" : 14
		},
		{
			"_id" : 3,
			"name" : "dn3.deb.com:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 79607,
			"optime" : Timestamp(1451456145, 1),
			"optimeDate" : ISODate("2015-12-30T06:15:45Z"),
			"lastHeartbeat" : ISODate("2016-01-10T04:25:21.237Z"),
			"lastHeartbeatRecv" : ISODate("2016-01-10T04:25:22.640Z"),
			"pingMs" : 0,
			"configVersion" : 14
		}
	],
	"ok" : 1
}
repset:PRIMARY>

Installing and Using Maven:

Lecture Notes:

Additional installation instructions regarding specific operating systems can be found at:
http://maven.apache.org/download.cgi#Installation
We need to build a automation tool and there are a couple to choose from, but for this example , we will choose one called Maven. We’re downloading it on:https://maven.apache.org/download.cgi
we downloaded apache-maven-3.3.9-bin.zip , then unzip it:

unzip apache-maven-3.3.9-bin.zip

Put the apache-maven-3.3.9/bin on the .profile: for Centos, on .bashrc and .bash_profile for the user who will execute Marven.

[hduser@base ~]$ mvn
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.315 s
[INFO] Finished at: 2016-01-10T00:27:48-05:00
[INFO] Final Memory: 4M/90M
[INFO] ------------------------------------------------------------------------
[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format 
[ERROR] : or :
[ERROR] [:]:. Available lifecycle phases are: validate, initialize, generate-sources, 
[ERROR] process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, 
[ERROR] process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, 
[ERROR] test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, 
[ERROR] verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/NoGoalSpecifiedException

So we have Maven in our path.
On our home directory, we have to create Maven Project, now, Maven uses something called a Project Object Model which is abbreviated as POM, and the POM and it is nstored in a file called pom.xml.We can created one by hand , so we’re going to use this handy plug-in from Maven called Archetype to create a new emplty Maven project.

We can run it by:

mvn archetype:generate

but we’ll choose the default , and we’ll just take default for which version but Maven requires a group ID, which is kind of like a java package name: com.mongodb and for an artifact name, we’ll choose the name like: M101J.

Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.1/maven-archetype-quickstart-1.1.pom 
(2 KB at 19.8 KB/sec)
Define value for property 'groupId': : com.mongodb
Define value for property 'artifactId': : M101J
Define value for property 'version':  1.0-SNAPSHOT: : 
Define value for property 'package':  com.mongodb: : 
Confirm properties configuration:
groupId: com.mongodb
artifactId: M101J
version: 1.0-SNAPSHOT
package: com.mongodb
 Y: : 
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: basedir, Value: /home/hduser
[INFO] Parameter: package, Value: com.mongodb
[INFO] Parameter: groupId, Value: com.mongodb
[INFO] Parameter: artifactId, Value: M101J
[INFO] Parameter: packageName, Value: com.mongodb
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /home/hduser/M101J
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 07:19 min
[INFO] Finished at: 2016-01-10T00:48:02-05:00
[INFO] Final Memory: 16M/146M
[INFO] ------------------------------------------------------------------------

we can do it also via this commande:

mvn archetype:generate -DgroupId=com.mongodb -DartifactId=M101J -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

It created the directory like below:

[hduser@base ~]$ ls -ltr M101J
total 8
-rw-r--r-- 1 hduser hadoop  743 Jan 10 00:48 pom.xml
drwxr-xr-x 4 hduser hadoop 4096 Jan 10 00:48 src

In the pom.xml, we have the source directory and we have the content of my pom.xml by using JDK 8:

  4.0.0
  com.mongodb
  M101J
  jar
  1.0-SNAPSHOT
  M101J
  http://maven.apache.org

  
    1.8
    1.8
  

  

    
      com.sparkjava
      spark-core
      2.0.0
    

    
      org.slf4j
      slf4j-simple
      1.7.5
    

    
      org.mongodb
      mongo-java-driver
      3.1.0
    

    
      com.google.code.gson
      gson
      2.2.4
    

    
      junit
      junit
      3.8.1
      test
    
  

    
        
            Spark repository
            http://www.sparkjava.com/nexus/content/repositories/spark/
        
    

The source directory has a class called App.java and then also a test called AppTest.java

See below the simple code of App.java, that print Hello World:

[hduser@base mongodb]$ pwd
/home/hduser/M101J/src/main/java/com/mongodb
[hduser@base mongodb]$ cat App.java
package com.mongodb;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
    }
}

So we can run this class with a Maven plug-in called Exec: the class for our example is called : com.mongodb.App

cd /home/hduser/M101J
mvn clean compile exec:java -Dexec.mainClass=com.mongodb.App

If it works, you will get this result:

Downloading: https://repo.maven.apache.org/maven2/org/apache/commons/commons-parent/35/commons-parent-35.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/commons/commons-parent/35/commons-parent-35.pom 
(57 KB at 499.3 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/apache/apache/15/apache-15.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/apache/15/apache-15.pom (15 KB at 158.3 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-utils/3.0.20/plexus-utils-3.0.20.jar
Downloading: https://repo.maven.apache.org/maven2/org/apache/commons/commons-exec/1.3/commons-exec-1.3.jar
Downloaded: https://repo.maven.apache.org/maven2/org/apache/commons/commons-exec/1.3/commons-exec-1.3.jar 
(54 KB at 320.2 KB/sec)
Downloaded: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-utils/3.0.20/plexus-utils-3.0.20.jar
(238 KB at 770.9 KB/sec)
Hello World!
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 21.632 s
[INFO] Finished at: 2016-01-10T01:05:11-05:00
[INFO] Final Memory: 19M/199M
[INFO] ------------------------------------------------------------------------


[hduser@base M101J]$ ls -ltr
total 12
-rw-r--r-- 1 hduser hadoop  743 Jan 10 00:48 pom.xml
drwxr-xr-x 4 hduser hadoop 4096 Jan 10 00:48 src
drwxr-xr-x 4 hduser hadoop 4096 Jan 10 01:05 target
[hduser@base M101J]$ ls -ltr target
total 8
drwxr-xr-x 3 hduser hadoop 4096 Jan 10 01:05 maven-status
drwxr-xr-x 3 hduser hadoop 4096 Jan 10 01:05 classes

In this demo, we will use tool called IntelliJIDEA, if you like , you can download it here:https://www.jetbrains.com/idea/download/#section=linux

Spark Web Application Framework:

The final project is web application,so one of the things we need to do is get started with a web application . There’s a lot of web application frameworks for Java. For our example, we’ll use a simple web application with minimun dependencies and is really easy to get started.
So, we choose framework called Spark. here, we don’t need a web server or an application server. So , like Mongo Java, we have to import it on the project.
The first thing in Spark is to tell to Maven where is the spark repository in our POM.xml by using , for example IntelliJIDEA:
In my POM.XML, i add this repository:

    
        
            Spark repository
            http://www.sparkjava.com/nexus/content/repositories/spark/
        

Then i add also this dependency:

    
      com.sparkjava
      spark-core
      2.0.0

Now we are ready to create our first spark application called SparkSayHelloWorld:

package com.mongodb;
import spark.Request;
import spark.Response;
import spark.Route;
import static spark.Spark.*;
/*** Created by hduser on 11/01/16.*/
public class SparkSayHelloWorld {
    public static void main(String[] args) {
        get("/", new Route() {
            @Override
            public Object handle(Request request, Response response) {
                return "Hello World!!";
            }
        });
    }
}

By executing SparkSayHelloWorld with IntelliJIDEA, we got this result:

/usr/java/jdk1.8.0/bin/java -Didea.launcher.port=7532 -Didea.launcher.bin.path=/home/hduser/IDEAIC/idea-IC-143.1184.17/bin -Dfile.encoding=UTF-8 -classpath /usr/java/jdk1.8.0/jre/lib/charsets.jar:/usr/java/jdk1.8.0/jre/lib/deploy.jar:/usr/java/jdk1.8.0/jre/lib/ext/cldrdata.jar:/usr/java/jdk1.8.0/jre/lib/ext/dnsns.jar:/usr/java/jdk1.8.0/jre/lib/ext/jfxrt.jar:/usr/java/jdk1.8.0/jre/lib/ext/localedata.jar:/usr/java/jdk1.8.0/jre/lib/ext/nashorn.jar:/usr/java/jdk1.8.0/jre/lib/ext/sunec.jar:/usr/java/jdk1.8.0/jre/lib/ext/sunjce_provider.jar:/usr/java/jdk1.8.0/jre/lib/ext/sunpkcs11.jar:/usr/java/jdk1.8.0/jre/lib/ext/zipfs.jar:/usr/java/jdk1.8.0/jre/lib/javaws.jar:/usr/java/jdk1.8.0/jre/lib/jce.jar:/usr/java/jdk1.8.0/jre/lib/jfr.jar:/usr/java/jdk1.8.0/jre/lib/jfxswt.jar:/usr/java/jdk1.8.0/jre/lib/jsse.jar:/usr/java/jdk1.8.0/jre/lib/management-agent.jar:/usr/java/jdk1.8.0/jre/lib/plugin.jar:/usr/java/jdk1.8.0/jre/lib/resources.jar:/usr/java/jdk1.8.0/jre/lib/rt.jar:/home/hduser/M101J/target/classes:/home/hduser/.m2/repository/com/sparkjava/spark-core/2.0.0/spark-core-2.0.0.jar:/home/hduser/.m2/repository/org/slf4j/slf4j-api/1.7.2/slf4j-api-1.7.2.jar:/home/hduser/.m2/repository/org/eclipse/jetty/jetty-server/9.0.2.v20130417/jetty-server-9.0.2.v20130417.jar:/home/hduser/.m2/repository/org/eclipse/jetty/orbit/javax.servlet/3.0.0.v201112011016/javax.servlet-3.0.0.v201112011016.jar:/home/hduser/.m2/repository/org/eclipse/jetty/jetty-http/9.0.2.v20130417/jetty-http-9.0.2.v20130417.jar:/home/hduser/.m2/repository/org/eclipse/jetty/jetty-util/9.0.2.v20130417/jetty-util-9.0.2.v20130417.jar:/home/hduser/.m2/repository/org/eclipse/jetty/jetty-io/9.0.2.v20130417/jetty-io-9.0.2.v20130417.jar:/home/hduser/.m2/repository/org/eclipse/jetty/jetty-webapp/9.0.2.v20130417/jetty-webapp-9.0.2.v20130417.jar:/home/hduser/.m2/repository/org/eclipse/jetty/jetty-xml/9.0.2.v20130417/jetty-xml-9.0.2.v20130417.jar:/home/hduser/.m2/repository/org/eclipse/jetty/jetty-servlet/9.0.2.v20130417/jetty-servlet-9.0.2.v20130417.jar:/home/hduser/.m2/repository/org/eclipse/jetty/jetty-security/9.0.2.v20130417/jetty-security-9.0.2.v20130417.jar:/home/hduser/.m2/repository/org/slf4j/slf4j-simple/1.7.5/slf4j-simple-1.7.5.jar:/home/hduser/.m2/repository/org/mongodb/mongo-java-driver/3.1.0/mongo-java-driver-3.1.0.jar:/home/hduser/.m2/repository/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar:/home/hduser/IDEAIC/idea-IC-143.1184.17/lib/idea_rt.jar com.intellij.rt.execution.application.AppMain com.mongodb.SparkSayHelloWorld
== Spark has ignited ...
>> Listening on 0.0.0.0:4567
[Thread-0] INFO org.eclipse.jetty.server.Server - jetty-9.0.2.v20130417
[Thread-0] INFO org.eclipse.jetty.server.ServerConnector - Started ServerConnector@1c54c38b{HTTP/1.1}{0.0.0.0:4567}

With our browser http://localhost:4567/ , we had the result: Hello World

Freemakrker Templating Engine:

It is a template engine
see information here:http://freemarker.incubator.apache.org/
We have to add a dependency of Freemarker in our POM.XML:

 org.freemarker
 freemarker
 2.3.20

Blog in Relational Tables:

let’s assume that our blog can be modeled with the following relational tables.

authors:
	author_id,
	name,
	email,
	password
posts:
	post_id,
	author_id
	title,
	body,	
	publication_date

comments:
	comment_id,
	name, 
	email,
	comment_text

post_comments:
	post_id,
	comment_id

tags
	tag_id
	name

post_tags
	post_id
	tag_id

In order to display a blog post with its comments and tags, we will be accessed 6 tables in a relational system.

Modeling a Blog in MongoDB:

Posts collection:Imagine we have a collection called posts which we can have a title of the post, the body and the author , the date of the post was posted then propably some comments also tags.
Authors collection:we can have a authors collection which will contain username, password.
Here we have 2 collections that represent 6 tables that we have in relational system.
To access the home page of our blog, we need only the posts collection because in this collection we have also the information about authors.

Schema Design:

In the posts collection, tags and comments can have the same elements, in this scenario it is impossible to embed these data within a document posts (we must put them in a separate collection), if not the embedded data could exceed the 16MB document limit within MongoDB.