Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Wednesday, June 20, 2012

File Upload with Spring and jQuery (Part 1)

Introduction

In this article, we will study how to do file uploads with Spring and jQuery. We will learn how to attach multiple files and use the jQuery-File-Upload plugin to provide a seamless file upload experience.


Dependencies


Github

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

Functional Specs

Let's define our application's requirements:
  • Create a simple form where users can upload multiple files
  • Users should be able to add an owner name and description for each upload
  • Provide an AJAX-like experience

Here's our Use Case diagram:


[User]-(Add files)
[User]-(Upload)

File Upload Strategy
To achieve an AJAX-like experience we have to resort to a different strategy when uploading and sending form data. Instead of sending all form data in one go, we will upload the file separately (behind the scenes without user intervention).

Here are the steps:
  1. User fills-in the form's text inputs, i.e owner and description
  2. User clicks on "Add a file" link. Browsers for a file and attaches it
  3. Behind the scene, the form uploads the file to the server. The server saves the file and returns the file details, i.e filename and file size
  4. User clicks on "Upload" button. The form does a POST action to send the form data. But it never sends the file itself. Instead it sends the filename that was saved by the server. The user is tricked into thinking that the file hasn't been uploaded yet.

Screenshots

Let's preview how our application will look like after it has been completed. This is also a good way to clarify further our application's specs

This is the entry page where users can upload files. Users are allowed to attach multiple files.


Upload Form

When attaching multiple files, this is the expected output.


Multiple files attachment

This alert shows whenever files have been successfully uploaded.


Successful upload alert

This alerts shows whenever files have failed to be uploaded.


Form fields cleared alert

Next

In the next section, we will 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: File Upload with Spring and jQuery (Part 1) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

File Upload with Spring and jQuery (Part 2)

Review

In the previous section, we have laid down the functional specs of the application. In this section, we will start writing the Java classes and discuss the project's structure.


Project Structure

Our application is a Maven project which means our project follows the Maven structure.

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





Domain Layer

The domain layer contains a Message class that is used as a container to hold file details.

Message.java


The domain layer also contains an UploadedFile class which is used for sending file information after it has been processed by the controller.

UploadedFile.java


Controller Layer

The controller layer contains a simple controller that serves a form for uploading files. There are two important endpoints here:
  • /message - processes the file descriptions
  • /file - receives the files themselves

To simplify this tutorial, we're not persisting the messages and files in a database or to the disk.

UploadController.java


Others

StatusResponse is used to determine the status of a request, and includes an error message if any.

StatusResponse.java


Next

We've completed writing our Java classes. In the next section, we will start writing the configuration files. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: File Upload with Spring and jQuery (Part 2) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

File Upload with Spring and jQuery (Part 3)

Review

In the previous section, we have implemented the Java classes. In this section, we will start writing the configuration files.


Configuration

To complete our application, here are the important configuration files that needs to be declared:
  • applicationContext.xml
  • spring-servlet.xml
  • web.xml

applicationContext.xml
Pay attention to the CommonsMultipartResolver and the MappingJacksonJsonView.
  • The CommonsMultipartResolver is a requirement for processing MultipartFile files
  • The MappingJacksonJsonView is required for serializing JSON responses properly. The extractValueFromSingleKeyModel is meant to remove the wrapper object when responding with single key model (see the Stack Overflow link for details).


spring-servlet.xml


web.xml


Next

In the next section, we will discuss the HTML form for uploading files. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: File Upload with Spring and jQuery (Part 3) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

File Upload with Spring and jQuery (Part 4)

Review

In the previous section, we have written the configuration files. In this section, we will write the HTML form for uploading files.


To achieve a seamless AJAX-like file upload experience, we will be using blueimp's jQuery-File-Upload plugin for jQuery.

What is jQuery-File-Upload?

File Upload widget with multiple file selection, drag&drop support, progress bars and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.

Source: https://github.com/blueimp/jQuery-File-Upload

To test-drive this plugin, please visit the following demos:

For our purposes, we will follow the minimal setup guide, so that we can create our custom UI and eliminate extraneous steps.

Warning!
Make sure to test the plugin on different browsers. Not all browsers behave the same way. In my opinion, Chrome and Firefox are the best for development.

Html Form

Here's our upload form again:

Upload Form

Here's the full source:



Let's dissect this source and make sense of it.

Endpoint Urls
We've declared two global urls: messageUploadUrl and fileUploadUrl. These are the endpoints for uploading messages and files respectively.



Import Scripts
Based on the jQuery-File-Upload basic plugin guide, we need to import the following scripts: jquery.ui.widget.js, jquery.iframe-transport.js, and jquery.fileupload.js. The util.js contains a method for posting JSON objects. The remaining scripts are for the jQuery framework itself.



Initialization Function
This function contains the following initialization steps:
  • Beautify buttons
  • Attach submit function
  • Attach clear function
  • Attach file upload function
  • Initialize filelist data



File Display Function
This is used for formatting filenames. The output is similar to the following: filename (256.50K)



File List Function
This is used to retrieved the list of filenames. The output is comma-delimited, which is similar to the following: filename1.jpg,filename2.doc,filename3.txt



Dialog Function
This is a helper function for displaying dialog boxes.



Clear Function
This clears the form of its contents.



Form
This is the form itself. Notice we've set the file input's opacity to zero to hide it and make it work under Safari and Opera (try removing the opacity and hide the file input via display:none to see an unwanted effect).



By setting the file input's opacity to 0, we have successfully hidden the input. But how do we access it now? Notice the "Add a file" link? We've attached a click trigger function on that link to fire up the file input. If we removed the opacity, here's what we will see:

Chrome 19.0.1084.56


Firefox 9.0.1


Internet Explorer 9.0.8112.16421


Browser Bugs

Unfortunately, even though the jQuery-File-Upload plugin has great cross-browser support, HTML5 and traditional, there are still bugs and unwanted behavior. Maybe it's a configuration issue or a browser issue. In other words, always tests before you deploy to production. Here's what I've discovered so far:

Internet Explorer 9.0.8112.16421
  • Does not upload file
  • Does not upload message

Opera 11.60
  • Attach link does not work if file input has display:none
  • To make it work, set the opacity instead

Safari 5.1.2
  • Attach link does not work if file input has display:none
  • To make it work, set the opacity instead

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: File Upload with Spring and jQuery (Part 4) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

File Upload with Spring and jQuery (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)

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-fileupload-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-fileupload-tutorial
    Jun 20, 2012 8:35:14 PM org.apache.catalina.startup.Embedded start
    INFO: Starting tomcat server
    Jun 20, 2012 8:35:14 PM org.apache.catalina.core.StandardEngine start
    INFO: Starting Servlet Engine: Apache Tomcat/6.0.29
    Jun 20, 2012 8:35:15 PM org.apache.catalina.core.ApplicationContext log
    INFO: Initializing Spring root WebApplicationContext
    Jun 20, 2012 8:35:17 PM org.apache.coyote.http11.Http11Protocol init
    INFO: Initializing Coyote HTTP/1.1 on http-8080
    Jun 20, 2012 8:35:17 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-fileupload-tutorial/upload

Attach a file

  1. Click on "Add a file"
  2. Browse for a file and add it. Check the logs and you should see something similar to the following:
    [DEBUG] [tomcat-http--24 02:15:20] (TraceInterceptor.java:writeToLog:21) Entering UploadController.upload(org.springframework.web.multipart.commons.CommonsMultipartFile@d1258b)
    [DEBUG] [tomcat-http--24 02:15:20] (UploadController.java:upload:43) Writing file to disk...done
    [DEBUG] [tomcat-http--24 02:15:20] (TraceInterceptor.java:writeToLog:21) Leaving UploadController.upload(): [UploadedFile [name=Tulips.jpg, size=620888, url=http://localhost:8080/spring-fileupload-tutorial/resources/Tulips.jpg, thumbnail_url=null, delete_url=null, delete_type=null]]
    

Attach multiple files

  1. Click on "Add another file"
  2. Browse for files and add them. Check the logs and you should see something similar to the following:
    [DEBUG] [tomcat-http--26 02:15:42] (TraceInterceptor.java:writeToLog:21) Entering UploadController.upload(org.springframework.web.multipart.commons.CommonsMultipartFile@7783ea)
    [DEBUG] [tomcat-http--26 02:15:42] (UploadController.java:upload:43) Writing file to disk...done
    [DEBUG] [tomcat-http--26 02:15:42] (TraceInterceptor.java:writeToLog:21) Leaving UploadController.upload(): [UploadedFile [name=Hydrangeas.jpg, size=595284, url=http://localhost:8080/spring-fileupload-tutorial/resources/Hydrangeas.jpg, thumbnail_url=null, delete_url=null, delete_type=null]]
    [DEBUG] [tomcat-http--27 02:15:42] (TraceInterceptor.java:writeToLog:21) Entering UploadController.upload(org.springframework.web.multipart.commons.CommonsMultipartFile@85ec1b)
    [DEBUG] [tomcat-http--27 02:15:42] (UploadController.java:upload:43) Writing file to disk...done
    [DEBUG] [tomcat-http--27 02:15:42] (TraceInterceptor.java:writeToLog:21) Leaving UploadController.upload(): [UploadedFile [name=Jellyfish.jpg, size=775702, url=http://localhost:8080/spring-fileupload-tutorial/resources/Jellyfish.jpg, thumbnail_url=null, delete_url=null, delete_type=null]]
    

Upload the files

  1. Click on "Upload". Check the logs and you should see something similar to the following:
    [DEBUG] [tomcat-http--30 02:16:20] (TraceInterceptor.java:writeToLog:21) Entering UploadController.message(Message [owner=John Smith, description=These are my files. I owned them., filename=Tulips.jpg,Hydrangeas.jpg,Jellyfish.jpg])
    [DEBUG] [tomcat-http--30 02:16:20] (UploadController.java:message:33) Service processing...done
    [DEBUG] [tomcat-http--30 02:16:20] (TraceInterceptor.java:writeToLog:21) Leaving UploadController.message(): StatusResponse [success=true, message=Message received, ]
    

Note:

When adding a file via the "Add a file" link, the file is automatically uploaded to the backend. The backend responds with an object containing the filename (and other file details). When you click on the "Upload" button, the form data is sent along with the filename. The file itself is never uploaded in this second step because it's already in the server!

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-fileupload-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 file upload application with Spring and jQuery-File-Upload plugin. We've learned how to setup an HTML form for file uploads with AJAX-like experience.

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 June 20 2012 Uploaded tutorial
2 June 26 2012 Corrected wrong entry url
3 June 27 2012 Corrected wrong entry url again

StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: File Upload with Spring and jQuery (Part 5) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Monday, June 18, 2012

Email with Spring and SendGrid (Part 1)

Introduction

In this article we will study how to send email with Spring by integrating with SendGrid's email service. Instead of the usual SMTP, we will use HTTP to communicate with SendGrid.


Dependencies


Github

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

Functional Specs

Let's define our application's requirements:
  • Create a simple form where users can compose and send emails
  • Emails do not need to be persisted in a database
  • Send email via HTTP instead of SMTP to avoid firewall issues

Here's our Use Case diagram:


[User]-(Compose)
[User]-(Send)

In MVC terms, we decompose the application as follows:
  • Model: A simple Map object that conforms with SendGrid's message format
  • View: An HTML-based form where users can compose and send emails
  • Controller: Spring controller that receives the request. The controller delegates actual work to the service layer which eventually executes an HTTP call to send email to SendGrid.

What is SendGrid?

SendGrid's cloud-based email infrastructure relieves businesses of the cost and complexity of maintaining custom email systems. SendGrid provides reliable delivery, scalability and real-time analytics along with flexible API's that make custom integration a breeze.

Source: http://www.sendgrid.com

Why SendGrid?
  1. It's easy to integrate with.
  2. It has a free plan that allows 200 email messages per day.
  3. SendGrid has an HTTP API for sending emails which is very simple to use.

Screenshots

Let's preview how our application will look like after it has been completed. This is also a good way to clarify further our application's specs

This is the entry page where users can compose and send emails.

Compose Email Form

After clicking "Send", the email message is sent. An alert is shown to confirm the action.

Sent alert

When user clicks on "Reset", the contents of the fields are cleared. An alert is shown to confirm the action.

Fields cleared alert

Email Messages
This is the sample email received from Gmail. Notice Gmail is able to show that this email was sent via SendGrid.

Gmail email


email details

This is the sample email received from Yahoo.

Yahoo email

Next

In the next section, we will show how to sign-up with SendGrid's email service. This is required before we can start sending emails. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Email with Spring and SendGrid (Part 1) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Email with Spring and SendGrid (Part 2)

Review

In the previous section, we have laid down the functional specs of the application . In this section, we will demonstrate how to sign-up with SendGrid's email service. This is required so that we can integrate with their service.

Disclaimer

SendGrid manually approves each account. It takes almost a day before they can approve your account. If it takes longer, I suggest sending an email to their tech support.


1. Go to SendGrid's page at http://www.sendgrid.com


2. Click on "Pricing" and scroll-down.


3. At the bottom portion of the page, there's a link to the "Free Plan". Click it.


4. The account creation page is displayed. Fill-in the details. Then submit your application. Remember your username and password here. These will be your API username and key.


5. You will be redirected to the "Get Started" page. Complete all the required actions. Notice your account is on provision. It might take a day for it to be approved.


Account Completion
Once your account has been provisioned, visit your SendGrid account page



SendGrid API

SendGrid offers numerous APIs to allow developers to fully integrate with their service. They have the following APIs:
  • Customer Subuser API
  • Event API
  • Parse API
  • Web API
  • SMTP API
  • Reseller API
  • Newsletter API

We will focus on the Mail module, which is under the Web API. Please see http://docs.sendgrid.com/documentation/api/web-api/mail/#send for the complete documentation.

To test the Mail module, you can either use your browser or CURL (if you're familiar with it).

Browser-based test:
https://sendgrid.com/api/mail.send.xml?api_user=youremail@domain.com&api_key=secureSecret&to=destination@example.com&toname=Destination&subject=Example%20Subject&text=testingtextbody&from=info@domain.com

CURL-based test:
curl -d 'to=destination@example.com&toname=Destination&subject=Example Subject&text=testingtextbody&from=info@domain.com&api_user=sendgridUsername&api_key=sendgridPassword' https://sendgrid.com/api/mail.send.json

But how do we use the Web API via Java and Spring? We will discuss that on the next section. But to satisfy your inquisitive minds, here's a preview:



Next

In the next section, we will start writing the Java classes and discuss the SendGrid API. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Email with Spring and SendGrid (Part 2) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Email with Spring and SendGrid (Part 3)

Review

In the previous section, we have learned how to sign-up with SendGrid's free plan. In this section, we will start writing the Java classes and discuss the project's structure.


Project Structure

Our application is a Maven project which means our project follows the Maven structure.

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





Domain Layer

The domain layer contains a Message class that represents an email message.



Controller Layer

The controller layer contains a simple controller that serves a form for composing and sending emails. It also contains a send method that accepts a Message object. The controller delegates the sending part to an email service.


Service Layer

The service layer contains the email service. We have a simple interface EmailService for sending messages.


The actual implementation SendGridEmailService relies on RestTemplate to send the email message via HTTP as a POST method.


Utility Layer

This layer contains helper classes and interfaces. Here we've extracted the required SendGrid parameters for sending emails via HTTP. Please refer to Part 2 of this guide if you need to review the SendGrid Web API.


View Layer

The view layer contains a simple html form for composing and sending email messages. One important section here that needs to be discussed is the usage of the postJSON plugin.

jQuery plugin

postJSON is a jQuery plugin that allows sending of JSON objects via POST. This plugin is based a plugin I found at the jQuery plugin repository. Unfortunately, the location doesn't seem to exist anymore. Also, I've made some modifications with the plugin (see the comments).


Next

We've completed writing our Java classes. In the next section, we will start writing the configuration files. Click here to proceed.

StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Email with Spring and SendGrid (Part 3) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Email with Spring and SendGrid (Part 4)

Review

In the previous section, we have implemented the Java classes. In this section, we will start writing the configuration files to complete our Spring application.


Configuration

To complete our application, here are the important configuration files that needs to be declared:
  • spring.properties
  • applicationContext.xml
  • spring-servlet.xml
  • web.xml

The spring.properties file contains the SendGrid user and key values to access the Web API. This is equivalent to your SendGrid's username and password.


applicationContext.xml


spring-servlet.xml


web.xml


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: Email with Spring and SendGrid (Part 4) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Email with Spring and SendGrid (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)

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-sendgrid-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-sendgrid-tutorial
    Jun 18, 2012 10:27:47 PM org.apache.catalina.startup.Embedded start
    INFO: Starting tomcat server
    Jun 18, 2012 10:27:47 PM org.apache.catalina.core.StandardEngine start
    INFO: Starting Servlet Engine: Apache Tomcat/6.0.29
    Jun 18, 2012 10:27:48 PM org.apache.catalina.core.ApplicationContext log
    INFO: Initializing Spring root WebApplicationContext
    Jun 18, 2012 10:27:49 PM org.apache.coyote.http11.Http11Protocol init
    INFO: Initializing Coyote HTTP/1.1 on http-8080
    Jun 18, 2012 10:27:49 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-sendgrid-tutorial/email

Send an email

  1. Compose and email
  2. Send it. You should see within the logs an output similar to the following:
    [DEBUG] [tomcat-http--23 04:25:03] (TraceInterceptor.java:writeToLog:21) Entering EmailController.send(org.krams.domain.Message@486d1d)
    [DEBUG] [tomcat-http--23 04:25:03] (TraceInterceptor.java:writeToLog:21) Entering SendGridEmailService.send(org.krams.domain.Message@486d1d)
    [DEBUG] [tomcat-http--23 04:25:04] (TraceInterceptor.java:writeToLog:21) Leaving SendGridEmailService.send(): StatusResponse [success=true, message=Message sent, ]
    [DEBUG] [tomcat-http--23 04:25:04] (TraceInterceptor.java:writeToLog:21) Leaving EmailController.send(): StatusResponse [success=true, message=Message sent, ]
    

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-sendgrid-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 email application with Spring and SendGrid integration. We've learned how to setup a SendGrid account and how to utilize its Web API via Spring's RestTemplate.

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 June 18 2012 Uploaded tutorial


StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Email with Spring and SendGrid (Part 5) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Thursday, March 8, 2012

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

Introduction

In this tutorial, we will create a simple CRUD application using Spring 3.1 and Neo4j. We will based this tutorial on a previous guide for MongoDB. This means we will re-use our existing design and implement only the data layer to use Neo4j as our data store.


Dependencies

  • Spring core 3.1.0.RELEASE
  • Spring Data Neo4j 2.1.0.M1
  • Neo4j Kernel 1.6
  • Neo4j Cypher 1.6
  • Neo4j Cypher DSL 1.6
  • 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 specification as follows:
  • A CRUD page for managing users
  • Use AJAX to avoid page refresh
  • Users have roles: 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 Neo4j and Spring Data Neo4j and coming from a SQL-background, please take some time to read the following references:

In its simplest form, Neo4j is a NoSQL graph database containing nodes and relationships.

What is Neo4j?

The Neo4j data model consists of nodes and relationships, both of which can have key/value-style properties. What does that mean, exactly? Nodes are the graph database name for records, with property keys instead of column names. That's normal enough. Relationships are the special part. In Neo4j, relationships are first-class citizens, meaning they are more than a simple foreign-key reference to another record, relationships carry information.

Source: Spring Data Neo4j - Chapter 4. Learning Neo4j

What is a Graph database?

A graph database stores data in a graph, the most generic of data structures, capable of elegantly representing any kind of data in a highly accessible way.

“A Graph —records data in→ Nodes —which have→ Properties”

“Nodes —are organized by→ Relationships —which also have→ Properties”

“A Traversal —navigates→ a Graph; it —identifies→ Paths —which order→ Nodes”

“An Index —maps from→ Properties —to either→ Nodes or Relationships”

“A Graph Database —manages a→ Graph and —also manages related→ Indexes”


Source: What is a Graph Database?

From Java to Neo4j

We have two Java classes representing our domain: User and Role. Here is the Class diagram:

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

In Neo4j, User and Role are nodes, and the link between the two is a relationship. In Part 2 we will demonstrate how to declare them as nodes and how to create the relationship.

Here's 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.

Screenshots

Let's preview how the application will look like after it's finished. This is also a good way to clarify further our application's specs. Note: These are the same screenshots you will see from the Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB guide (We're reusing the exact presentation layer).

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 write the Java classes and discuss the application's layers. 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 Neo4j (Part 1) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

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

Review

In the previous section, we have laid down the functional specs of the application and discussed the Neo4j data model. In this section, we will discuss the project's structure, write the Java classes, and map our domain classes to the Neo4j data model.


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 the following POJOs:
  • User - represents our user
  • Role - represents the role of the user
  • UserRoleRelationship - represents the relationship of a user to its role
  • .





Notice we've annotated our domain classes with Spring Data Neo4j annotations. Here are the explanations:

@NodeEntity

The @NodeEntity annotation is used to turn a POJO class into an entity backed by a node in the graph database. Fields on the entity are by default mapped to properties of the node. Fields referencing other node entities (or collections thereof) are linked with relationships.

Source: Spring Data Neo4j Reference

@GraphId

For the simple mapping this is a required field which must be of type Long. It is used by Spring Data Neo4j to store the node or relationship-id to re-connect the entity to the graph.

For the advanced mapping such a field is optional. Only if the underlying id has to be accessed, it is needed.

Source: Spring Data Neo4j Reference

@Indexed

@Indexed: Making entities searchable by field value

The @Indexed annotation can be declared on fields that are intended to be indexed by the Neo4j indexing facilities. The resulting index can be used to later retrieve nodes or relationships that contain a certain property value, e.g. a name. Often an index is used to establish the start node for a traversal.

Source: Spring Data Neo4j Reference

@Fetch

To have the collections of relationships being read eagerly ... we have to annotate it with the @Fetch annotation. Otherwise Spring Data Neo4j refrains from following relationships automatically.

Source: Spring Data Neo4j Reference

@RelatedTo

@RelatedTo: Connecting node entities

Every field of a node entity that references one or more other node entities is backed by relationships in the graph. These relationships are managed by Spring Data Neo4j automatically.

The simplest kind of relationship is a single field pointing to another node entity (1:1). In this case, the field does not have to be annotated at all, although the annotation may be used to control the direction and type of the relationship. When setting the field, a relationship is created when the entity is persisted. If the field is set to null, the relationship is removed.

Source: Spring Data Neo4j Reference

@RelationshipEntity

To access the full data model of graph relationships, POJOs can also be annotated with @RelationshipEntity, making them relationship entities. Just as node entities represent nodes in the graph, relationship entities represent relationships. As described above, fields annotated with @RelatedTo provide a way to link node entities together via relationships, but it provides no way of accessing the relationships themselves.

Relationship entities can be accessed via by @RelatedToVia-annotated

Fields in relationship entities are, similarly to node entities, persisted as properties on the relationship. For accessing the two endpoints of the relationship, two special annotations are available: @StartNode and @EndNode. A field annotated with one of these annotations will provide read-only access to the corresponding endpoint, depending on the chosen annotation.

Source: Spring Data Neo4j Reference

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 a single service, UserService for managing users.



What is Spring Data Neo4j?

Spring Data Neo4j enables POJO based development for the Graph Database Neo4j. It maps annotated entity classes to the Neo4j Graph Database with advanced mapping functionality. The template programming model is equivalent to well known Spring templates and builds the basis for interaction with the graph and is also used for the advanced repository support.
Spring Data Neo4j is part of the Spring Data project which aims to provide convenient support for NoSQL databases.

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

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 Neo4j (Part 2) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

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

Review

In the previous section, we have implemented the Java classes and discussed the Neo4j service. In this section, we will write the configuration files for enabling Spring MVC and Neo4j support.


Configuration

To enable Neo4j support, we need to declare the following beans
  • a Spring Data Neo4j repository
  • a Neo4j store directory
  • Optionally, we declared an InitNeo4jService to automatically populate our database with sample data (currently disabled)


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 Neo4j (Part 3) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

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

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 Neo4j (Part 4) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring MVC 3.1 - Implement CRUD with Spring Data Neo4j (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

  • You don't need to run a separate Neo4j server because it will start simultaneously with the application.
  • There's no need to populate the database.
  • Due to some issues with the initialization service, I have decided to deactivate the service (though it's included in the source code for reference).

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-neo4j-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-neo4j-tutorial
    Mar 9, 2012 7:19:07 AM org.apache.catalina.startup.Embedded start
    INFO: Starting tomcat server
    Mar 9, 2012 7:19:07 AM org.apache.catalina.core.StandardEngine start
    INFO: Starting Servlet Engine: Apache Tomcat/6.0.29
    Mar 9, 2012 7:19:07 AM org.apache.catalina.core.ApplicationContext log
    INFO: Initializing Spring root WebApplicationContext
    Mar 9, 2012 7:19:11 AM org.apache.coyote.http11.Http11Protocol init
    INFO: Initializing Coyote HTTP/1.1 on http-8080
    Mar 9, 2012 7:19:11 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-neo4j-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-neo4j-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 Neo4j using the Spring Data Neo4j framework, and studied how to map our domain objects to the Neo4j graph. We've only explored the basics of Neo4j, but I hope that this simple tutorial will provide a good start.

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 March 8 2012 Uploaded tutorial
2 March 9 2012 Uploaded source code to Github

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 Neo4j (Part 5) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Monday, February 20, 2012

MongoDB - Replica Sets with Spring Data MongoDB (Part 1)

Introduction

In this tutorial, we will study how to setup MongoDB Replica Sets using a Spring Data MongoDB-based application for testing our replica sets. We will not create a MongoDB application here but instead we will reuse an existing one from the Spring MVC 3.1 - Implement CRUD with Spring Data MongoDB guide. For this study, we will use production-ready, cloud servers to demonstrate in real-time the results.


What is a Replica Set?

Replica sets are a form of asynchronous master/slave replication, adding automatic failover and automatic recovery of member nodes.

  • A replica set consists of two or more nodes that are copies of each other. (i.e.: replicas)
  • The replica set automatically elects a primary (master). No one member is intrinsically primary; that is, this is a share-nothing design.
  • Drivers (and mongos) can automatically detect when a replica set primary changes and will begin sending writes to the new primary.

Replica sets have several common uses:
  • Data Redundancy
  • Automated Failover / High Availability
  • Distributing read load
  • Simplify maintenance (compared to "normal" master-slave)
  • Disaster recovery

Source: MongoDB Replica Sets

Servers

We have four cloud servers (for security purposes, I have modified their actual IP addresses). All servers are running with the following configuration:
OS: CentOS release 5.2 (Final)
RAM: 512MB
HD: 30GB

Here are our servers:
Server #IP addressMongoDB portComments
Server 1123.456.78.9027017primary server
Server 2123.456.78.9127017slave server
Server 3123.456.78.9227017slave server
Server 4123.456.78.9327017arbiter server (see note below)

Although Server 1 is the primary server, this is not permanent. Whenever the primary server is down, another server is elected as a primary. Server 4 is an arbiter server which is useful for certain cases in electing a primary server.

Note: Our Spring Data MongoDB-based application is hosted in Server 1.

What is an Arbiter?
Arbiters are nodes in a replica set that only participate in elections: they don't have a copy of the data and will never become the primary node (or even a readable secondary). They are mainly useful for breaking ties during elections (e.g. if a set only has two members).

When to add an arbiter
  • Two members with data : add an arbiter to have three voters. 2 out of 3 votes for a member establishes it as primary.
  • Three members with data : no need to add an arbiter. In fact having 4 voters is worse as 3 of 4 needed to elect a primary instead of 2 of 3. In theory one might add two arbiters thus making number of votes five, and 3 of 5 would be ok; however this is uncommon and generally not recommended.
  • Four members with data : add one arbiter.

Source: MongoDB - Adding an Arbiter

Do I need an Arbiter?
You need an arbiter if you have an even number of votes. As an extension to this, at most you should only ever have 1 arbiter. If you aren't sure how many votes you have, it's probably the same as the number of servers in the set you have (including slaves, hidden, arbiters).

Source: Does My MongoDB Replica Set Need An Arbiter?

Next

In the next section, we will install MongoDB on our servers and configure Replica Sets. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: MongoDB - Replica Sets with Spring Data MongoDB (Part 1) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share