Category Archives: REST
HttpMessageConverters
Spring MVC uses HttpMessageConverter to convert the Http request to an object representation and back.Spring Framework then uses one of the Jackson message converters to marshall and unmarshall Java Objects to and from JSON over HTTP.Spring will use the “Accept” header to determine the media type that it needs to respond with and uses the “Content-Type” header to determine the media type of the request body.
Default Message Converters in Spring MVC
StringHttpMessageConverter: it converts Strings from the HTTP request and response.
FormHttpMessageConverter: it converts form data to/from a MultiValueMap
ByteArrayHttpMessageConverter: it converts byte arrays from the HTTP request and response.
MappingJackson2HttpMessageConverter: it converts JSON from the HTTP request and response.
Jaxb2RootElementHttpMessageConverter: it converts Java objects to/from XML.
SourceHttpMessageConverter: it converts javax.xml.transform.Source from the HTTP request and response.
AtomFeedHttpMessageConverter: it converts Atom feeds.
RssChannelHttpMessageConverter: it converts RSS feeds.
Customizing HttpMessageConverters with Spring MVC
Spring REST Annotations
Annotation | Usage |
---|---|
@RequestMapping |
@RequestMapping(value = "/{name}", method = RequestMethod.GET, consumes="application/json" produces ="application/json", headers={"name=pankaj", "id=1"}) |
path (or) (or) name (or) and value: which URL the method is mapped to method: compatible HTTP methods params: filters requests based on presence, absence, or value of HTTP parameters headers: filters requests based on presence, absence, or value of HTTP headers consumes: which media types the method can consume in the HTTP request body produces: which media types the method can produce in the HTTP response body |
|
@RequestBody |
@RequestMapping(method = RequestMethod.POST) @ResponseBody public HttpStatus something(@RequestBody MyModel myModel) { return HttpStatus.OK; } |
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. | |
@ResponseBody |
@RequestMapping(value = "/user/all", method = RequestMethod.GET) public @ResponseBody List<User> listAllUsers() { return userService.findAllUsers(); } |
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 | |
@RequestParam |
http://localhost:8080/springmvc/hello/101?param1=10¶m2=20 public String getDetails( @RequestParam(value="param1", required=true) String param1, @RequestParam(value="param2", required=false) String param2){ ... } |
@RequestParam is to obtain an parameter from the URI as well.@RequestParam annotation used for accessing the query parameter values from the request defaultValue – This is the default value as a fallback mechanism if request is not having the value or it is empty. name – Name of the parameter to bind required – Whether the parameter is mandatory or not. If it is true, failing to send that parameter will fail. value – This is an alias for the name attribute |
|
@PathVariable |
'http://localhost:8080/springmvc/hello/101?param1=10¶m2=20 @RequestMapping("/hello/{id}") public String getDetails(@PathVariable(value="id") String id, @RequestParam(value="param1", required=true) String param1, @RequestParam(value="param2", required=false) String param2){ ....... } @GetMapping("/user/{firstName}/{lastName}") @ResponseBody public String handler(@MatrixVariable("firstName") String firstName, @MatrixVariable("lastName") String lastName ) { return "<br>Matxrix variable <br> " + "firstName =" + firstName +"<br>" + "lastName =" + lastName; } |
@PathVariable is to obtain some placeholder from the URI @MatrixVariable – a name-value pair within a path segment is referred as matrix variable. Matrix variables can appear in any path segment, each variable separated with a semicolon (;) and multiple values are separated by comma (,) i.e. http://www.example.com/employee/Mike;salary=45000;dept=HR http://www.example.com/car/Audi;color=RED,BLACK,WHITE |
|
@RequestHeader |
@Controller public class HelloController { @RequestMapping(value = "/hello.htm") public String hello( @RequestHeader(value="Accept") String accept, @RequestHeader(value="Accept-Language") String acceptLanguage, @RequestHeader(value="User-Agent", defaultValue="foo") String userAgent, HttpServletResponse response) { System.out.println("accept: " + accept); System.out.println("acceptLanguage: " + acceptLanguage); System.out.println("userAgent: " + userAgent); return null; } } |
Reading http requestheader is written in HelloController The advantage of using Spring @RequestHeader is that it will automatically throw an exception like HTTP Status 400 – Missing request header ‘X’ for method parameter of type, if the header is NOT sent in the input request (by setting required=true) @RequestHeader for facilitating use to get the header details easily in our controller class |
Get vs Put vs Post vs Delete
GET
- GET is idempotent and can be requested any number of times
- GET requests can be cached, can be distributed & shared
- GET request is less secured compared to POST.
POST
- Used to Create a resource
- Post is not idempotent.x++ is not idempotent
- POST is NOT idempotent. So if you retry the request N times, you will end up having N resources with N different URIs created on server.
PUT
- Used to Create or Modify a resource
- PUT is idempotent, so if you PUT an object twice, it has no effect.
- x=5 is idempotent.You can PUT a resource whether it previously exists, or not (eg, to Create, or to Update)!
When to use Put and Post
You can use both PUT or POST for creating the resource until the client decides the resource location in the Server.But if the server decides the resource location using
POST /questions/HTTP/1.1 Host: www.example.com/
Note that the following is an error:
POST /questions/HTTP/1.1 Host: www.example.com/
If the URL is not yet created, you should not be using POST to create it while specifying the name. This should result in a ‘resource not found’ error because
You could though do something like this to create a resources using POST:
POST /questions HTTP/1.1 Host: www.example.com/
Note that in this case the resource name is not specified, the new objects URL path would be returned to you.
PUT is Used to create a resource, or overwrite it. While you specify the resources new URL.
PUT /questions/HTTP/1.1 Host: www.example.com/
To overwrite an existing resource:
PUT /questions/HTTP/1.1 Host: www.example.com/
PATCH
Patch request says that we would only send the data that we need to modify without modifying or effecting other parts of the data. Ex: if we need to update only the first name, we pass only the first name.PATCH – HTTP.PATCH can be used when the client is sending one or more changes to be applied by the server. The PATCH method requests that a set of changes described in the request entity be applied to the resource identified by the Request-URI. The set of changes is represented in a format called a patch document.
In PUT request, the enclosed entity would be considered as the modified version of a resource which residing on server and it would be replaced by this modified entity.
In PATCH request, enclosed entity contains the set of instructions that how the entity which residing on server, would be modified to produce a newer version.
DELETE
DELETE is pretty easy to understand. It is used to delete a resource identified by a URI.On successful deletion, return HTTP status 200 (OK) along with a response body, perhaps the representation of the deleted item (often demands too much bandwidth), or a wrapped response (see Return Values below). Either that or return HTTP status 204 (NO CONTENT) with no response body. In other words, a 204 status with no body, or the JSEND-style response and HTTP status 200 are the recommended responses.
Caching in REST API
- Caching is the ability to store copies of frequently accessed data in several places along the request-response path. When a consumer requests a resource representation, the request goes through a cache or a series of caches (local cache, proxy cache or reverse proxy) toward the service hosting the resource.
- If any of the caches along the request path has a fresh copy of the requested representation, it uses that copy to satisfy the request. If none of the caches can satisfy the request, the request travels all the way to the service (or origin server as it is formally known).
- Using HTTP headers, an origin server indicates whether a response can be cached and if so, by whom, and for how long. Caches along the response path can take a copy of a response, but only if the caching metadata allows them to do so.
- Few are the advantages of Caching
- Reduce bandwidth
- Reduce latency
- Reduce load on servers
- Hide network failures
- GET requests are cachable by default – until special condition arises. Usually, browsers treat all GET requests cacheable.
- POST requests are not cacheable by default but can be made cacheable if either an Expires header or a Cache-Control header with a directive, to explicitly allows caching, is added to the response. Responses to PUT and DELETE requests are not cacheable at all.
There are two main HTTP response headers that we can use to control caching behavior:
Expires : The Expires HTTP header specifies an absolute expiry time for a cached representation. Beyond that time, a cached representation is considered stale and must be re-validated with the origin server. To indicate that a representation never expires, a service can include a time up to one year in the future.
Expires: Wed, 6 March 2019 15:09:49 IST
Cache-Control:
The header value comprises one or more comma-separated directives. These directives determine whether a response is cacheable, and if so, by whom, and for how long e.g. max-age or s-maxage directives.
Cache-Control: max-age=3600 ETag: "abcd1234567n34jv" (or) Last-Modified: Fri, 10 May 2016 09:17:49 IST
Cacheable responses (whether to a GET or to a POST request) should also include a validator — either an ETag or a Last-Modified header.
ETag
An ETag value is an opaque string token that a server associates with a resource to uniquely identify the state of the resource over its lifetime. When the resource changes, the ETag changes accordingly.
Last-Modified
Whereas a response’s Date header indicates when the response was generated, the Last-Modified header indicates when the associated resource last changed. The Last-Modified value cannot be later than the Date value.
How @RequestBody and @ResponseBody Works
@RequestBody, spring will try to convert the content of the incoming request body to your parameter object on the fly.@ResponseBody, spring will try to convert its return value and write it to the http response automatically
@Controller @RequestMapping(value = "/bookcase") public class BookCaseController { private BookCase bookCase; @RequestMapping(method = RequestMethod.GET) @ResponseBody public BookCase getBookCase() { return this.bookCase; } @RequestMapping(method = RequestMethod.PUT) @ResponseStatus(HttpStatus.NO_CONTENT) public void setBookCase(@RequestBody BookCase bookCase) { this.bookCase = bookCase; } }
Depending on your configuration, spring has a list of HttpMessageConverters registered in the background. A HttpMessageConverters responsibility is to convert the request body to a specific class and back to the response body again, depending on a predefined mime type. Every time an issued request is hitting a @RequestBody or @ResponseBody annotation spring loops through all registered HttpMessageConverters seeking for the first that fits the given mime type and class and then uses it for the actual conversion.
Refer here