Friday, January 7, 2011

Spring MVC 3: Using a Document-Oriented Database - MongoDB

In this tutorial we will create a simple Spring MVC 3 application that uses a document-oriented database for its persistence layer. We will be using MongoDB as our database. We will explore and discover how easy it is to integrate MongoDB with Spring MVC 3. Our application is a simple CRUD service for managing a list of Persons. We will provide facilities for adding, deleting, editing, and viewing of all registered persons. This tutorial is similar with my other database integration tutorials: Spring 3 MVC - JDBC Integration Tutorial, Spring 3 MVC - Hibernate 3: Using Annotations Integration Tutorial

Note: An updated version of this tutorial is now accessible at Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 1)

What is MongoDB?
MongoDB (from "humongous") is a scalable, high-performance, open source, document-oriented database. Written in C++, MongoDB features:
  • Document-oriented storage
  • Full Index Support
  • Replication & High Availability
  • Scale horizontally without compromising functionality.
  • Rich, document-based queries.
  • Atomic modifiers for contention-free performance.
  • Flexible aggregation and data processing.
  • Store files of any size without complicating your stack.
  • Enterprise class support, training, and consulting available.

Source: http://www.mongodb.org/
In a nutshell MongoDB uses JSON instead of SQL There's no static schema to create. All schemas are dynamic, meaning you create them on-the-fly. You can try a real-time online shell for MongoDB at http://try.mongodb.org/. Visit the official MongoDB site for a through discussion.

In order to complete this tutorial, you will be required to install a copy of MongoDB. If you don't have a MongoDB yet, grabe one now by visiting this link http://www.mongodb.org/display/DOCS/Quickstart. The installation is really easy.

Let's begin by defining our MongoDBFactory.

MongoDBFactory
package org.krams.tutorial.mongo;

import java.net.UnknownHostException;

import org.apache.log4j.Logger;

import com.mongodb.Mongo;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.MongoException;

/**
 * A simple factory for returning a MongoDB
 */
public class MongoDBFactory {
 
 protected static Logger logger = Logger.getLogger("mongo");
 
 private static Mongo m;
 
 // Make sure no one can instantiate our factory
 private MongoDBFactory() {}
 
 // Return an instance of Mongo
 public static Mongo getMongo() {
  logger.debug("Retrieving MongoDB");
  if (m == null) {
   try {
    m = new Mongo( "localhost" , 27017 );
   } catch (UnknownHostException e) {
    logger.error(e);
   } catch (MongoException e) {
    logger.error(e);
   }
  }
  
  return m;
 }
 
 // Retrieve a db
 public static DB getDB(String dbname) {
  logger.debug("Retrieving db: " + dbname);
  return getMongo().getDB(dbname);
 }
 
 // Retrieve a collection
 public static DBCollection getCollection(String dbname, String collection) {
  logger.debug("Retrieving collection: " + collection);
  return getDB(dbname).getCollection(collection);
 }
}
MongoDBFactory is simply a factory for retrieving a single instance of your database via getDB() and a single instance of your collection via getCollection(). This is a custom class we created to simplify the retrieval of these items. If you prefer to retrieve them manually instead of using this MongoDBFactory, you're free to do so. Here's an example on how you may retrieve them manually:

Remember our database and collections will be created on-the-fly. Our schema will be based on our domain Person object.

Person


Let's now define a Person service for performing CRUD functions in our application.

PersonService

This service defines our basic CRUD system. We have the following public methods:
getAll() - for retrieving all persons
edit() - for editing
delete() - for deleting
add() - for adding
get() - for retrieving single person
We also have the following private methods:
init() - for initializing our database
getDBObject() - for retrieving a single Mongo object
The database is initialized once in the PersonService's constructor through the init() method:


Notice we're creating a dynamic JSON schema here with the following format:
{  
   id:'',
   firstName:'',
   lastName:'',
   money:''
}
Let's complete our Spring MVC application. We need to define a controller.

MainController

This controller declares the following mappings:
/persons - for retrieving all persons
/persons/add (GET) - displays the Add New form
/persons/add (POST) - saves the new person
/persons/delete - deletes an existing person
/persons/edit (GET) - displays the Edit form
/persons/edit (POST) - saves the edited person

Each mapping delegates the call to the PersonService. When the PersonService is done processing, the controller then forwards the request to a JSP page that displays a confirmation message. Here are the JSP pages.

personspage.jsp

editpage.jsp

addpage.jsp

editedpage.jsp

addedpage.jsp

deletedpage.jsp

To finish our Spring MVC application, we need to declare a couple of required XML configurations.

To enable Spring MVC we need to add it in the web.xml

web.xml

Take note of the URL pattern. When accessing any pages in our MVC application, the host name must be appended with
/krams
In the web.xml we declared a servlet-name spring. By convention, we must declare a spring-servlet.xml as well.

spring-servlet.xml

By convention, we must declare an applicationContext.xml as well.

applicationContext.xml

 
 
 
 
 
 
  
That's all we need to do to integrate MongoDB and Spring MVC.

Let's examine what happens in the MongoDB console whenever we perform a particular action in our MVC application. When the application is initially run, we mentioned that it will drop and create a new collection. So MongoDB's console should reflect this action as well. Here's the log:
Fri Jan  7 00:34:10 [initandlisten] connection accepted from 127.0.1.1:42747 #1
Fri Jan  7 00:34:10 [conn1] CMD: drop mydb.mycollection
Fri Jan  7 00:34:10 [conn1] building new index on { _id: 1 } for mydb.mycollection
Fri Jan  7 00:34:10 [conn1] done for 0 records 0secs
It did drop and create our collection.

Now let's access the main page that shows all registered persons. To access the main page, enter the following URL in your browser:
http://localhost:8080/spring-mvc-mongodb/krams/main/persons
Here's what you should see:

Here's the log from MongoDB's console:
Fri Jan  7 00:36:48 [initandlisten] connection accepted from 127.0.1.1:53424 #2
Let's edit the first record in our list by clicking the Edit link. We will be redirected to the Edit Person page:

Here's the log from MongoDB's console:
Fri Jan  7 00:39:07 [initandlisten] connection accepted from 127.0.1.1:53427 #3
After editing the person and submitting the changes, we should see the following page:

However the MongoDB's console didn't change. When return back to the main page, we see the edited person.

Let's stop our application, and check the output from MongoDB's console:
Fri Jan  7 00:47:50 [conn3] end connection 127.0.1.1:53427
Fri Jan  7 00:47:50 [conn1] end connection 127.0.1.1:42747
Fri Jan  7 00:47:50 [conn2] end connection 127.0.1.1:53424
It ended three connections which is logical because we made three connections.

That's it. We've managed to create a simple Spring MVC 3 application that uses MongoDB for its database. We've also seen the benefits of a document-oriented database when we created the schema dynamically.

The best way to learn further is to try the actual application.

Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-mvc-mongodb/

You can download the project as a Maven build. Look for the spring-mvc-mongodb.zip in the Download sections.

You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run

If you want to learn more about Spring MVC and integration with other technologies, feel free to read my other tutorials in the Tutorials section.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC 3: Using a Document-Oriented Database - MongoDB ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

12 comments:

  1. It's not working somehow.

    HTTP Status 404 - /spring-mvc-mongodb/krams/main/persons
    type Status report
    message /spring-mvc-mongodb/krams/main/persons
    description The requested resource (/spring-mvc-mongodb/krams/main/persons) is not available.
    Apache Tomcat/7.0.14

    I imported all the required libraries and opened the project in eclipse.

    ReplyDelete
  2. @Gilberto Albino

    I have resolved the error. When I try to run via "mvn tomcat:run" command I got errors on console.

    In my case I have SpringMongoConfig.java in my project which I am not using but it is throwing error when server starts. When I remove that file from my project it works perfect

    rizzz86

    ReplyDelete
  3. getting same error

    ReplyDelete
  4. thanks working like a charm.

    ReplyDelete
  5. Why don't you put in some exceptions for us that tells us if the mongod is running or not? There is not enough information here on running it. You have assumed your readers are familiar with a lot like Maven and Spring. Sometimes we just like to see it work. I'm using STS Eclipse so I can run goals in it. Try posting that too. No need for mvn command there. Thanks for all your effort with tutorials. I hope we can help you make them better is all. Lots of newbs like me.

    ReplyDelete
    Replies
    1. Douglas, this is an old tutorial. Did you read the note at the beginning of the tutorial? See http://krams915.blogspot.com/2012/01/spring-mvc-31-implement-crud-with_4739.html

      Delete
  6. @Dear Krams , How I get and achieve the one to many relationship between two entities using mongodb in spring mvc

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Good Post! Thank you so much for sharing this pretty post, it was so good to read and useful to improve my knowledge as updated one, keep blogging.

    core java training in Electronic City

    Hibernate Training in electronic city

    spring training in electronic city

    java j2ee training in electronic city

    ReplyDelete
  9. Happy to found this blog. Good Post!. It was so good to read and useful to improve my knowledge as updated one, keep blogging. Hibernate Training in Electronic City
    Java Training in Electronic City

    ReplyDelete
  10. It is amazing and wonderful to visit your site.Thanks for sharing this information,this is useful to me...

    Selenium Training in Electronic City

    ReplyDelete