Using Spring MVC for REST-like Services

Spring MVC makes it trivial and easy to build REST-like web services using HTTP and JSON. Services can be built and documented quickly in pure Java with virtually no boilerplate. With modern web clients being built in Javascript providing quick access to data is increasingly important. I’ll introduce you to how Spring MVC can make this a painless process.

I carefully choose the term “REST-like” because they are not actually REST services.  There is no hypermedia here, therefore it is not REST by definition.  That won’t stop most developers and companies (including Google) from using the term “REST service” much to Roy Fielding’s ire.  I however will not do so.  Instead I will call them “REST-like” as they are built on what so many developers call “REST”: standard HTTP methods and JSON.

Spring MVC Example

In this prototype we’ll build a simple movie ratings application.  It will store everything in memory and provide a set of services for movies.

  • Add a movie
  • Edit a movie
  • Delete a movie
  • List movies by rating
  • Rate a movie

This will provide us with the  basics mechanisms needed for a common web application.  Note that we will not be building a UI in this article.  I actually intend to use this as a base for demonstrating a few different options for building a browser based client.

Boilerplate Spring MVC

We’ll be using Maven of course.  We’ll start with some basic, common dependencies for a web application.  Namely Servlet, JUnit, etc. along with the Spring Framework and Jackson.  Jackson will serialize our objects to and from JSON.

Can not find code at url : https://github.com/kenblair/spring-demo/blob/1.0/pom.xml

Create the Spring configuration, we’ll use XML for the basics.

Can not find code at url : https://github.com/kenblair/spring-demo/blob/1.0/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml

Now setup a DispatcherServlet to handle all requests.

Can not find code at url : https://github.com/kenblair/spring-demo/blob/1.0/src/main/webapp/WEB-INF/web.xml

Now we’re ready for a Spring MVC web application. First we configured Spring to scan for beans in what will be our base package. Second we told Spring MVC to look for annotation based controller mappings. Then we configured a servlet that will pass all requests to the Spring MVC DispatcherServlet. The dispatcher is at the core of Spring MVC and will determine how and where a request is handled.

Building the Controller

With what little boilerplate there is out of the way we can build a controller.  As mentioned the dispatcher servlet determines how a request is handled.  In our Spring configuration we used <mvc:annotation-driven/> to tell Spring to look for controllers with annotations.  To create one we need to create a controller bean and specify which requests it handles. These will be mapped and used by the dispatcher servlet to find the class and method to call.

package net.kenblair.spring.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * A simple Spring controller.
 *
 * @author Ken Blair
 */
@Controller
public class HelloWorldController {

    /**
     * Display a name.
     *
     * @return The movies.
     */
    @RequestMapping("/hello")
    public @ResponseBody String hello(@RequestParam(required = false) String name) {
        return "
Hello " + name + "

";
    }
}

First we use @Controller to mark this as not just a bean, but a bean for handling web requests. Then we use @RequestMapping to define a method that can handle a request. In this case it will handle any request for the path /hello such as http://localhost:8080/spring-demo/hello. We also specify an expected parameter with @RequestParam. By default parameters are required however in this case we’ve specified that it’s not.

When returning a String from a method in Spring MVC it is normally treated as a View name. The dispatcher servlet will use view resolvers you have configured to find the view, whether it’s a JSP, Velocity/Freemarker template or something else. This is well covered in the Spring MVC documentation and elsewhere. Here we’re not interested in using Spring MVC to render a view, we’re simply interested in using Spring MVC to provide easy to use REST-like APIs.

Instead we use @ResponseBody which tells Spring that we are not returning a view to be rendered, we are returning that actual content of the response. You can compile and run the example using mvn package tomcat7:run and then visit the page at http://localhost:8080/spring-demo/hello. To specify a name change it to /hello?name=World.

A Simple REST-like API

How does all of this translate to an actual REST-like API? We could return JSON, for example return "{\"name\":\"" + name + "\"}". Doing everything by hand is tedious and time consuming, I promised trivial and easy. Enter Jackson, a library we included in our dependencies in the POM. Jackson will serialize objects to JSON and vice versa. Thus instead of returning a String we can return an actual object, like say a Movie. Spring MVC is smart enough to look for Jackson and use it to create a JSON response from the object.
Create a Movie and MovieRating.

Can not find code at url : https://github.com/kenblair/spring-demo/blob/1.0/src/main/java/net/kenblair/spring/domain/Movie.java
Can not find code at url : https://github.com/kenblair/spring-demo/blob/1.0/src/main/java/net/kenblair/spring/domain/MovieRating.java

A movie has a name and a list of ratings. Ratings have a rating of 1 to 5 and a description. Very simple. Now create a service to store and access these ratings.

Can not find code at url : https://github.com/kenblair/spring-demo/blob/1.0/src/main/java/net/kenblair/spring/service/MovieService.java
Can not find code at url : https://github.com/kenblair/spring-demo/blob/1.0/src/main/java/net/kenblair/spring/service/InMemoryMovieService.java

Great. We can now save and retrieve movies. Let’s build a controller to access these.

Can not find code at url : https://github.com/kenblair/spring-demo/blob/1.0/src/main/java/net/kenblair/spring/web/MovieController.java

And we’re done. It really is that simple. Now of course you could expand upon this. Perform validation, return a detailed error message, force an update to use PUT and a retrieval to use GET and so on. We’ll get into some of that later, for now we have a very simple service to use for building a client which I will cover in future posts.  The complete source for this example is on Github at https://github.com/kenblair/spring-demo/tree/1.0.  Build it using mvn package and run it using mvn tomcat7:run-war.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>