Categories: springmvc

Spring MVC @RequestBody @ResponseBody Example

This post shows Spring MVC @RequestBody, @ResponseBody annotations usage, ResponseEntity, default HttpMessageConverteres available, and writing custom message converters. Let’s get going.

@RequestBody and @ResponseBody annotations are used to bind the HTTP request/response body with a domain object in method parameter or return type. Behind the scenes, these annotation uses HTTP Message converters to convert the body of HTTP request/response to domain objects.

@RequestBody

If a method parameter is annotated with @RequestBody, Spring will bind the incoming HTTP request body(for the URL mentioned in @RequestMapping for that method) to that parameter. While doing that, Spring will [behind the scenes] use HTTP Message converters to convert the HTTP request body into domain object [deserialize request body to domain object], based on Accept header present in request.

  • The Accept header is used by HTTP clients [browsers] to tell the server what content types they’ll accept.
  • The server sends back the response, which will include a Content-Type header telling the client what the content type of the returned content actually is. In case of POST or PUT request, browsers do send data in request, so they actually send content-type as well.

Take this method for example:


 @RequestMapping(value="/user/create", method=RequestMethod.POST)
 public ResponseEntity<Void> createUser(@RequestBody User user, UriComponentsBuilder ucBuilder){
  System.out.println("Creating User "+user.getName());
  
  if(userService.isUserExist(user)){
   System.out.println("A User with name "+user.getName()+" already exist");
   return new ResponseEntity<Void>(HttpStatus.CONFLICT);
  }

  userService.saveUser(user);
  
  HttpHeaders headers = new HttpHeaders();
     headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.getId()).toUri());
     return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
 }

This is the controller method to handle typical HTTP Post request [for URL /user/create]. In a pure REST oriented approach, this controller method creates a user, and returns the HTTP 201[CREATED] along with a LocationHeader containing the locations of newly created user [/app-address/user/1 e.g].

Now back to our original discussion, HTTP Post request body contains the detail of user to be created. When a client sends a request [/user/create] to create a user, it will be intercepted in this method. Method parameter user is marked with @RequestBody annotation. Thanks to this annotation, Spring will try to bind the request body [which can be JSON/XML/Other] to user object[ Means crating a new user object with the details found in the request body like user name,age etc..], based on Content-Type header in Http request.

But Spring need help to convert the request body into user object. It needs a converter which can convert the data in HTTP request body [which can be JSON/XML/Other] into user object.

Spring provides out-of-box many default HttpMessageConverters, which will be used for conversion, depending on presence of certain library in project classpath.

For example, if the Content-Type in request Header was one of application/json or application/xml , that means the POST body contains json or XML[Popular formats], and if Jackson library is found in your classpath, Spring will delegate the conversion to MappingJackson2HttpMessageConverter [for json] or MappingJackson2XmlHttpMessageConverter [for xml].

To declare a dependency to Jackson library (jackson-databind) include following dependency in your pom.xml

  <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>${jackson.version}</version>
  </dependency>

ResponseEntity (used in above example) represents the entire HTTP response. Good thing about it is that you can control anything that goes into it. You can specify status code, headers, and body. Next post goes into details of it with a fully working example.

@ResponseBody

If a method is annotated with @ResponseBody, Spring will bind the return value to outgoing HTTP response body. While doing that, Spring will [behind the scenes] use HTTP Message converters to convert the return value to HTTP response body [serialize the object to response body], based on Content-Type present in request HTTP header.

Take this method for example:

 @RequestMapping(value = "/user/all", method = RequestMethod.GET)
 public @ResponseBody List<User> listAllUsers() {
  return userService.findAllUsers();
 }

This is the controller method to handle typical HTTP GET request [for URL /user/all] to retrieve all users. In this case, Spring will convert the user list into appropriate format [JSON/XML/Other] using available converters, based on content type.

NOTE : As from Spring 4, @RestController is the preferred way to achieve the same functionality earlier provided by @ResponseBody. Under the hood, @RestController is @Controller+@ResponseBody, and it avoids the need of prefixing every method with @ResponseBody. Next post goes into details with a full working example.

Default HttpMessageConverters

Spring provides out of box following Http message converters which implements HttpMessageConverter interface [Credit : Spring Reference].

  • StringHttpMessageConverter

    An HttpMessageConverter implementation that can read and write Strings from the HTTP request and response. By default, this converter supports all text media types ( text/*), and writes with a Content-Type of text/plain.

  • FormHttpMessageConverter

    An HttpMessageConverter implementation that can read and write form data from the HTTP request and response. By default, this converter reads and writes the media type application/x-www-form-urlencoded. Form data is read from and written into a MultiValueMap.

  • ByteArrayHttpMessageConverter

    An HttpMessageConverter implementation that can read and write byte arrays from the HTTP request and response. By default, this converter supports all media types ( */*), and writes with a Content-Type of application/octet-stream. This can be overridden by setting the supportedMediaTypes property, and overriding getContentType(byte[]).

  • MarshallingHttpMessageConverter

    An HttpMessageConverter implementation that can read and write XML using Spring’s Marshaller and Unmarshaller abstractions from the org.springframework.oxm package. This converter requires a Marshaller and Unmarshaller before it can be used. These can be injected via constructor or bean properties. By default this converter supports ( text/xml) and ( application/xml).

  • MappingJackson2HttpMessageConverter

    An HttpMessageConverter implementation that can read and write JSON using Jackson’s ObjectMapper. JSON mapping can be customized as needed through the use of Jackson’s provided annotations. When further control is needed, a custom ObjectMapper can be injected through the ObjectMapper property for cases where custom JSON serializers/deserializers need to be provided for specific types. By default this converter supports ( application/json).

  • MappingJackson2XmlHttpMessageConverter

    An HttpMessageConverter implementation that can read and write XML using Jackson XML extension’s XmlMapper. XML mapping can be customized as needed through the use of JAXB or Jackson’s provided annotations. When further control is needed, a custom XmlMapper can be injected through the ObjectMapper property for cases where custom XML serializers/deserializers need to be provided for specific types. By default this converter supports ( application/xml).

  • SourceHttpMessageConverter

    An HttpMessageConverter implementation that can read and write javax.xml.transform.Source from the HTTP request and response. Only DOMSource, SAXSource, and StreamSource are supported. By default, this converter supports ( text/xml) and ( application/xml).

  • BufferedImageHttpMessageConverter

    An HttpMessageConverter implementation that can read and write java.awt.image.BufferedImage from the HTTP request and response. This converter reads and writes the media type supported by the Java I/O API.

Custom HttpMessageConverters

Most of the time, the default converters provided by Spring are enough. But if you need some custom behavior, you can roll out your own implementaion.

For instance, in above example, MappingJackson2HttpMessageConverter was used to handle JSON content. By default, the Jackson ObjectMapper supplied with this converter fails if there are missing properties in your JSON or domain object. It simply fails to convert. You can override this behavior by telling object mapper not to fail on missing properties, as shown below:


package com.websystique.springmvc.configuration;

import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.websystique.springmvc")
public class HelloWorldConfiguration extends WebMvcConfigurerAdapter{
 
 
 @Override
 public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
  converters.add(mappingJackson2HttpMessageConverter());
 }
 
 @Bean
 public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
  MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
  converter.setObjectMapper(new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false));
  return converter;
 }
 
 
}

Here we have overridden extendMessageConverters method which provides a hook to add your own validator, wihtout skipping all existing validators.

That’s it about the basic introduction on REST. Next post shows a RESTFUL CRUD web service, complete example with HTTP GET,PUT,POST & DELETE methods mapping.

View Comments

Share
Published by

Recent Posts

Spring Boot + AngularJS + Spring Data + JPA CRUD App Example

In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…

8 years ago

Spring Boot Rest API Example

Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…

8 years ago

Spring Boot WAR deployment example

Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…

8 years ago

Spring Boot Introduction + hello world example

Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…

8 years ago

Secure Spring REST API using OAuth2

Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…

8 years ago

AngularJS+Spring Security using Basic Authentication

This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…

8 years ago