Friday, 2 July 2010

Working with Ajax and JSON in Spring-MVC

I'm now working on the final major chapter of the Spring-MVC course, how to use Ajax with Spring.

I must say I'm pretty shocked (in a good way) at just how simple the support for Ajax in Spring-MVC is.

On the course, we're going perform a search against a database of books, and produce a list of near matches on the fly, as the user types into a text box on the web form. Something like this, with the results updating as soon as I type a letter in the search box...



I'd like to be able to send the list of matching books back to the web browser in JSON form. Although in the early days of Ajax, data was sent in XML form (the X in Ajax), these days JSON is a more natural choice as it is more compact and much easier to manipulate on the JavaScript client.

For details of what JSON looks like, see here. For example, a collection of book data might look something like:

[{"author":"Will Self","title":"Great Apes"},
 {"author":"Charles Dickens","title":"Great Expectations "},
 {"author":"Ken Kesey","title":"Sometimes a Great Notion "},
 {"author":"F. Scott Fitzgerald","title":"The Great Gatsby "}]

So I'd like my controller to be able to send back the results in the form of JSON. You might be thinking that I need to convert my Java objects manually - but in fact Spring-MVC makes it almost trivial:

  1. Annotate your controller method with @ResponseBody. This annotation tells Spring that the response to the browser should be serialised (ie converted from plain Java Objects into some kind of flattened, encoded structure).
  2. Add the JAR files from the Jackson project into your lib directory. Jackson is capabale of transforming object graphs into JSON form.
  3. You also need the <mvc:annotation-driven/> directive in your Spring wiring. By the time we do Ajax on the course, we'll have added this already, but if you're reading the blog separately from the course, you'll need to make sure you've done this.

These three things combined tells Spring that we want to send the response back from the method annotated with @ResponseBody in the form of a JSON graph.

So, the controller looks wonderfully simple:

@RequestMapping("/looseSearch")
public @ResponseBody List<Book> performLooseSearch(@RequestParam("CHARS")String chars)
{
    return bookService.searchBooksByLooseMatch(chars);
}

In terms of Spring-MVC, that's all there is to know. You now just need to code a front end capable of making an Ajax call. Until recently, the recommended approach in Spring was to use a framework like DWR - a framework that allowed us to call Java code as if it were a JavaScript method.

These days, however, the amazing jQuery library is the preferred choice. jQuery is a library that makes everyday JavaScript tasks such as making Ajax calls almost trivially easy.

Now, jQuery is beyond the scope of Spring-MVC so I can't provide a tutorial here, but I can show a code fragment that demonstrates how to call our loose search:

<head>
   <script type="text/javascript" src="/scripts/jquery-1.4.2.min.js" />
  
   <script type="text/javascript"> 
 
  function doSearch() {   
     $.getJSON("looseSearch.do", { CHARS: $('#searchBox').val() }, function(data) 
               {   
                  $('#results').text('');
    
                  for (var index in data) {
                     $('#results').append('<p>' + data[index].title + '</p>'); 
                  }
               });
 }
   </script>
</head>

<h1>Loose Search Test</h1>

<input type="text" id="searchBox" onKeyUp="doSearch();"/>

<div id="results">
 Results will appear here...
</div>

All you need to do is download the jquery JavaScript file from here and make sure it is picked up by your page.

All references to $ are jQuery calls.

On line 7, getJSON performs an Ajax call to the URL "looseSearch.do" - hence our controller will be run. The request parameter CHARS is populated with whatever is contained in the "searchBox" input field.

When (and if) a response is received by the server, the callback function that I've provided is invoked (lines 8-14). In the callback function, I simply clear the "results" div (line 9), and then I loop around the JSON results. For each element in the results, I extract the title and wrap it around a paragraph tag.

Line 21 ensures that the doSearch() function is called everytime I release a key in the input field.

If you're interested in seeing this full example coded, the Spring-MVC video course is released on 30 July 2010. You can register an interest by sending a blank email to subscribe@virtualpairprogrammers.com, and don't worry, we won't use your email address for any purpose except for keeping you updated with new courses.

8 comments:

  1. Hey Richard

    Theres a lot of work to do with Javscript there, why not use a better framework like JSF2, no nasty Javascript needed?

    ReplyDelete
  2. JSF2 is good as well (I wouldn't use JSF though), that does indeed hide any manual JavaScript work in high level tags.

    I think it's a question of preference. With Spring-MVC you don't get a lot of abstraction and so have to do more, but you retain control.

    In JSF2, you have to work harder to do anything that the components you are using can do (although of course, you can write your own).

    Too many frameworks to choose from in Java!

    ReplyDelete
  3. Hi Richard,
    Can you please send me the source code of this example Spring with Json ?

    I love the way you are explaining your tutorials, but your DVDs are very expensive.

    Thanks

    ReplyDelete
  4. I bought your Spring MVC video training and got to chapter 11. Ajax and jQuery. The same example as here. I typed in all of the code and it won't work! Java Script is giving me a error doSearch is not defined.
    I then copied the code from the examples that come with the training and the same error. Then I copied the code from here, and the same error!
    Where is the error? Can you help me?

    ReplyDelete
  5. Hi Zoran,

    Could you send a message to the support system at VirtualPairprogrammers, at http://www.virtualpairprogrammers.com/contact.html

    Then we can handle your problem properly, we'll probably ask you to send your code in and we'll inspect it in detail.

    Thanks.

    ReplyDelete
  6. Hi Richard, I was trying to do an example JSON with Spring MVC. But till now i didnt get any examples when i was goggling. It was a Good Example for Experienced People. Can u Just Give me the Completed Example Explanation. With a JSon Request and a Json Response in Spring. It will be very helpful for beginners like me.

    ReplyDelete
  7. I bought your Spring MVC video training. On the video you showed an example of Ajax with plain html form , chapter 11 (without validation). I try to combine together ajax example with the form validation that you did in chapter 7 and 8 (). This does not work. Do you have any advice on how to make it work?
    Thanks

    ReplyDelete
  8. Hi Antonio, there is an errata entry on the course page at https://www.virtualpairprogrammers.com/training-courses/Spring-MVC-and-WebFlow-training.html relating to Ajax - I think that might be the problem.

    Don't forget you can always send us a support call through the contact page on the site - that will always get a quicker response. I hope the above works, if not drop us a call and one of the support team will get things working.

    ReplyDelete