'add location header to Spring MVC's POST response?

My Spring boot 1.4 application has this POST method to create a resource. As a requirement, it should spit a location header specifying the URL of the newly created resource (https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html). I am just wondering if there is any good way to do it than manually constructing the URL and adding it to the response.

Any helps/clues are deeply appreciated



Solution 1:[1]

This exact scenario is demonstrated in the Building REST Services with Spring Guide.

Once you have persisted your new entity, in your controller you can use the below:

URI location = ServletUriComponentsBuilder
                    .fromCurrentRequest()
                    .path("/{id}")
                    .buildAndExpand(newEntity.getId())
                    .toUri();

You can then add this to your response using ResponseEntity as below:

ResponseEntity.created(location).build()

or

ResponseEntity.status(CREATED).header(HttpHeaders.LOCATION, location).build()

The latter expects a string so you can use toUriString() on the uri builder instead of toUri().

Solution 2:[2]

Another way is to use UriComponentsBuilder. You can inject it right into a controller method:

@PostMapping(consumes = { MediaType.APPLICATION_JSON_UTF8_VALUE })
public ResponseEntity<Void> addCustomer(
          UriComponentsBuilder uriComponentsBuilder, 
          @RequestBody CustomerRequest customerRequest ){

        final long customerId = customerService.addCustomer(customerRequest)

        UriComponents uriComponents =
                uriComponentsBuilder.path("/{id}").buildAndExpand(customerId);

        return ResponseEntity.created(uriComponents.toUri()).build();
}

Take note that the following will not compute the current request path. You will need to add it manually (or I might be missing something).

ex:

UriComponents uriComponents =
       uriComponentsBuilder.path("CURRENT_REQUEST_PATH/{id}")
       .buildAndExpand(customerId);

Solution 3:[3]

This answer pointed me in the right direction, but my create entity endpoint path was slightly different from the path where the saved entity was stored.

I was able to use fromCurrentRequest() and replacePath("new path here") like so:

URI uri = ServletUriComponentsBuilder.fromCurrentRequest()
        .replacePath("/customer/{id}/fat")
        .buildAndExpand(savedCustomer.getCustomerId())
        .toUri();

return ResponseEntity.created(uri).build();

Solution 4:[4]

 @Autowired 
 private UserService service;

 @PostMapping("/users")
 public ResponseEntity<Object> createUser(@RequestBody User user)
  {
    User myUser = service.save(user);
    URI location = ServletUriComponentsBuilder
                .fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(myUser.getId())
                .toUri();

    ResponseEntity.created(location).build()
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 fireball.1
Solution 2 Valdemar
Solution 3
Solution 4 anand krish