Spring MVC: Ajax & JQuery

Spring-JQuery-AJAX
Today I want to demonstrate how to integrate AJAX into a Spring MVC application. I’m going to use JQuery on a client side for sending of requests and receiving of responses. This tutorial will be based on one of my previous tutorials about Spring MVC and REST services. In this article you will read how to make a web-application more interactive with the help of asynchronous requests.

Preparations

I need to modify the SmartphoneController class by removing methods which are not required any more. This is a first step of AJAX integration.

//imports are omitted
@Controller
@RequestMapping(value="/smartphones")
public class SmartphoneController {
	
	@Autowired
	private SmartphoneService smartphoneService;
	
	@RequestMapping(value="/create", method=RequestMethod.GET)
	public ModelAndView createSmartphonePage() {
		ModelAndView mav = new ModelAndView("phones/new-phone");
		mav.addObject("sPhone", new Smartphone());
		return mav;
	}
	
	@RequestMapping(value="/create", method=RequestMethod.POST, 
			produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Smartphone createSmartphone(@RequestBody Smartphone smartphone) {
		return smartphoneService.create(smartphone);
	}
	
	@RequestMapping(value="/edit/{id}", method=RequestMethod.GET)
	public ModelAndView editSmartphonePage(@PathVariable int id) {
		ModelAndView mav = new ModelAndView("phones/edit-phone");
		Smartphone smartphone = smartphoneService.get(id);
		mav.addObject("sPhone", smartphone);
		return mav;
	}
	
	@RequestMapping(value="/edit/{id}", method=RequestMethod.PUT, 
			produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Smartphone editSmartphone(@PathVariable int id, 
			@RequestBody Smartphone smartphone) {
		smartphone.setId(id);
		return smartphoneService.update(smartphone);
	}
	
	@RequestMapping(value="/delete/{id}", method=RequestMethod.DELETE, 
			produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Smartphone deleteSmartphone(@PathVariable int id) {
		return smartphoneService.delete(id);
	}
	
	@RequestMapping(value="", method=RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public List< Smartphone > allPhones() {
		return smartphoneService.getAll();
	}
	
	@RequestMapping(value="", method=RequestMethod.GET)
	public ModelAndView allPhonesPage() {
		ModelAndView mav = new ModelAndView("phones/all-phones");
		List< Smartphone > smartphones = new ArrayList< Smartphone >();
		smartphones.addAll(allPhones());
		mav.addObject("smartphones", smartphones);
		return mav;
	}
	
}

You can compare the new version of the SmartphoneController with the older one. Methods which process PUT, POST, DELETE requests and return ModelAndView objects were removed. The methods were deleted because AJAX calls can be addressed directly to REST methods. Now the controller contains just two types of methods:

  • The first type directs user to pages where CRUD operations can be performed.
  • The second type performs CRUD operations (REST methods)

Client side

An AJAX usage implies a lot of code on a client side of a web-application. In this section I will demonstrate a basics which will help you to understand what steps to do for implementation of AJAX calls.
Let’s examine case with creation of a new smartphone in the application.

First of all I need to add JQuery library to HTML page:


A main part of the HTML has one valuable update – extension of form action attribute was changed to .json

Create new Smartphone

Here you can create new Smartphone:

Producer: Nokia iPhone HTC Samsung
Model:
Price:
Home page

And now, ladies and gentlemen, I wish to introduce a snippet of JQuery code for the creation of new smartphone:

    $(document).ready(function() {
      
      $('#newSmartphoneForm').submit(function(event) {
    	  
    	  var producer = $('#producer').val();
    	  var model = $('#model').val();
    	  var price = $('#price').val();
    	  var json = { "producer" : producer, "model" : model, "price": price};
    	  
        $.ajax({
        	url: $("#newSmartphoneForm").attr( "action"),
        	data: JSON.stringify(json),
        	type: "POST",
        	
        	beforeSend: function(xhr) {
        		xhr.setRequestHeader("Accept", "application/json");
        		xhr.setRequestHeader("Content-Type", "application/json");
        	},
        	success: function(smartphone) {
        		var respContent = "";
        		
		  		respContent += "Smartphone was created: [";
		  		respContent += smartphone.producer + " : ";
		  		respContent += smartphone.model + " : " ;
		  		respContent += smartphone.price + "]";
        		
        		$("#sPhoneFromResponse").html(respContent);   		
        	}
        });
         
        event.preventDefault();
      });
       
    });

I’m not going to stop on this code and explain it in detail because you can read about AJAX and JQuery on official site.

Brief explanation: when someone want to submit the form with specified ID, all form fields are assigned to appropriate variables. After that a new JSON document is generated based on the form field variables. Then AJAX call is performed. It directed to URL which is specified in the action attribute of form tag. The JSON is used as a data which need to be processed. Type of the request is POST (it can vary depending on operation, e.g. for update it will has PUT value). In the beforeSend function I explicitly specify required headers for JSON format. In the end I formulate a response and insert it in DOM.

Create new Smartphone

That’s it what related to creation of smartphone. The update of smartphone is the similar, just type of the request need to be changed.

Now let’s see how to work with DELETE type of requests. As previously I need to change extension of URLs to .json

Delete

A JQuery code for the DELETE operation will be a little bit distinct compared to POST and PUT.

$(document).ready(function() {
    	
	var deleteLink = $("a:contains('Delete')");
      
	$(deleteLink).click(function(event) {
    	  
		$.ajax({
			url: $(event.target).attr("href"),
			type: "DELETE",
			  	
			  beforeSend: function(xhr) {
			  	xhr.setRequestHeader("Accept", "application/json");
			  	xhr.setRequestHeader("Content-Type", "application/json");
			  },
			  	
			  success: function(smartphone) {
			  	var respContent = "";
			  	var rowToDelete = $(event.target).closest("tr");
			  		
			  	rowToDelete.remove();
			  		
			  	respContent += "Smartphone was deleted: [";
			  	respContent += smartphone.producer + " : ";
			  	respContent += smartphone.model + " : " ;
			  	respContent += smartphone.price + "]";
			  		
			  	$("#sPhoneFromResponse").html(respContent);   		
			  }
		});
  
		event.preventDefault();
	});
       
});   

The first distinction is the selector for the element. In case with DELETE I want to work with links but not with forms. The type of the AJAX call is changed to DELETE value. There is no any data which is send with the request. And in the end I delete the row with the smartphone which need to be deleted.

Delete smartphone

Summary

I hope this short overview of the AJAX will be useful for you. There are a lot of features which can be implemented with the help of AJAX in any web-application, so don’t ignore this convenient way for communication with a server. You can find this application on GitHub.

Share and Enjoy

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS
  • marghi

    very nice, put it on github, thank you ;)

  • Majid Lotfi

    Hi,

    Thank you for this tutorial, I imported it in STS, when I tried to create a smartphone I got this exception :

    ov 08, 2013 10:14:09 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions

    ERROR: Table ‘hibnatedb.smartphones’ doesn’t exist

    Nov 08, 2013 10:14:09 PM org.apache.catalina.core.StandardWrapperValve invoke

    SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/MobileApp] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: org.hibernate.exception.SQLGrammarException: could not execute statement; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute statement] with root cause

    com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table ‘hibnatedb.smartphones’ doesn’t exist

    Please your help is appreciated.

    • Vladislav Molchanov

      It means that you haven’t the table with name “hibnatedb.smartphones”. Make sure that you use MySql database (com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException) and you have created the table with name “hibnatedb.smartphones”.

      • Susi Loma

        Hi, i would prefer to create the database table from the application, of course only in development mode. But i have never seen the config within spring. So do someone know what i have to do, to get the database table created from the application. In another hibernate application i use this parameter to do it. “create”

  • Sedat

    Hi, success part of my ajax post change it to HTML post. If i remove success part, it comes as XHR. Do you have any idea what the reason could be?

  • TechMan

    I have been trying with similar code since last 3 hours and getting 400 error while trying to add a new phone. Actually I was trying to do this with Angular $http and then tried with JQuery but no luck.
    POST with ‘consumes’ and ‘produces’ together is just not working for me.
    Any thoughts why?

    • http://fruzenshtein.com/ Alex Zvolinskiy

      I have no idea.
      Before publish any tutorial I always check a code sample works fine