Friday, September 16, 2011

Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 1

Introduction

In this article we will explore how to integrate MySQL, MongoDB, and RabbitMQ in a Spring MVC application using Spring Data JPA, Spring Data MongoDB, and Spring AMQP projects respectively. Then we'll add AJAX in the presentation layer using jQuery. For presenting tabular data, we will explore two jQuery plugins: DataTables and jQgrid. The jQgrid version will use Spring Cache support to boost performance. The ultimate purpose of this article is to demonstrate how to integrate these different projects in a single Spring MVC application.

Our application is a simple event management system for performing CRUD operations. When we talk of events, we're referring to the colloquial definition, i.e wedding event. The application's main data will be stored in a MySQL database using Hibernate as our ORM. We will use Spring Data JPA to simplify the data access layer. This means we don't need to implement our own data access objects.

Our application is also capable of broadcasting these events as simple text messages. To broadcast these events, we will use RabbitMQ as our messaging broker, and Spring AMQP for sending and receiving of messages.

No application is free from errors. Therefore, we've added error persistence capability using MongoDB. Our application has logging capabilities already, but we want the ability to analyze these errors later. Therefore, this is where MongoDB plays in. To simplify the data access layer, we will use Spring Data MongoDB, similar with Spring Data JPA.

Table of Contents

  1. Event Management
  2. Messaging support
  3. Error persistence
  4. Build and deploy

Frequently Asked Questions (FAQs)

  1. Q: What is JPA?
    A: See http://en.wikipedia.org/wiki/Java_Persistence_API
  2. Q: What is MongoDB?
    A: See http://www.mongodb.org
  3. Q: What is RabbitMQ?
    A: See http://www.rabbitmq.com
  4. Q: What is Spring Data?
    A: See http://www.springsource.org/spring-data
  5. Q: What is Spring Data - JPA?
    A: See http://www.springsource.org/spring-data/jpa
  6. Q: What is Spring Data - MongoDB?
    A: See http://static.springsource.org/spring-data/data-document/docs/current/reference/html
  7. Q: What is Spring AMQP?
    A: See http://www.springsource.org/spring-amqp
  8. Q: What is jQuery?
    A: http://jquery.com/
  9. Q: What is AJAX?
    A: http://en.wikipedia.org/wiki/Ajax_(programming)
  10. Q: What is Ehcache?
    A: http://ehcache.org/

Required Tools and Services

The following tools and services are essential in building and running our project:
  1. MySQL
  2. The application's main data will be stored in MySQL. If you don't have one yet, download and install one by visiting the MySQL home page, or use a pre-packaged setup via XAMPP or Wamp.
    • MySQL: http://www.mysql.com/downloads/
    • Wamp: http://www.wampserver.com
    • XAMPP: http://www.apachefriends.org
  3. RabbitMQ
  4. We will publish and listen for messages using RabbitMQ. If you don't have one yet, download and install one by visiting the RabbitMQ home page.
    • http://www.rabbitmq.com/download.html
  5. MongoDB
  6. We will persist errors using MongoDB. If you don't have one yet, download and install one by visiting the MongoDB home page.
    • http://www.mongodb.org/downloads
  7. Maven
  8. We will use Maven to build our project. If you don't have one yet, download and install one by visiting the Maven home page. You can also use SpringSource Tool Suite (STS), an Eclipse-powered IDE, which has Maven pre-installed.
    • Maven: http://maven.apache.org/download.html
    • STS: http://www.springsource.com/developer/sts

Screenshots

Before we dive into development, it's better if we first visualize what we will be developing.






Live Deployment in the Cloud

The best way to interact with the application is with a live deployment. Therefore, I have taken extra steps to deploy the project in the cloud via the excellent open platform Cloud Foundry. To access the project, visit http://spring-mysql-mongo-rabbit.cloudfoundry.com/

Project Structure

To see how we're going to structure the project, take a look at the following screenshot:


The project's source code is available at GitHub. You can access the project's repository at spring-mysql-mongo-rabbit-integration

Project Dependencies (pom.xml)

The pom.xml contains the project's dependencies. It's a long list but I will only show the relevant entries. As of Sept 17 2011, we're using the latest versions.

What is POM?
POM stands for "Project Object Model". It is an XML representation of a Maven project held in a file named pom.xml. See http://maven.apache.org/pom.html

To see the pom's entire contents, please check the attached Maven project at the end of this tutorial.

Development

The project will be divided into four parts:
  1. Event Management
  2. Messaging support
  3. Error persistence
  4. Build and deploy

A. Event Management

The Event Management is the core function of the system. And we're specifically referring to the CRUD operations. We will divide this stage in four sub-parts:
  1. Event Management
    • A1. Domain
    • A2. Service
    • A3. Controller
    • A4. View
      1. DataTables view
      2. jQgrid view
    • A5. Crosscutting Concerns

A1. Domain

The domain contains a simple Event class. By marking it with @Entity the class will be persisted in a relational database. Notice the class has validation constraints added. For example, the name field cannot be null.

Special attention is given to the date field. We've annotated it with @DateTimeFormat, a Spring conversion annotation (see Spring Reference 5.6.2.1 Format Annotation API) to help us serialize and deserialize JSON dates in the presentation layer.

Event.java


A2. Service

Before we start developing the service layer we need to create first the data access objects (DAOs) manually. We do this for every new project. Through time it becomes repetitive and tedious. Gladly, Spring has a solution: the Spring Data project.

Spring Data's purpose is to provide us ready-made data access objects for various database sources. All we need to do is extend an interface and we're good to go. This means we can start writing the service immediately (if needed).

Spring Data is not a single project, but rather it's composed of many different projects specifically catering to different types of databases (see http://www.springsource.org/spring-data). Since we're using MySQL and Hibernate we will use the Spring Data JPA project.

IEventRepository.java


IEventService.java


EventService.java


A3. Controller

We have a single controller, EventController, whose main purpose is to display the Event page. It also has methods for handling CRUD operations that are ultimately delegated to the EventService.

EventController.java


A4. View

I've provided two views for displaying Event records: a DataTables version and a jQgrid version. The purpose of having two views is to demonstrate Spring's flexibility and teach various ways of presenting tabular data.

To proceed, please choose your preferred view (a specific guide will be presented):
  1. DataTables view
  2. jQgrid view

JMeter Test

The main difference between these two views are the addition of cache to the jQgrid controller. To appreciate the difference, I've provided JMeter tests to gauge each controller's performance. Take note that this tests have nothing to do with the DataTables or jQgrid plugin. The tests are written so that it will only query the controllers without generating the presentation layer.

Small dataset (9 records):

Large dataset (4300+ records):

Notice in small datasets the difference in performance is almost trivial. However, in large datasets the difference is phenomenal. Adding a cache greatly improves the application's performance (of course this assumes that the same request will be called multiple times).

Click here to download the JMeter Test. To run this test, make sure to run only one test, i.e do the DataTables first, then the jQgrid, or vice versa.

What is JMeter?
Apache JMeter is open source software, a 100% pure Java desktop application designed to load test functional behavior and measure performance. Source: http://jakarta.apache.org/jmeter/

A5. Crosscutting Concerns

As mentioned earlier, no application is free from errors. To facilitate troubleshooting, a logging mechanism needs to be added. Typically we would place the logging mechanism across our existing classes. This is a crosscutting concern.

What is a crosscutting concern?
In computer science, cross-cutting concerns are aspects of a program which affect other concerns. These concerns often cannot be cleanly decomposed from the rest of the system in both the design and implementation, and can result in either scattering (code duplication), tangling (significant dependencies between systems), or both.

For instance, if writing an application for handling medical records, the bookkeeping and indexing of such records is a core concern, while logging a history of changes to the record database or user database, or an authentication system, would be cross-cutting concerns since they touch more parts of the program. See http://en.wikipedia.org/wiki/Cross-cutting_concern

To implement a clean way of logging our application, we will take advantage of Spring's CustomizableTraceInterceptor support as seen in the Spring Data JPA reference (Appendix B. Frequently asked questions).

By default CustomizableTraceInterceptor uses trace level for logging. If we want to change the logging level, we need to extend this class and override the writeToLog() method. We have created a sub-class TraceInterceptor and change the logging level to debug

TraceInterceptor.java


After creating the class, we declare it as a bean in the XML configuration. Notice we've configured the entry and exit signature patterns and the pointcut expressions to match. In other words, this will log all services and specific controllers.

trace-context.xml


Next Section

In the next section, we will add messaging support using RabbitMQ and Spring AMQP. To proceed to the next section, click here.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 1 ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 3

Review

In the previous two sections, we've managed to create the core Event management system and integrated RabbitMQ messaging using Spring AMQP. For performing CRUD operations, we've utilized the Spring Data JPA project. In this section, we will integrate MongoDB and add error persistence.

Where am I?

Table of Contents

  1. Event Management
  2. Messaging support
  3. Error persistence
  4. Build and deploy

Error Persistence

It might be odd why we need to record errors in the application. Isn't the default logging feature enough? That depends. But for the purpose of this tutorial, we are doing it to explore MongoDB integration. There are also advantages with this approach. We can easily query and analyze our application's errors and provide a statistical view.

It's interesting that logging is the first use case listed in the MongoDB site and statistical analysis as the last well-suited use case (see MongoDB Use Cases).

We'll divide this page into five sections:
  1. C. Error Persistence
    • C1. Domain
    • C2. Service
    • C3. Aspect
    • C4. Controller
    • C5. View

C1. Domain

The domain contains a simple ErrorLog class. At the class head we've added @Document, a Spring Data MongoDB annotation, for efficiency reasons, and @Id to mark the field id as the class's identifier. If you scrutinize the application's domain classes, notice the @Id annotation in the Event.java (earlier) is from the javax.persistence package; whereas the @Id in ErrorLog.java is from the org.springframework.data.annotation package.

ErrorLog.java


C2. Service

Normally before we start developing the service layer we have to create first the data access objects (DAOs) manually. It becomes tedious as you keep repeating the same implementation. Gladly, Spring is here to rescue us from this repetitive task with Spring Data project.

Spring Data's main purpose is to provide us ready-made data access objects for various database sources. This means all we need to do is write our service to contain the business logic. And since we're using a MongoDB, we will use the corresponding Spring Data project: Spring Data MongoDB. (To see a list of other Spring Data projects, visit http://www.springsource.org/spring-data).

IErrorLogRepository.java


That's it. We're done with the service. Wait, where's the service? We don't create one since we don't have custom business logic that needs to be wrapped in a service. All we're doing is retrieval of records.

C3. Aspect

Error persistence, at its core, is no different with logging. It's a crosscutting concern. And similar with how we implemented AMQP messaging, we will use an Aspect to add error persistence.

We have declared EventMongoAspect with two pointcut expressions: one for the service and another for the controller. The interceptService() method handles and persists service errors, while the interceptController() method handles controller errors. We don't persist controller errors; instead we provide a default value so that when returning JSP pages we're not propagating stack traces to the browser.

EventMongoAspect.java


C4. Controller

The error controller is a simple controller with the single purpose of serving the error page.

ErrorController.java


C5. View

Our view is a single JSP page containing a table and an AJAX request for retrieving records. The setup is similar with the event-page.jsp (see A4. View), except we don't have dialogs for adding, editing, or deleting records.

The getRecords() function is the AJAX request responsible for retrieval and filling-in of records to the table. Then it will convert the table to a DataTables. The addition of DataTables is mainly for aesthetic purposes (and some nifty features like sorting and searching).

error-page.jsp


Result

You can preview the final output by visiting a live deployment at http://spring-mysql-mongo-rabbit.cloudfoundry.com/error


Next Section

In the next section, we will build and deploy our project using Tomcat and Jetty. To proceed, click here.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 3 ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 2

Review

In the previous section, we created the core Event management system and utilized the Spring Data JPA project to simplify data access. We've also added AJAX functionality to make the application responsive. In this section, we will integrate RabbitMQ and messaging in general.

Where am I?

Table of Contents

  1. Event Management
  2. Messaging support
  3. Error persistence
  4. Build and deploy

Messaging Support

Our application is capable of broadcasting events as simple text messages. These messages are CRUD actions and exceptions that arise during the lifetime of the application. This means if a user performs an add, edit, delete, or get these actions will be published to a message broker. If there are any exceptions, we will also publish them.

Why do we need to publish these events? First, it helps us study and explore RabbitMQ messaging. Second, we can have a third-party application whose sole purpose is to handle these messages for intensive statistical analysis. Third, it allows us to monitor in real-time and check the status of our application instantaneously.

If you're unfamiliar with messaging and its benefits, I suggest visiting the following links:

We'll divide this page into four sections:
  1. B. Messaging Support
    • B1. Aspect
    • B2. Configuration
    • B3. Controller
    • B4. View

B1. Aspect

We will publish CRUD operations as simple messages. It's like logging except we send the logs to a message broker. Usually we would add this feature across existing classes. Unfortunately, this leads to "scattering" and " tangling" of code. No doubt--it's a crosscutting concern. We have the same scenario when added the logging feature earlier (See A5. Crosscutting Concerns section earlier).

We have created an Aspect, EventRabbitAspect.java, to solve this concern. To send messages, we use the AmqpTemplate where we pass the exchange, routing key, and the message. Since we want to publish messages as they are called and also errors as they happened, we use @Around to capture these events. The proceeding code is a variation of the original tutorial Chatting in the Cloud: Part 1 by Mark Fisher (http://blog.springsource.com/2011/08/16/chatting-in-the-cloud-part-1/)

EventRabbitAspect.java


In order for Spring to recognize this aspect, make sure to declare the following element in your XML configuration (we've done this in the trace-context.xml):



B2. Configuration

After declaring the Aspect, we now declare and configure the RabbitMQ and Spring AMQP specific settings. In fact, you will soon discover that most of the work with Spring AMQP is configuration-related: declaration of queues, bindings, exchanges, and connection settings.

We've declared two queues: eventQueue for normal events, and errorQueue for errors. We have a single exchange, eventExchange where we declare the bindings for the two queues.

In order to send messages to the eventQueue, we set the routing key to event.general.*. Likewise, to send messages to the errorQueue, we set the routing key to event.error.*. For a tutorial on these concepts, please visit the official examples at http://www.rabbitmq.com/getstarted.html

spring-rabbit.xml


B3. Controller

After configuring RabbitMQ and Spring AMQP, we declare a controller, aptly named MonitorController. It's main purpose is to handle monitoring requests. This controller is based on Chatting in the Cloud: Part 1 blog by Mark Fisher (http://blog.springsource.com/2011/08/16/chatting-in-the-cloud-part-1/).

MonitorController.java


B4. View

We have two JSP pages event-monitor-page.jsp and error-monitor-page.jsp for event and error views respectively. We've utilized AJAX to pull information from the application. Again, this is based on Chatting in the Cloud: Part 1 blog by Mark Fisher (http://blog.springsource.com/2011/08/16/chatting-in-the-cloud-part-1/).

event-monitor-page.jsp


error-monitor-page.jsp


Result

You can preview the final output by visiting our live app at http://spring-mysql-mongo-rabbit.cloudfoundry.com/monitor/event


Next Section

In the next section, we will integrate MongoDB and add error persistence to the current application. To proceed to the next section, click here.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 2 ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 1: DataTables View

Review

In the previous section, we created the core Event management system. In this section, we will work on the View layer. Data will be presented in a table. We will use DataTables, a jQuery plugin, and a custom JavaScript function to provide advance features to our table like sorting and searching.

Where am I?

Table of Contents

  1. Event Management
  2. Messaging support
  3. Error persistence
  4. Build and deploy

DataTables

What is DataTables?
DataTables is a plug-in for the jQuery Javascript library. It is a highly flexible tool, based upon the foundations of progressive enhancement, which will add advanced interaction controls to any HTML table. (Source: http://datatables.net/)

Before we proceed with the development, let's preview the final output:

Development

Since we've already discussed the controller and service classes in the previous section, we just need to discuss the JSP pages. We actually have five JSP pages:
  1. Primary page
  2. Supporting pages
    • add-dialog.jsp
    • edit-dialog.jsp
    • delete-dialog.jsp
    • generic-dialog.jsp

1. Primary page

The primary page contains the main view. It's a single page containing the following sections:
  1. URLs
  2. Imports
  3. Menu
  4. Table
  5. Dialogs
  6. Conversion of links to buttons
  7. Attaching link functions
  8. Retrieval of records and conversion to DataTables

event-page.jsp


Let's discuss each section:

a. URLs
The following section declares two URLs which uses the JSTL core tag: the root and the resources URLs respectively. These URLs are here for reusability purposes:



b. Imports
The following section imports a number of CSS and JavaScript resources which includes the core jQuery library, the DateJS library (a Date utility, http://www.datejs.com/), DataTables (a jQuery plugin, http://datatables.net/), and a custom jQuery plugin for retrieving records via AJAX and inserting records to a table automatically:



c. Menu
The following section declares a menu list:



d. Table
The following section creates an empty table and three HTML links (controller links) for adding, editing, and deleting of records. Take note of the table id, eventTable, because this id will be referenced multiple times:



e. Dialogs
The following section includes four external JSPs. The first three JSPs contain form elements for adding, editing, and deleting of records respectively. The fourth dialog is used for displaying generic messages.



f. Conversion of links to buttons
The following section converts the previous three links to a button. This is mainly for aesthetic purposes:



g. Attaching link functions
The following section attaches a function to our controller buttons. Each function will trigger a dialog box. These dialog boxes are the four dialog JSPs we included earlier:



h. Retrieval of records and conversion to DataTables
The following section calls a custom getRecords() function which will retrieve Event records, populate our table with data, and convert the table to DataTables:



If you want to disable DataTables, just change the previous function to the following:



Results

When we run the application, the result should be similar to the following image (this is an actual screenshot taken from a live deployment):


Limitations

Our DataTables page has some limitations. However, these are not DataTables limitations but rather something that we intentionally (and unintentionally) did not implement:
  • The status "Showing 1 to 4 Entries" has a bug when adding or deleting a record. You need to refresh the whole page to show the correct status
  • Date conversion is in integer format instead of Date
  • UI validation is not implemented

Playground

Some developers might not have time to build the entire project. Maybe they just want something to play around really fast. Because of that, I've deployed live samples to Cloud Foundry and added sample fiddles via JSFiddle.

JSFiddle

If you want to explore more about DataTables, I've provided fiddles for you to play around. These fiddles do not need any server-side programs to run. Feel free to fork them.

Here are the fiddles:
  • Plain table with static data: http://jsfiddle.net/krams/Us9S5/
  • Plain table with dynamic data: http://jsfiddle.net/krams/jD67t/
  • Add form: http://jsfiddle.net/krams/8QKAe/
  • Edit form: http://jsfiddle.net/krams/Kf4MF/
  • Full table with DataTables and buttons: http://jsfiddle.net/krams/9Syqc/

What is JSFiddle?
JsFiddle is a playground for web developers, a tool which may be used in many ways. One can use it as an online editor for snippets build from HTML, CSS and JavaScript. The code can then be shared with others, embedded on a blog, etc. Using this approach, JavaScript developers can very easily isolate bugs. We aim to support all actively developed frameworks - it helps with testing compatibility - Source: http://doc.jsfiddle.net/

Cloud Foundry

If you want to tinker with a live deployment, I suggest you visit the application's live site at http://spring-mysql-mongo-rabbit.cloudfoundry.com/event

What is Cloud Foundry?
Cloud Foundry is the open platform as a service project initiated by VMware. It can support multiple frameworks, multiple cloud providers, and multiple application services all on a cloud scale platform.

Next Section

In the next section, we will explore jQgrid, a jQuery plugin, for displaying tabular data. Read next.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 1: DataTables View ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 4

Review

In the previous four sections, we've managed to create the core Event management system, integrate messaging via RabbitMQ, and add error persistence via MongoDB. We've also explored DataTables and jQgrid for presenting tabular data. In this section, the final section, we will build and deploy our project.

Where am I?

Table of Contents

  1. Event Management
  2. Messaging support
  3. Error persistence
  4. Build and deploy

Build and deploy

Cloud Foundry Deployment

Before we build and deploy the project, it is worth visiting first the live application as deployed in the cloud. To access the live app, visit the following url:

http://spring-mysql-mongo-rabbit.cloudfoundry.com

When you run the application for the first time, you might encounter some unexpected results that's because there's a well-known bug when using the JSTL tag c:url. The session id is attached on all URLs! Therefore, the resources don't display as expected. Refreshing the page should quickly resolve this issue. There are workarounds but I don't want to distract my readers from this issue. This is discussed and documented at stackoverflow.com (read it here).

If you're using SpringSource Tool Suite (STS), you can deploy your own app to Cloud Foundry for free! If you need instructions on how to deploy to Cloud Foundry, please check the following resources:

What is STS?
SpringSource Tool Suite™ (STS) provides the best Eclipse-powered development environment for building Spring-powered enterprise applications. STS supplies tools for all of the latest enterprise Java, Spring, Groovy and Grails based technologies as well as the most advanced tooling available for enterprise OSGi development. Source: http://www.springsource.com/developer/sts

What is Cloud Foundry?
Cloud Foundry is the open platform as a service project initiated by VMware. It can support multiple frameworks, multiple cloud providers, and multiple application services all on a cloud scale platform. Source: http://www.cloudfoundry.com/

Localhost Deployment

Before you can deploy the application locally, you need to ensure that the following services are running:
  • MySQL
  • MongoDB
  • RabbitMQ

If you need help on how to download install these services, please visit the FAQs section (at the beginning of this guide).

Create the Database

If all required services are running, go to MySQL and create a new database eventdb. For MongoDB and RabbitMQ, no further configuration is needed because their "databases" will be created during the application's startup. Here's a snippet of the application's db properties:

spring.properties


Run Maven, Deploy to Tomcat

After creating the MySQL database, we can now build the application. Because the application is a Maven project, we can easily build and deploy the application, either to Tomcat or Jetty server.

To build and deploy the application to Tomcat, run the following Maven command: mvn tomcat:run

This will build the project and deploy it in an embedded Tomcat server. To access the application's main page, open your browser and enter the following URL: http://localhost:8080/spring-jpa-mongo-rabbit/. This assumes Tomcat is running under port 8080, and you're using the latest Tomcat Maven plugin:



If the plugin version from org.apache.tomcat.maven will not work (I actually had difficulty using that version), I suggest using the org.codehaus.mojo version:



If successful, you should see the following output in the terminal:
[INFO] Running war on http://localhost:8080/spring-mysql-mongo-rabbit
[INFO] Using existing Tomcat server configuration at /home/Desktop/downloads/spring-mysql-mongo-rabbit/target/tomcat
09 16, 11 10:19:14 PM org.apache.catalina.startup.Embedded start
INFO: Starting tomcat server
09 16, 11 10:19:14 PM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.29
09 16, 11 10:19:14 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
09 16, 11 10:19:18 PM org.apache.coyote.http11.Http11Protocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
09 16, 11 10:19:18 PM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080

For details, see the following resources:
  • http://tomcat.apache.org/maven-plugin-2.0-SNAPSHOT/tomcat-maven-plugin/index.html (new)
  • http://mojo.codehaus.org/tomcat-maven-plugin/index.html (old)

Run Maven, Deploy to Jetty

If you prefer Jetty instead, run the following Maven command: mvn jetty:run

This will build the project and deploy it in an embedded Jetty server. To access the application's main page, open your browser and enter the following URL: http://localhost:8080. This assumes Jetty is running under port 8080, and you're using Jetty 7 Maven plugin:



If successful, you should see the following output in the terminal:
2011-09-16 22:20:48.950:INFO:/:Initializing Spring root WebApplicationContext
2011-09-16 22:20:52.688:INFO:oejsh.ContextHandler:started o.m.j.p.JettyWebAppContext{/,file:/home/Desktop/downloads/spring-mysql-mongo-rabbit/src/main/webapp/},file:/home/Desktop/downloads/spring-mysql-mongo-rabbit/src/main/webapp/
2011-09-16 22:20:52.739:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8080 STARTING
[INFO] Started Jetty Server

For details, see the following resources:
  • http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin (new)
  • http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin (old)

Maven Caveats

When building our project, you might get exceptions pertaining to missing hibernatePersistenceUnit. This is used by the Spring Data JPA project and located under the src/main/java/META-INF folder:


By default, Maven will not copy this file when building the project. You have to manually instruct Maven to do such. There are various Maven plugins for copying external resources. Among these Maven plugins, I found the Maven-copy-plugin the best. For more info about this plugin, check out http://evgeny-goldin.com/wiki/Maven-copy-plugin

Here's the plugin declaration:


Conclusion

That's it. We have successfully integrated MySQL, MongoDB, and RabbitMQ in a single Spring MVC application. With Spring Data we have greatly reduced the data access layer to simple interfaces, and with Spring AMQP, we are able to integrate RabbitMQ without any difficulty. We've also explored various jQuery plugins for presenting tabular data.

Download the project
You can download the source code as a Maven project at GitHub at https://github.com/krams915/spring-mysql-mongo-rabbit-integration

Click the Downloads button at the upper-right corner to begin downloading. Or you can fork the source and start hacking with it.

If you need IDE support for exploring Git repos, use SpringSource Tool Suite (STS).

If you want to learn more about Spring and integration with various technologies, please visit the Tutorials section.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 4 ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 1: jQgrid View

Review

In the previous section, we've managed to create the core Event management system and use DataTables to display tabular data. In this section, we will use jQgrid, a jQuery plugin, to provide advance features to our table like sorting and searching.

Where am I?

Table of Contents

  1. Event Management
  2. Messaging support
  3. Error persistence
  4. Build and deploy

jQgrid View

As mentioned in the previous section, we will present tabular data using jQgrid and we'll add caching functionality to improve the application's performance. We'll utilize Spring Cache as our abstraction tool, and Ehcache as our cache storage.

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.
jqGrid uses a jQuery Java Script Library and is written as plugin for that package. (Source: http://www.trirand.com/jqgridwiki/doku.php)

What is Ehcache?
Ehcache is an open source, standards-based cache used to boost performance, offload the database and simplify scalability. Ehcache is robust, proven and full-featured and this has made it the most widely-used Java-based cache. Source: http://ehcache.org/

Before we proceed with the development, let's preview the final output:

Development

Since we'll be adding caching functionality, we need to provide a custom controller, and since jQgrid requires a specific JSON format, we need to create a custom DTO. We shall divide this page as follows:
  1. Data Transfer Object (DTO)
  2. Controller
  3. JSP page

1. Data Transfer Object (DTO)

jQgrid can exchange and communicate data via different formats: XML, JSON, Arrays, and etc. We will use JSON as our data-interchange format because it's lightweight and flexible. In order for our JSON format to work, we need to create a custom data transfer object (DTO) that matches our jQgrid's JSON reader property.

Below is our jQgrid JSON reader declaration:


We have to match those fields in our DTO (for an explanation of those fields, read the comments in the DTO). Consequently, we have the following class:



2. Controller

Next we will create a new controller to handle jQgrid-related requests with caching functionality:



We are re-using the same EventService for the DataTables. The methods for adding, editing, and deleting are exact copies of the EventController for the DataTables as well.

There are two unique methods here: the getEventPage() and the getAll(). The getEventPage() returns a JSP page containing a jQgrid table. The getAll() is a little-bit involved since it needs to wrap the results in a DTO, but nonetheless, it's quite straightforward.

We've also annotated the CRUD methods with two Java annotations: @Cacheable and @CacheEvict to add caching functionality. Notice how easy it is to add cache to our existing application.

To highlight the difference, I suggest comparing the DataTables and jQgrid version and monitor the calls to EventService via the Event Monitor page (part of the application's feature). Only the DataTables will show calls to readAll().

What is @Cacheable?
@Cacheable is used to demarcate methods that are cacheable - that is, methods for whom the result is stored into the cache so on subsequent invocations (with the same arguments), the value in the cache is returned without having to actually execute the method. Source: Spring Reference 3.1.0.M1

What is @CacheEvict?
@CacheEvict demarcates methods that perform cache eviction, that is methods that act as triggers for removing data from the cache. Just like its sibling, @CacheEvict requires one to specify one (or multiple) caches that are affected by the action, allows a key or a condition to be specified but in addition, features an extra parameter allEntries which indicates whether a cache-wide eviction needs to be performed rather then just an entry one Source: Spring Reference 3.1.0.M1

3. JSP page

Now, let's examine the JSP page. It's a single page containing the following sections:
  1. URLs
  2. Imports
  3. Menu
  4. Table
  5. jQgrid initialization
  6. Pager functions
    1. Add function
    2. Edit function
    3. Delete function

event-page.jsp


Let's discuss each section:

a. URLs
The following section declares two URLs which uses the JSTL core tag: the root and the resources URLs respectively. These URLs are here for reusability purposes:



b. Imports
The following snippet imports a number of CSS and JavaScript resources which includes the core jQuery library, the DateJS library (a Date utility, http://www.datejs.com/), and the jQgrid plugin (http://www.trirand.com/blog/):



c. Menu
The following section declares a menu list:



d. Table
The following section declares a div with two inner elements: a table and a div for attaching the jQgrid and the control buttons respectively:



e. jQgrid initialization
The following section initializes the jQgrid table. The function declares the table properties, column models, url where to retrieve the data, and control buttons to display in the pager section:



f. Pager functions

1. Add function
The following section attaches a function to the Add button in the jQgrid pager section:



2. Edit function
The following snippet attaches a function to the Edit button in the jQgrid pager section:



3. Delete function
The following section attaches a function to the Delete button in the jQgrid pager section:



Results

When we run the application, the result should be similar to the following image (this is an actual screenshot taken from a live deployment):


Limitations

Our jQgrid view has some limitations. However, these are not jQgrid limitations but rather something that we intentionally (and unintentionally) did not implement:
  • Search feature is not implemented
  • Sort feature is not implemented
  • UI validation is not fully implemented

Playground

Some developers might not have time to build the entire project. Maybe they just want something to play around really fast. Because of that, I've deployed live samples to Cloud Foundry and added sample fiddles via JSFiddle.

JSFiddle

If you want to explore more about jQgrid, I've provided a fiddle for you to play around. This fiddle do not need any server-side programs to run. Feel free to fork it.

Here's the fiddle: http://jsfiddle.net/krams/jqJch/

What is JSFiddle?
JsFiddle is a playground for web developers, a tool which may be used in many ways. One can use it as an online editor for snippets build from HTML, CSS and JavaScript. The code can then be shared with others, embedded on a blog, etc. Using this approach, JavaScript developers can very easily isolate bugs. We aim to support all actively developed frameworks - it helps with testing compatibility - Source: http://doc.jsfiddle.net/

Cloud Foundry

If you want to tinker with a live deployment, I suggest you visit the application's live site at http://spring-mysql-mongo-rabbit.cloudfoundry.com/jqgrid/event

What is Cloud Foundry?
Cloud Foundry is the open platform as a service project initiated by VMware. It can support multiple frameworks, multiple cloud providers, and multiple application services all on a cloud scale platform.

Next Section

In the next section, we will add messaging support using RabbitMQ and Spring AMQP. Read next.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring MVC: Integrating MySQL, MongoDB, RabbitMQ, and AJAX - Part 1: jQgrid View ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share