Saturday, January 28, 2012

Spring MVC 3.1, jqGrid, and Spring Data JPA Integration Guide (Part 1)

In this tutorial, we will create a simple CRUD application using Spring MVC 3.1, jqGrid, and Spring Data JPA. We will use jqGrid, a jQuery plugin, to present tabular data as an interactive grid, and Spring Data JPA to simplify the creation of JPA repositories (where Hibernate and MySQL are our JPA vendor and database respectively).


Dependencies

  • Spring core 3.1.0.RELEASE
  • Spring Data JPA 1.1.0 RC1
  • jQuery 1.6.4
  • jqGrid 4.3.1
  • 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
  • Display reports in an interactive table
  • 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

Our database contains two tables: user and role tables.


user and role table design

User table

The user table contains personal information of each user. Notice the password values are hashed using Md5.

user table

Role table

The role table contains role values of each user. We define a role value of 1 as an admin, while a role value of 2 as a regular user.

role table

Screenshots

Before we start with the actual development, let's preview how our application should look like by providing screenshots. This is also a good way to clarify further the application's specs.

Entry page
The entry page is the primary page that users will see. It contains an interactive table where users can view, add, edit, and delete records on the same page.
Entry page (page 1)

Entry page (page 2)

Entry page (showing all records at once)

Create new record form
This form is used for adding new records. It is displayed when the user clicks on the Add button.
Create new record

Edit existing record form
This form is used for editing existing records. It is displayed when the user clicks on the Edit button. When editing, the form is pre-populated with the selected record's data.
Edit existing record

Alerts
You must select a record first alert is displayed whenever a user tries to edit or delete an existing record without selecting first that record.
Failure alert

Entry has been edited successfully alert is displayed whenever a successful action has been done, for example editing of an existing record.
Success alert

Filtered records
Records can be filtered by typing keywords on the menu toolbar.
Filtered records

Next

In the next section, we will discuss the project's structure and write 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, jqGrid, and Spring Data JPA Integration Guide (Part 1) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC 3.1, jqGrid, and Spring Data JPA Integration Guide (Part 3)

Review

In the previous section, we have created the Java classes and discussed jqGrid's jsonReader format. In this section, we will focus on the presentation layer, in particular the HTML and JavaScript files.


Presentation Layer

To display our data without page-refresh and interactively, we will add AJAX and jqGrid, a jQuery plugin, to present tabular data.

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/

What is jqGrid?

jqGrid is an Ajax-enabled JavaScript control that provides solutions for representing and manipulating tabular data on the web. Since the grid is a client-side solution loading data dynamically through Ajax callbacks, it can be integrated with any server-side technology, including PHP, ASP, Java Servlets, JSP, ColdFusion, and Perl.

Source: http://www.trirand.com/jqgridwiki/doku.php

Preview

We only have a single HTML file (users.jsp, a JSP to be exact) to perform all actions. This page contains our jqGrid table and buttons for interacting with the data.

Entry page

Source

At first glance, when you look at the JavaScript code, it is somewhat intimidating, but once you've familiarized with the jqGrid syntax, you'll find that it's actually simple. If you aren't familiary with jqGrid, please visit the jqGrid Official Wiki


You might be asking: "What's that humongous lines of jibberish code?" If you'd been following my blog, you would notice that I have tackled jqGrid a couple of times from my previous tutorials. If my explanation in this tutorial isn't enough, please see the following tutorials for an alternative perspective:


An In-depth Look

If we partition this HTML page, you will notice the following sections:
  • URL imports
  • JavaScript and CSS imports
  • jqGrid initialization
  • JavaScript functions: addRow(), editRow(), deleteRow()
  • HTML table

Notice how we've separated the HTML markup from the JavaScript code. We could, of course, move that one huge JavaScript code in an external js file, and make the HTML look somewhat smaller. But I'll leave that exercise to my readers.

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, jqGrid, and Spring Data JPA Integration Guide (Part 3) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC 3.1, jqGrid, and Spring Data JPA Integration Guide (Part 2)

Review

In the previous section, we have laid down the functional specs of the application. 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

This layer contains two domain classes, User and Role. They represent our database tables, user and role respectively. Because we're developing a JPA-based repository, both classes must be annotated with JPA annotations.




Data Transfer Object (DTO)

This layer contains three DTO classes:
  • UserDto is a POJO for mapping User objects to and from the presentation layer
  • StatusResponse is a POJO for sending boolean responses to the presentation layer
  • JqgridResponse is a container for UserDto objects for sending records to the jqGrid table. It contains information regarding the number of rows, current page, and total pages.




What is the principle behind JqgridResponse's structure?

By default, the jqGrid plugin can process data in various formats: XML, JSON, Arrays, and etc. For this tutorial, we will use JSON because it's lightweight and simple. If we're going to use JSON, our JSON format must match our jqGrid's jsonReader property. Consequently, our DTO object must match as well.

Below is a sample jqGrid jsonReader property declaration:

Below is a sample JSON string that's acceptable to jqGrid (Notice the fields match the jsonReader fields and JqgridResponse's fields):
{"page":"1","total":"2","records":"2","rows":[{"id":1,"firstName":"John","lastName":"Smith","username":"john","role":1},{"id":2,"firstName":"Jane","lastName":"Adams","username":"jane","role":2}]}

Controller

This layer contains two controllers, MediatorController and UserController.
  • MediatorController is responsible for redirecting requests from the root path to the Users page
  • UserController is responsible for handling user related requests




The UserController in all cases, except for the getUsersPage() method, returns a JSON string as indicated in the @RequestMapping annotation:
produces="application/json"


The methods create(), update(), delete(), and get() are pretty much straightforward. However, the records() and getFilteredRecords() methods are somewhat more involved.

The records() method basically returns a list of UserDto objects as JSON strings. If the search prooperty is true, it will call the getFilteredRecords() method. Otherwise, it will retrieve all records.

The getFilteredRecords() is quite interesting. The basic algorithm is as follows:
  1. Convert a JSON String filter to a JqgridFilter object
  2. Use JqgridObjectMapper.map() method to do the conversion
    (After the conversion, a list of Rule objects are produced)
  3. Loop these list.
  4. If any of the fields match "username", "firstName", "lastName", and "role", store its value
    (This means we can only search within these fields.)
  5. Do a repository search based on non-empty field parameters
  6. Return the results to the presentation layer

Introducing Jsonquery

Question: What if I want to have a dynamic search on all fields? For example, instead of doing a "like" comparison, I want to do a "greater than" or "less than" and combine various operators, i.e. "and", "or".

Answer: This is not possible with the way I coded that here. And even if I could, it would be a big mess of if-else conditions. Luckily, there's a library that would simplify that for us: jsonquery

Jsonquery is a framework that translates SQL-like JSON queries to type-safe JPQL queries through Querydsl which means each query is type-safe, fluent, and SQL-like. Currently, the framework is designed for JPA-based backends.

To see the actual project, please visit https://github.com/markdevcode/jsonquery
To see the samples, please visit https://github.com/markdevcode/jsonquery-samples

However there are caveats:
  • It's not yet available from the Maven repository (it's on its way)
  • You must build and deploy the project from Github
  • You must use JPA and QueryDSL

Repository

This layer contains a single interface, UserRepository. This is our data access object (DAO). With the help of Spring Data JPA, Spring will automatically provide the actual implementation.

What is Spring Data JPA?

Spring JPA is part of the umbrella Spring Data project that makes it easy to easily implement JPA based repositories.

Implementing a data access layer of an application has been cumbersome for quite a while. Too much boilerplate code has to be written to execute simple queries as well as perform pagination, and auditing. Spring JPA aims to significantly improve the implementation of data access layers by reducing the effort to the amount that's actually needed. As a developer you write your repository interfaces, including custom finder methods, and Spring will provide the implementation automatically.

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

Service

This layer contains a single service, UserService. Its main purpose is to handle the CRUD operations for the User object. Notice all operations are eventually delegated to the UserRepository.

Utilities

  • JqgridFilter is a Java representation of a jqGrid filter
  • JqgridObjectMapper is used to convert a jqGrid filter to a JqgridFilter object
  • UserMapper is used to map User objects to UserDto objects
  • TraceInterceptor 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 discuss the presentation layer and write 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, jqGrid, and Spring Data JPA Integration Guide (Part 2) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC 3.1, jqGrid, and Spring Data JPA Integration Guide (Part 4)

Review

In the previous section, we have focused on the presentation layer and discussed jqGrid. In this section, we will focus on the configuration files, in particular XML files.


Configuration

Database properties

Remember we'll use MySQL as our application's database. However, it's also possible to use a different database provider. Therefore, to make switching database simpler, we've externalized our database configuration within a properties file.


Application Context

Below is a typical application context file for enabling Spring MVC support.


Spring Data

In conjuction with the spring.properties file, we have to declare the actual datasource. Notice we're using JPA and Spring Data JPA support.


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, jqGrid, and Spring Data JPA Integration Guide (Part 4) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC 3.1, jqGrid, and Spring Data JPA Integration Guide (Part 5)

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 MySQL (install one if you don't have one yet)
  2. Create a new database:
    spring_jqgrid_tutorial
  3. Import the following file which is included in the source code under the src/main/resources folder:
    spring_jqgrid_tutorial.sql

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-jqgrid-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-jqgrid-tutorial
    Jan 28, 2012 11:15:25 AM org.apache.catalina.startup.Embedded start
    INFO: Starting tomcat server
    Jan 28, 2012 11:15:25 AM org.apache.catalina.core.StandardEngine start
    INFO: Starting Servlet Engine: Apache Tomcat/6.0.29
    Jan 28, 2012 11:15:26 AM org.apache.catalina.core.ApplicationContext log
    INFO: Initializing Spring root WebApplicationContext
    Jan 28, 2012 11:15:32 AM org.apache.coyote.http11.Http11Protocol init
    INFO: Initializing Coyote HTTP/1.1 on http-8080
    Jan 28, 2012 11:15:32 AM 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-jqgrid-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-jqgrid-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 integrate with jqGrid and add AJAX functionality 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 28 2012 Uploaded tutorial and Github repository
2 Jan 30 2012 Update Functional Specs
3 Feb 11 2012 Update to Spring Data JPA 1.1.0 RC1

StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC 3.1, jqGrid, and Spring Data JPA Integration Guide (Part 5) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share