Spring MVC RequestMapping consumes condition example

16 March 2013
By Gonçalo Marques
In this tutorial you will learn how to use @RequestMapping annotation together with the "consumes" condition to handle distinct HTTP request content-types by distinct Controller methods.

Introduction

Spring MVC @RequestMapping annotation used in Controller methods allows the developer to define which methods will be used to handle distinct HTTP requests sent by clients based in the request content-type.

This may be useful if we are developing some kind of API that will be consumed by distinct clients, each one sending requests in some kind of format and also expecting distinct format responses or results.

In this tutorial we will define some Controller methods that will handle HTTP requests accordingly to their content-type.

This tutorial considers the following software and environment:

  1. Ubuntu 12.04
  2. JDK 1.7.0.09
  3. Spring 3.2.0
  4. Tomcat 7.0.35

The Controller

Let's define a Spring MVC controller that will handle the clients HTTP requests:

ExampleController.java

package com.byteslounge.spring.mvc.controller;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class ExampleController {

  @RequestMapping(value = "/test",
    method = RequestMethod.POST,
    consumes = "application/xml")
  public ResponseEntity<String> processXml(
    @RequestBody String requestBody){
    
    return new ResponseEntity<String>(
      "Handled application/xml request. Request body was: " 
      + requestBody, 
      new HttpHeaders(), 
      HttpStatus.OK);
  }
  
  @RequestMapping(value = "/test",
    method = RequestMethod.POST,
    consumes = "application/json")
  public ResponseEntity<String> processJson(
    @RequestBody String requestBody){
    
    return new ResponseEntity<String>(
      "Handled application/json request. Request body was: " 
      + requestBody, 
      new HttpHeaders(), 
      HttpStatus.OK);
  }
  
}

We are defining two distinct methods in the Controller: processXml and processJson. The @RequestMapping annotation is used to configure the rules that will determine which method will be chosen by Spring MVC to handle certain types of HTTP requests.

The value parameter determines the request URL pattern that will be used to match and choose a certain method to handle the request. We define value as /test so this means that both method will handle all requests which URL is /test.

The method parameter defines which HTTP method will be handled by the Controller's methods. We configured both Controller methods to handle HTTP requests which method is POST.

Finally we also configured the consumes parameter. This parameter defines which Controller method will be chosen based on the client HTTP request content-type. processXml method will handle requests which content-type is application/xml and processJson method will handle requests which content-type is application/json.

Both methods are returning an instance of type ResponseEntity. ResponseEntity type is used to build a complete HTTP response, ie. we are able to build a response with a complete set of HTTP headers and the response body respectively, but we will not cover this in detail in this tutorial. Let's say that - in this example- each method outputs a distinct response body based on the request content-type.

We are returning responses with HTTP status code 200(OK). We could be returning any other available HTTP response status codes and at the same time be handling other HTTP methods than POST. This would be useful for example to build a REST API.

Note: We may also define a consumes parameter value as !application/xml meaning that the method will handle all requets which content type is not application/xml

Note2: All requests which characteristics don't match any of the Request Mappings will not be handled by the Controller

DispatcherServlet configuration

The DispatcherServlet configuration follows next:

DispatcherServlet configuration
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xsi:schemaLocation="http://www.springframework.org/schema/beans     
  http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-3.2.xsd
  http://www.springframework.org/schema/mvc
  http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

  <context:component-scan base-package="com.byteslounge.spring.mvc.controller" />

  <mvc:annotation-driven />

</beans>

The configuration is sort of straight-forward: component-scan element tells the Spring container to look for managed components in package com.byteslounge.spring.mvc.controller. This package is where we placed our Controller.

annotation-driven element registers RequestMappingHandlerMapping and RequestMappingHandlerAdapter as the entities that will enable DispatcherServlet distinct request handling based on RequestMapping annotation configuration.

Testing

Let's send some requests to our application. First we deploy the application in Tomcat with springmvc as the application context. This means that the application will be reachable at:

http://localhost:8080/springmvc

We will use a command line tool called curl to send HTTP requests to the application.

Following next is the command to send a test request which content-type is application/xml:

curl -i -X POST -H "Content-Type: application/xml" \
-d "<root><element>value</element></root>" \
http://localhost:8080/springmvc/test

When we execute this command we will send an HTTP POST request to our application containing value in the request body. The request URL is /test and the content-type is application/xml, so the Controller method that will handle this request is processXml. The server response will be:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/plain;charset=ISO-8859-1
Content-Length: 87
Date: Sat, 16 Mar 2013 16:40:15 GMT

Handled application/xml request.
Request body was:
<root><element>value</element></root>

Which is the expected.

Now let's send another request which content type is application/json:

curl -i -X POST -H "Content-Type: application/json" \
-d '{ "root": { "element": "value" } }' \
http://localhost:8080/springmvc/test

The server response will be:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/plain;charset=ISO-8859-1
Content-Length: 85
Date: Sat, 16 Mar 2013 16:40:42 GMT

Handled application/json request.
Request body was:
{ "root": { "element": "value" } }

The tutorial full source code is available for download at the end of this page.

Download source code from this article

Related Articles

Comments

About the author
Gonçalo Marques is a Software Engineer with several years of experience in software development and architecture definition. During this period his main focus was delivering software solutions in banking, telecommunications and governmental areas. He created the Bytes Lounge website with one ultimate goal: share his knowledge with the software development community. His main area of expertise is Java and open source.

GitHub profile: https://github.com/gonmarques

He is also the author of the WiFi File Browser Android application: