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.
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.
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.
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.
Spring provides out of box following Http message converters which implements HttpMessageConverter interface [Credit : Spring Reference].
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.
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.
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[]).
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).
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).
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).
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).
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.
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.
If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help improve further our learning process.
In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…
Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…
Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…
Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…
Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…
This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…
View Comments
As always, neat to understand and implement, thanks.
this is really nice. thank you
Thanks, nice post