This post shows Spring MVC @RequestBody, @ResponseBody annotations usage, ResponseEntity, default HttpMessageConverteres available, and writing custom message converters.
@RequestBody
- 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 aContent-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) publicResponseEntity<Void> createUser(@RequestBodyUser 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"); returnnew ResponseEntity<Void>(HttpStatus.CONFLICT); } userService.saveUser(user); HttpHeaders headers =new HttpHeaders(); headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.getId()).toUri()); returnnew 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 parameteruser 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 onContent-Type present in request HTTP header.
Take this method for example:
@RequestMapping(value ="/user/all", method = RequestMethod.GET) public@ResponseBody List<User> listAllUsers() { returnuserService.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:
packagecom.websystique.springmvc.configuration; importjava.util.List; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.ComponentScan; importorg.springframework.context.annotation.Configuration; importorg.springframework.http.converter.HttpMessageConverter; importorg.springframework.http.converter.json.MappingJackson2HttpMessageConverter; importorg.springframework.web.servlet.config.annotation.EnableWebMvc; importorg.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; importcom.fasterxml.jackson.databind.DeserializationFeature; importcom.fasterxml.jackson.databind.ObjectMapper; @Configuration @EnableWebMvc @ComponentScan(basePackages ="com.websystique.springmvc") publicclass HelloWorldConfigurationextends WebMvcConfigurerAdapter{ @Override publicvoid extendMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(mappingJackson2HttpMessageConverter()); } @Bean publicMappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { MappingJackson2HttpMessageConverter converter =new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(newObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false)); returnconverter; } }
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.
ref link : http://websystique.com/springmvc/spring-mvc-requestbody-responsebody-example/