Ajax Simplifications in Spring 3.0

Keith Donald

In my last entry, I walked you through several enhancements in Spring 3 for web application development. A number of you expressed interest in a follow-up entry focused on Ajax remoting. Spring 3 provides a lot in this area to take advantage of. Read on, and I'll walk you through it.

Spring and Ajax Overview

For the purposes of this article, when I say Ajax, I'm talking about the web browser's ability to communicate with a web server asynchronously using JavaScript. On the server-side, Spring provides the programming model for defining web services, including services consumed by JavaScript clients. On the client-side, nobody rolls their own Ajax framework these days, either. Most use an established JavaScript framework such as jQuery or Dojo.

Support for Ajax Clients

Until version 3, Spring did not ship support for Ajax remoting. That didn't stop our users from extending Spring to get it, or integrating other options themselves. Some used DWR, especially in the period before the rise of the JavaScript frameworks. More recently, REST-style remoting with JSON as the data exchange format has become more popular, especially because jQuery and co. make it so easy to do.

Now that Spring 3 is out, official support for Ajax remoting with JSON is provided as part of Spring MVC. This includes support for generating JSON responses and binding JSON requests using the Spring MVC @Controller programming model. In this article, I'm going to focus on using this support to implement several Ajax use cases. Like my last post, I'll do this by walking you through a sample application you can experiment with yourself.

MVC Ajax Sample

mvc-ajax has been designed to illustrate Spring MVC's JSON support. The project is available in our spring-samples Subversion repository, is buildable with Maven, and is importable into STS / Eclipse. mvc-ajax has the same structure as the mvc-basic project presented in my previous entry. In fact, the Spring configuration is identical between the two.

Start your review by deploying the project to your servlet container and accessing the welcome page at localhost:8080/mvc-ajax. Since I use STS, I did this by first importing the project into the IDE, then deploying it to the built-in Tomcat / tc-server instance.

Getting JSON from the Server

From the welcome page, activate the "Ajax @Controller Example" link. You will see a form to create a new Account. When you tab out of the Name field, your browser will ask the server if the name you just entered is available. If it is not, an error message will be displayed and the form will remain disabled until you enter a name that is available. The client-side JavaScript handling this resides in /WEB-INF/views/account/createForm.jsp and looks like:

$(document).ready(function() {
    // check name availability on focus lost
    $('#name').blur(function() {
        checkAvailability();
    });
});

function checkAvailability() {
    $.getJSON("account/availability", { name: $('#name').val() }, function(availability) {
        if (availability.available) {
            fieldValidated("name", { valid : true });
        } else {
            fieldValidated("name", { valid : false,
                message : $('#name').val() + " is not available, try " + availability.suggestions });
        }
    });
}

Nothing Spring-specific here, just standard jQuery JavaScript.

On the server-side, the Controller for the account/availability resource is standard Java with some Spring MVC annotations:

@RequestMapping(value="/availability", method=RequestMethod.GET)
public @ResponseBody AvailabilityStatus getAvailability(@RequestParam String name) {
    for (Account a : accounts.values()) {
        if (a.getName().equals(name)) {
            return AvailabilityStatus.notAvailable(name);
        }
    }
    return AvailabilityStatus.available();
}

AvailabilityStatus is a plain Java Value Object with two properties: an availability flag that tells the client if the user name is available, and an array of alternatives to suggest if the name you want is not available. The @ResponseBody annotation instructs Spring MVC to serialize the AvailabilityStatus to the client. Spring MVC automatically serializes to JSON because the client accepts that content type.

Underneath the covers, Spring MVC delegates to a HttpMessageConverter to perform the serialization. In this case, Spring MVC invokes a MappingJacksonHttpMessageConverter built on the Jackson JSON processor. This implementation is enabled automatically when you use the mvc:annotation-driven configuration element with Jackson present in your classpath.

Pretty cool, huh? Try creating an Account, then creating another one with the same name. You should see an error message suggesting alternate names. Turn on Firefox's Firebug or Safari's Web Inspector to debug the asynchronous interaction.

Posting JSON to the Server

Spring MVC also provides support for sending JSON to the server. I have found the need for this to be less common, simply because posting form parameters is often sufficient. Nevertheless, JSON provides a flexible data-interchange format that richer JavaScript clients can conveniently work with. The ability to map JSON to a server-side Java Object for processing can be a useful feature in those cases.

In the sample, a JavaScript event handler intercepts the form submit event and posts the form data as JSON. The server returns the id of the newly created Account, which is then used to display a modal confirmation dialog:

$("#account").submit(function() {
    var account = $(this).serializeObject();
    $.postJSON("account", account, function(data) {
        $("#assignedId").val(data.id);
        showPopup();
    });
    return false;
});

On the server-side, the Controller is more standard Java with Spring MVC annotations:

@RequestMapping(method=RequestMethod.POST)
public @ResponseBody Map<String, ? extends Object> create(@RequestBody Account account, HttpServletResponse response) {
    Set<ConstraintViolation<Account>> failures = validator.validate(account);
    if (!failures.isEmpty()) {
        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        return validationMessages(failures);
    } else {
        accounts.put(account.assignId(), account);
        return Collections.singletonMap("id", account.getId());
    }
}

Here, the @RequestBody annotation instructs Spring MVC to map the body of the HTTP request to an Account object. Spring MVC knows to map from JSON because the client set the request Content Type to application/json.

The create method also validates the Account object. If there are validation errors, a HTTP 400 is returned with the error messages, otherwise a HTTP 200 is returned with the assigned account ID.

Summary

Spring 3 provides first-class Ajax support with JSON as part of the Spring MVC module. This includes support for generating JSON responses and binding JSON requests using the Spring MVC @Controller programming model in conjunction with the Jackson JSON processor. In this article, I showed you how this support works. I hope you found this post useful, and look forward to hearing more of your experiences putting Spring 3 to work in your own applications!

Introduction To Spring Roo Screencast

Stefan Schmidt

After our mad dash to the final release of Spring Roo 1.0.0 on New Year's Eve, many users have asked for an introductory screencast.

In this 5 minute screencast you will see how to:

  • Develop a simple "contact manager application" using the Roo shell
  • Import and edit the project our free IDE, SpringSource Tool Suite (STS)
  • Run the Roo-provided integration tests in STS
  • Modify the application and understand ITD round-trip support
  • Deploy to your IDE's web container
  • Use the scaffolded web user interface
  • "Push-in refactor" to move source code between Java source files and ITDs
  • Remove Roo from the project

Interested? Just click the image below and enjoy…

Spring Roo 5 minute screencast

If you'd like to learn more about Spring Roo, please feel free to visit this link:

dm Server 2.0.0 released

Andy Wilkinson

As Adrian mentioned, today is the day for dm Server 2.0 and I'm delighted to announce that dm Server 2.0 is now available. Thank you for all of the feedback that we've had during the development of 2.0, it's helped to shape it into what we believe is a big step forward for enterprise OSGi. We're now looking forward to the next steps on the journey at Eclipse.org.

There's a lot of great stuff in the 2.0 release. Here's a brief overview:

  • dm Shell – we've added a brand new shell in 2.0, that's available both in-process and remotely over ssh. It provides extensive support for managing a dm Server instance and its deployed artifacts.
  • Admin console – the admin console has been extensively overhauled in 2.0. It provides, among other things, support for managing and deploying artifacts, examining diagnostic dumps, and examining the bundle wiring both in the live system, and at the time of a resolution failure.
  • Plans – dm Server 2.0 introduces support for plans which are powerful alternative to 1.0's PARs for deploying modular applications. A plan can be used to reference all of the artifacts that comprise your application, optionally making the application atomic to tie the child artifact lifecycles together, and scoped to isolate the application from other applications deployed in the same dm Server instance.
  • Provisioning – dm Server's always had excellent provisioning support and in 2.0 it's got even better. In addition to the automatic provisioning of bundles based on the needs of the installed applications that was available in 1.0, dm Server 2.0 provides support for provisioning plans, PARs, and configuration from both local and remote repositories.
  • Web support – dm Server 2.0 builds upon 1.0's Web support and embeds the Tomcat-based reference implementation for the OSGi Web Container specification, allowing users to deploy vanilla WAR files with all their dependencies in WEB-INF/lib, and Web Application Bundles that import their dependencies via OSGi manifest metadata. The web container is configurable using the standard Tomcat server.xml.
  • User region – dm Server 2.0 introduces a user region which isolates the dm Kernel from user-installed applications. Among other things, this simplifies administration as it allows users to focus on user application artifacts and their dependencies without having to deal with those of the kernel as well.
  • Spring 3.0 – like many others, we've been tracking the Spring 3.0 milestones and release candidates, and dm Server 2.0 now packages Spring 3.0 final. If you'd prefer to use dm Server 2.0 with a different version of Spring, it can easily be configured to do so.
  • Hot deployment – in addition to support for deployment via the admin console, artifacts can also be deployed to dm Server by copying them into the pickup directory, either in archive or exploded form.
  • Running as a service – dm Server can now be run as a Windows service or as a Unix background process.
  • Logging – as in 1.0, dm Server's logging support is available via SLF4J. In 2.0, the backend has been replaced with LogBack, making it extensively configurable by modifying dm Server's config/serviceability.xml file with a rich set of appenders available out of the box.
  • Equinox 3.5 – dm Server 2.0 embeds Equinox 3.5, the reference implementation of OSGi 4.2.

Latest comments across all posts

Recent Team Posts

Adrian Colyer

post dm Server project moves to Eclipse.org

Today we will be releasing version 2.0 of the dm server. This represents a major milestone for the project, and for enterprise application development with OSGi in general. I’m delighted to now be able to reveal the next step in the dm Server journey: we have submitted a proposal at Eclipse.org to continue development of [...]


Mark Fisher

post Task Scheduling Simplifications in Spring 3.0

Continuing the Spring 3.0 "simplification series" started by Keith and Chris, I would like to provide a quick overview of simplifications in scheduling and task execution enabled by Spring 3.0.
I will be walking through a basic sample application that you can checkout from the spring-samples Subversion repository. It has been designed to be as simple [...]


Ben Alex

post Spring Roo 1.0.0 Released

We're delighted to announce the general availability (GA) of Spring Roo 1.0.0.
Spring Roo is a next-generation rapid application development tool for Java developers. With Roo you can easily build full Java applications in minutes. It differs from other tools by focusing on:

Higher Java productivity: Try the ten minute test and see for yourself.
Stock-standard Java: Roo [...]

Older Posts

Grails 1.2 Released

Bundlor 1.0.0.RC1 Available

Configuration Simplifications in Spring 3.0

Groovy 1.7 released