Saturday, July 14, 2012


Spring 3.0 Support for RESTful Web Services


January 3, 2011

Although RESTful functionality was added to the Spring MVC framework quite early through annotations and other API features, support for RESTful Web services came a bit late to Spring MVC. Several JAX-RS (Java API for RESTful Web services) implementations such as Restlet, RESTEasy and Jersey supported RESTful Web services already, but the Spring community didn't add support for RESTful Web services features until Spring 3.0. In this article, I discuss the Spring 3.0 support for developing RESTful Web services, examining the classes and annotations provided.
As a quick refresher, RESTful Web services are Web services that are created and accessed using REST (REpresentational State Transfer) principles. RESTful Web services, which use HTTP methods for the operations they perform, can be easily accessed using Uniform Resource Identifiers (URIs). The HTTP methods POSTGETPUT and DELETE can be mapped to create, read, update and delete (CRUD) operations.

RESTful Web Services Using JAX-RS

JAX-RS is a Java programming API (JSR 311) that is included as part of the Java EE platform. JAX-RS is designed to make it easy to develop Java applications using REST principles and architecture; Using annotations, JAX-RS developers can expose simple POJOs as Web resources. JAX-RS applications are bundled as WAR files like any other Web application in Java and deployed on a container that supports the Java Servlet API.
One way to develop JAX-RS applications in Java is to use Jersey, an open source, production-quality reference implementation of JAX-RS. Jersey implements all the APIs, and it provides annotations for quick and easy creation of Java Web services using the REST style. It also provides a lot of additional features with its own APIs like the Jersey Client API. For RESTful Web services, Jersey uses a HTTP Web server called Grizzly. Requests to this container are handled by the Grizzly Servlet, with the fully qualified name com.sun.jersey.spi.container.servlet.ServletContainer.

RESTful Web Services Using Spring

With Spring MVC support for RESTful Web Services, Java developers can build RESTful applications using annotations that inherit from the annotations in Spring's Web MVC framework. Client-side support for RESTful applications are provided by the RestTemplate API, which is conceptually very similar to classes like JdbcTemplate and JmsTemplate. REST functionality is provided by the HttpConverters class, which helps convert objects to their representations in HTTP requests and responses, and vice versa. To achieve the mapping between objects and XML, Spring provides the MarshallingHttpMessageConverter class.
Spring Web MVC uses a DispatcherServlet for dispatching requests to handlers. The default handler is identified using the @Controller and @RequestMapping annotations. These annotations play a major role in developing RESTful applications for Spring, and in fact are fundamental (along with the @PathVariable annotation) to the RESTful functionality in Spring. The @Controller annotation is used for marking a POJO as a Controller, while the@RequestMapping annotation is used for mapping requests to a class or a handler method.

Spring Controllers and RESTful Web Services

Controllers represent the "C" in Spring Web MVC. They help handle user input and transform it into a model for the user through the view. Controllers can be declared using the @Controller annotation. Typically, this annotation is used on top of a class to mark that particular class as a controller.
@Controller
public class StockController {
   private final Stock stock;

   @AutoWired
   public StockController(Stock stock) {
      this.stock = stock;
   }

   @RequestMapping("/")
   public void stockInfo() {
   }

   @RequestMapping("/stockdetails")
   public String getStockDetails() {
      return this.stock.getStockDetails();
   }
}
The annotation @RequestMapping is not required at the class level, it can be mentioned at the method level. The appropriate method is invoked by the handler depending on the absolute path.

URI Templates

A URI template is a template to hold a URI like string. Typically, a URI template holds variables and when these variables are substituted with values, they become the actual URI. URI templates allow mentioning a template in the@RequestMapping annotation.
For example, the URI http://www.helloworld.com/users/{username} mentions a URI template that allows one to substitute the username with the actual name of a user like http://www.helloworld.com/users/john. The handler compares the actual URI with the URI template and substitutes the parameters appropriately.
@RequestMapping(value="/users/{username}", method=RequestMethod.GET)
public String sayHello(Model model) {
   ......
   return "Hello, Welcome!";
}

Spring Annotation: @PathVariable

The annotation @PathVariable is used to bind the URI template variable to a method parameter. In the previous example, the URI template variable username can be bound to the method parameter userName with the@PathVariable annotation. The method parameter types declared with @PathVariable are not restricted only to String; they can be of any primitive data type such as intlongdouble, etc.
@RequestMapping(value="/users/{username}", method=RequestMethod.GET)
public String sayHello(@PathVariable("username") String userName, Model model) {
   ......
   return "Hello "+userName+", Welcome!";
}
It is possible to bind multiple URI template variables to the method parameters also.
@RequestMapping(value="/users/{username}/city/{cityname}", method=RequestMethod.GET)
public String sayHello(@PathVariable("username") String userName, @PathVariable("cityname")  String cityName, Model model) {
   ......
}
URI template variables can come from the relative path as well.
@Controller
@RequestMapping(value="/users/{username}")
public class SayHelloController {

   @RequestMapping(value="/city/{cityname}")
   public String sayHello(@PathVariable("username") String userName, @PathVariable("cityname")  String cityName, Model model) {
   ......
   }
}
Parameterized conditions like myParam=paramValue are also supported, wherein the request is mapped only if the parameters have the given paramValue.

Spring Annotation: @RequestParam

The annotation @RequestParam is used to bind the request parameters to a method parameter in the controller. Similarly, the annotation @RequestBody is used to indicate that the parameter is bound to the value in the HTTP request body. While sending the response, the annotation @ResponseBody can also be used to return the value in the HTTP response body.
@Controller
@RequestMapping("/stockquote")
public class StockController {
   .....

   @RequestMapping(method=RequestMethod.GET)
   public double getStockPrice(@RequestParam("stockSymbol") String stockSymbol, Model model) {
      ...
      model.setAttribute("stockSymbol", stockSymbol);
      ...
   }
   .....
   .....
}
As mentioned previously, RestTemplate is the class used for accessing RESTful services on the client side. Even though this is similar to other template classes available in Spring, it can be customized further by providing callback methods and configuring the HttpMessageConverter class for marshalling and unmarshalling HTTP request and response. Client-side operations are performed completely with the RestTemplate and HttpMessageConverter classes.

The RestTemplate Class

The Jakarta Commons HttpClient class is used for invoking RESTful services in Java. For common operations, the executeMethod of the HttpClient is used for performing higher-level operations corresponding to the six HTTP methods. RestTemplate provides a set of methods that ensures REST best practices. The methods provided by the RestTemplate class that correspond to HTTP methods are:
RestTemplate class and corresponding HTTP methods
The method names in the RestTemplate class convey a simple meaning. The first part contains the name of the HTTP method to which the RestTemplate method names correspond, and the second part indicates the return value. To understand this better, consider the getForObject method: it performs a GET operation and returns an object from the HTTP response (HTTP response is converted into an object type). Similarly, the postForLocation method will perform a POST operation and return the HTTP location header where the newly created object is available.
The methods in the RestTemplate class accept a string URL or map strings. The RestTemplate object can be created using the default constructor, and the client uses the APIs in the java.net package to create HTTP requests. Here is an example of a client accessing RESTful Web services using the RestTemplate class:
........
String uri = "http://stock.com/stockdata/{symbol}/stockquote";
RestTemplate template = new RestTemplate();
StockQuote sq = new StockQuote();
........
URI location = template.postForLocation(uri, sq, "INFY");
........

HTTP Message Converters

Objects sent to and returned from the RestTemplate methods, such as getForObjectputpostForObject, etc., are converted to HTTP messages -- HTTP request and HTTP response -- by the HttpMessageConverter interface. This interface has the following methods:
  • boolean canRead(Class clazz, MediaType mediaType) -- Used to determine whether the given class and media type can be read by this converter
  • boolean canWrite(Class clazz, MediaType mediaType) -- Used to determine whether the given class and media type can be written by this converter
  • List getSupportedMediaTypes() -- Returns the list of MediaType objects supported
  • T read(Class clazz, HttpInputMessage inputMessage) -- Reads an object from the given input message, and returns it
  • void write(T t, HttpOutputMessage outputMessage) -- Writes a given object to the given output message
The converters for the MIME type are available by default. It is possible to write custom converters also. The default converter instances available are highlighted in the table below.
Default HTTP message converter instances

Conclusion

RESTful Web services are best suited for when there is a need for stateless Web services. The REST-based architecture provides better performance and caching options in those instances. As I've discussed in this article, the Spring Framework provides good support for building RESTful Web services in a simple and elegant way with annotations and APIs like RestTemplate.

Acknowledgements

The author would like to sincerely thank Mr. Subrahmanya (SV, VP, ECOM Research Group, E&R) for his ideas, guidance, support and constant encouragement and Mr. KL Nitin for kindly reviewing this article and providing valuable comments.

Further Reading

For more information on REST and REST principles, read these articles from DevX:

About the Author

Sangeetha S. works as a Senior Technical Architect at the E-Commerce Research Labs at Infosys Technologies. She has over 12 years of experience in the design and development of Java and Java EE applications. She has co-authored a book on J2EE architecture and also has written articles for online Java publications.