Friday, January 20, 2012

Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 1)

In this tutorial, we will create a simple CRUD application using Spring 3.1 and MongoDB. In particular, we will use Spring MVC to develop the web application and Spring Data MongoDB for the repository.


Dependencies

  • Spring core 3.1.0.RELEASE
  • Spring Data MongoDB 1.0.0.RELEASE
  • MongoDB (server) 2.0.2
  • MongoDB (Java driver) 2.7.2
  • See pom.xml for details

Github

To access the source code, please visit the project's Github repository (click here)

Functional Specs

Before we start, let's define our application's specs as follows:
  • A CRUD page for managing users
  • Use AJAX to avoid page refresh
  • Users have roles. They are either admin or regular (default)
  • Everyone can create new users and edit existing ones
  • When editing, users can only edit first name, last name, and role fields
  • A username is assumed to be unique

Here's our Use Case diagram:
[User]-(View)
[User]-(Add) 
[User]-(Edit) 
[User]-(Delete) 

Database

If you're new to MongoDB and coming from a SQL-background, please take some time to read the following resource SQL to Mongo Mapping Chart. It's a comparison between SQL and MongoDB.

We have two collections (tables in SQL): user and role. The user collection contains personal information of each user; whereas the role collection contains role values for each user where a value of 1 represents an admin and a value of 2 represents a regular user.

Here's the Class diagram:
# Cool UML Diagram
[User|id;firstName;lastName;username;password;role{bg:orange}]1--1> [Role|id;role{bg:green}]

User document

Below is the JSON structure of the User document after Spring Data MongoDB has created the collection:
{ 
   "_id" : "" , 
   "_class" : "org.krams.domain.User"
   "firstName" : ""
   "lastName" : ""
   "username" : ""
   "password" : "" , 
   "role" : { "$ref" : "role" , "$id" : "" }
}
Notice the role property is a reference to a Role record as indicated by $ref: role property.

Role document

Below is the JSON structure of the Role document after Spring Data MongoDB has created the collection:
{ 
   "_id" : ""
   "_class" : "org.krams.domain.Role"
   "role" : ""
}

Screenshots

Let's preview how the application will look like after it's finished. This is also a good way to clarify further the application's specs.

The Activity diagram:

http://yuml.me/diagram/activity/(start)-%3E%3Cd1%3Eview-%3E(Show%20Records)-%3E%7Ca%7C-%3E(end),%20%3Cd1%3Eadd-%3E(Show%20Form)-%3E%7Ca%7C,%20%3Cd1%3Eedit-%3E%3Cd2%3Ehas%20selected-%3E(Show%20Form)-%3E%7Ca%7C,%20%3Cd2%3Eno%20record%20selected-%3E(Popup%20Alert)-%3E%7Ca%7C,%20%3Cd1%3Edelete-%3E%3Cd3%3Ehas%20selected-%3E(Delete%20Record)-%3E%7Ca%7C,%20%3Cd3%3Eno%20record%20selected-%3E(Popup%20Alert)-%3E%7Ca%7C.

Entry page
The entry page is the primary page that users will see. It contains a table showing user records and four buttons for adding, editing, deleting, and reloading data. All interactions will happen in this page.

Entry page

Edit existing record
When user clicks the Edit button, an Edit Record form shall appear after the table.

Edit record form

When a user submits the form, a success or failure alert should appear.

Success alert

When the operation is successful, the update record should reflect on the table.

Edited record appears on the table

Create new record
When a user clicks the New button, a Create New Record form shall appear after the table.

Create new record form

When a user submits the form, a success or failure alert should appear.

Success alert

When the operation is successful, the new record should appear on the table.

New record shows on the form

Delete record
When user clicks the Delete button, a success or failure alert should appear.

Success alert

Reload record
When user clicks the Reload button, the data on the table should be reloaded.

Errors
When user clicks the Edit or Delete button without selecting a record first, a "Select a record first!" alert should appear.

Error alert

Next

In the next section, we will study how to setup a MongoDB server both in Windows and Ubuntu. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 1) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 3)

Review

In the previous section, we have learned how to setup a MongoDB server in Windows and Ubuntu. In this section, we will discuss the project's structure, write the Java classes, and organize them in layers.


Project Structure

Our application is a Maven project and therefore follows Maven structure. As we create the classes, we've organized them in logical layers: domain, repository, service, and controller.

Here's a preview of our project's structure:

The Layers

Domain Layer

This layer contains two classes, User and Role. They represent our database collections, user and role respectively. We're using Spring Data MongoDB to simplify MongoDB access. And to optimize these classes for the framework, we've added the @Document annotation. If you're familiar with JPA, this is similar to the @Entity annotation.

Notice the User class has a reference to a Role property. In order to achieve that, we must annotate the field with @DBRef.



Mapping annotation overview
  • @Id - applied at the field level to mark the field used for identiy purpose.
  • @Document - applied at the class level to indicate this class is a candidate for mapping to the database. You can specify the name of the collection where the database will be stored.
  • @DBRef - applied at the field to indicate it is to be stored using a com.mongodb.DBRef.
Source: http://static.springsource.org/spring-data/data-document/docs/current/reference/html/

Controller Layer

This layer contains two controllers, MediatorController and UserController
  • MediatorController is responsible for redirecting requests to appropriate pages. This isn't really required but it's here for organizational purposes.
  • UserController is responsible for handling user-related requests such as adding and deleting of records



Service Layer

This layer contains two services, UserService and InitMongoService
  • UserService is our CRUD service for the user collection. All data access is delegated to the repositories
  • InitMongoService is used for initiliazing our database with sample data. Notice we're using the MongoTemplate itself instead of the Spring Data MongoDB-based repository. There is no difference between the two. In fact, it's simpler if we used Spring Data instead. But I have chosen MongoTemplate to show an alternative way of interacting with the database


Note
The mapping framework does not handle cascading saves. If you change an Account object that is referenced by a Person object, you must save the Account object separately. Calling save on the Person object will not automatically save the Account objects in the property accounts.

Source: Spring Data MongoDB Reference (7.3.3. Using DBRefs)

Repository Layer

This layer contains two repositories, UserRepository and RoleRepository. These are our data access objects (DAO). With the help of Spring Data MongoDB, Spring will automatically provide the actual implementation. Notice for custom methods we just have to add the method signature.

What is Spring Data MongoDB?
Spring Data for MongoDB is part of the umbrella Spring Data project which aims to provide a familiar and consistent Spring-based programming model for for new datastores while retaining store-specific features and capabilities. The Spring Data MongoDB project provides integration with the MongoDB document database. Key functional areas of Spring Data MongoDB are a POJO centric model for interacting with a MongoDB DBCollection and easily writing a Repository style data access layer

Source: http://www.springsource.org/spring-data/mongodb




Utility classes

TraceInterceptor class is an AOP-based utility class to help us debug our application. This is a subclass of CustomizableTraceInterceptor (see Spring Data JPA FAQ)



Next

In the next section, we will focus on the configuration files for enabling Spring MVC. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 3) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 2)

Review

In the previous section, we have laid down the functional specs of the application. In this section, we will learn how to setup a MongoDB server both in Windows and Ubuntu.


MongoDB Setup

We will first tackle how to setup MongoDB in Windows, in particular Windows 7; then we will focus on Ubuntu, in particular Ubuntu 10.04.

Windows 7

To setup a MongoDB server in Windows, follow these steps:

1. Open a browser and visit the MongoDB download section at http://www.mongodb.org/downloads

2. Under the Production Release, choose the file that matches your operating system. In our case, it's Windows 32-bit.

3. Once downloaded, extract the contents of the zip file

4. Open the extracted folder and browse under the bin directory. You should see the following executables

5. Select and run mongod.exe application.

6. You should see a command prompt with a similar output:

Do not close the command prompt. Your MongoDB server is now running.

Note: If the command prompt abruptly appears and then disappears, it's possible that the data/db path is missing in your file system.

To verify this,
  1. Open a new command prompt
  2. Run mongod.exe (either by dragging the executable or typing manually the full path)
  3. Read the error and check if it's similar with the following:
    [initandlisten] exception in initAndListen: 10296 dbpath (/d
    ata/db) does not exist, terminating
    dbexit:
    [initandlisten] shutdown: going to close listening sockets...
    [initandlisten] shutdown: going to flush diaglog...
    [initandlisten] shutdown: going to close sockets...
    [initandlisten] shutdown: waiting for fs preallocator...
    [initandlisten] shutdown: closing all files...
    [initandlisten] closeAllFiles() finished
    dbexit: really exiting now
    
  4. If it's the same message, please proceed below to resolve the issue.

To resolve this issue, follow these steps:
  1. Go to C:\ drive
  2. Create a new folder data
  3. Open data
  4. Create a new folder db
  5. Then run mongod.exe again. You should see MongoDB running now.

Ubuntu 10.04

To setup a MongoDB server in Ubuntu, follow these steps:

1. Open a browser and visit the MongoDB download section at http://www.mongodb.org/downloads

2. Under the Production Release, choose the file that matches your operating system. In our case, it's Linux 32-bit.

3. Once downloaded, extract the contents of the compressed file

4. Open the extracted folder and browse under the bin directory. You should see the following executables. Pay attention to mongod.

5. Let's make mongod executable. There are two ways: GUI and terminal-based

GUI-based:
  1. Right-click on the mongod application
  2. Open the "Permissions" tab.
  3. Ensure that "Allow executing file as program" is checked

Terminal-based:
  1. Open a terminal
  2. Run the following command:
    sudo chmod +x PATH/TO/YOUR/MONGO/bin/mongod
    
    
    Make sure to change the path to your Mongo directory.

6. Open a terminal and run the following command:
PATH/TO/YOUR/MONGO/bin/mongod


7. You should see a similar output indicating that your MongoDB server is now running:

Note: If in case there's an error, make sure that /data/db directory exists in the file system. This is similar with the Windows error above.

Next

In the next section, we will discuss the project's structure and start writing the Java classes. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 2) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 4)

Review

In the previous section, we have implemented the Java classes and organized them in various layers. In this section, we will write the configuration files, which are mainly XML documents.


Configuration

To enable MongoDB repository, including template support, we have to declare the following beans:
  • a Mongo repository
  • a Mongo host
  • a Mongo template
  • Optionally, we declared an InitMongoService to automatically populate our database with sample data


For MongoDB connection, we've extracted the database properties in a separate file.


Finally, here's our applicationContext.xml file

Next

In the next section, we will create the HTML and JavaScript files. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 4) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 6)

Review

We have just completed our application! In the previous sections, we have discussed the functional specs, created the Java classes, declared the configuration files, and wrote the HTMl files. In this section, we will build and run the application using Maven, and show how to import the project in Eclipse.


Running the Application

Access the source code

To download the source code, please visit the project's Github repository (click here)

Preparing the data source

  1. Run MongoDB (see Part 2 for instructions)
  2. There's no need to create any collections because Spring will create them automatically
  3. There's no need to populate the database with sample data because our InitMongoService will insert our sample data automatically

Building with Maven

  1. Ensure Maven is installed
  2. Open a command window (Windows) or a terminal (Linux/Mac)
  3. Run the following command:
    mvn tomcat:run
  4. You should see the following output:
    [INFO] Scanning for projects...
    [INFO] Searching repository for plugin with prefix: 'tomcat'.
    [INFO] artifact org.codehaus.mojo:tomcat-maven-plugin: checking for updates from central
    [INFO] artifact org.codehaus.mojo:tomcat-maven-plugin: checking for updates from snapshots
    [INFO] ------------------------------------------
    [INFO] Building spring-mongodb-tutorial Maven Webapp
    [INFO]    task-segment: [tomcat:run]
    [INFO] ------------------------------------------
    [INFO] Preparing tomcat:run
    [INFO] [apt:process {execution: default}]
    [INFO] [resources:resources {execution: default-resources}]
    [INFO] [tomcat:run {execution: default-cli}]
    [INFO] Running war on http://localhost:8080/spring-mongodb-tutorial
    Jan 20, 2012 8:45:19 PM org.apache.catalina.startup.Embedded start
    INFO: Starting tomcat server
    Jan 20, 2012 8:45:19 PM org.apache.catalina.core.StandardEngine start
    INFO: Starting Servlet Engine: Apache Tomcat/6.0.29
    Jan 20, 2012 8:45:19 PM org.apache.catalina.core.ApplicationContext log
    INFO: Initializing Spring root WebApplicationContext
    Jan 20, 2012 8:45:22 PM org.apache.coyote.http11.Http11Protocol init
    INFO: Initializing Coyote HTTP/1.1 on http-8080
    Jan 20, 2012 8:45:22 PM org.apache.coyote.http11.Http11Protocol start
    INFO: Starting Coyote HTTP/1.1 on http-8080
    
  5. Note: If the project will not build due to missing repositories, please enable the repositories section in the pom.xml!

Access the Entry page

  1. Follow the steps with Building with Maven
  2. Open a browser
  3. Enter the following URL (8080 is the default port for Tomcat):
    http://localhost:8080/spring-mongodb-tutorial/

Import the project in Eclipse

  1. Ensure Maven is installed
  2. Open a command window (Windows) or a terminal (Linux/Mac)
  3. Run the following command:
    mvn eclipse:eclipse -Dwtpversion=2.0
  4. You should see the following output:
    [INFO] Scanning for projects...
    [INFO] Searching repository for plugin with prefix: 'eclipse'.
    [INFO] org.apache.maven.plugins: checking for updates from central
    [INFO] org.apache.maven.plugins: checking for updates from snapshots
    [INFO] org.codehaus.mojo: checking for updates from central
    [INFO] org.codehaus.mojo: checking for updates from snapshots
    [INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from central
    [INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from snapshots
    [INFO] -----------------------------------------
    [INFO] Building spring-mongodb-tutorial Maven Webapp
    [INFO]    task-segment: [eclipse:eclipse]
    [INFO] -----------------------------------------
    [INFO] Preparing eclipse:eclipse
    [INFO] No goals needed for project - skipping
    [INFO] [eclipse:eclipse {execution: default-cli}]
    [INFO] Adding support for WTP version 2.0.
    [INFO] -----------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] -----------------------------------------
    
    This command will add the following files to your project:
    .classpath
    .project
    .settings
    target
    You may have to enable "show hidden files" in your file explorer to view them
  5. Open Eclipse and import the project

Conclusion

That's it! We've have successfully completed our Spring MVC 3.1 web application. We've learned how to setup MongoDB and access it through Spring Data MongoDB. Furthermore, we used AJAX to make the application responsive.

I hope you've enjoyed this tutorial. Don't forget to check my other tutorials at the Tutorials section.

Revision History


Revision Date Description
1 Jan 20 2012 Uploaded tutorial and Github repository
2 Jan 22 2012 Updated description of InitMongoService
3 Jan 23 2012 Added class, use case, and activity diagrams

StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 6) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 5)

Review

In the previous section, we have created the configuration files and discussed them accordingly. In this section, we will focus on the view layer, in particular the HTML files and JavaScript codes.


HTML Files (with AJAX)

To improve the user experience, we will use AJAX to make the application responsive. All actions will be performed on the same page (no page refresh). Consequently, we only have one HTML page for the entire application. The rest are JavaScript files.

Notice how we've structured the HTML page. Basically, we followed the concept of separation of concerns by separating markup tags, CSS, and JavaScript code. We tried as much as possible to make the JavaScript code and CSS styles unobtrusive.



A Closer Look

At first glance, this JSP file seems complex. On the contrary, it's quite simple. Let's break it into smaller pieces for clarity:

URLs
The following declares our URLs as mapped to our UserController. We're using the url taglib to make the URL portable.


Imports
Here we're importing custom CSS and JavaScript files, along with jQuery.


What is jQuery?
jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.

Source: http://jquery.com/

JavaScript initialization
Here we're preparing the URLs, attaching functions to our buttons, and initially loading the table. The main chunk of the JavaScript code is referenced from an external JavaScript file custom.js
  • loadTable(): Performs an AJAX request and populates our table with records
  • toggleForms(): Hides and shows specific forms based on the passed argument
  • toggleCrudButtons(): Hides and shows buttons
  • hasSelected(): Checks whether a record has been selected
  • fillEditForm(): Fills the Edit form with details based on the selected record
  • submitDeleteRecord(): Submits a delete request via AJAX
  • submitNewRecord(): Submits a create new record request via AJAX
  • submitUpdateRecord(): Submits an update record request via AJAX


Table and buttons
This is a simple table for displaying records. The buttons are for interacting with the data.


Forms
These are forms used when adding and editing records.


Preview

If we run our application, this is what we shall see:

Entry page

For more screenshots, please visit Part 1 of this tutorial and check the Screenshots section.

Next

In the next section, we will build and run the application using Maven, and show how to import the project in Eclipse. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB (Part 5) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share