Search This Blog

Thursday, 11 July 2013

Combine CREATE and UPDATE operations in REST

I was searching the net on good practices for developing RestFull services when I came across this interesting discussion on stack overflow:
The question was "Should we use PUT or POST for Create Resource ?"
Among the answers - there was the interesting response that PUT can be used for both update and create.
That means a single API which takes a resource, checks if it exists then creates it else updates it. I decided to try the same:
@RequestMapping(method = RequestMethod.PUT)
   public ResponseEntity<Void> saveUser(@RequestBody final User user) {

      boolean recordExists = false;
      final Integer userId = user.getId();
      if (-1 == userId) {// user id defaults to -1 for uncreated records
         this.addUserToSystem(user);
         logger.info("saveUser: new user added with id " + user.getId());
      } else {
         recordExists = true;
         this.updateUserInSystem(userId, user);
         logger.info("saveUser: user with id " + userId + " has been updated");
      }

      ResponseEntity<Void> responseEntity = null;
      final HttpHeaders headers = new HttpHeaders();
      HttpStatus responseStatus = null;
      if (recordExists) {
         responseStatus = HttpStatus.NO_CONTENT;
      } else {
         final URI location = ServletUriComponentsBuilder
               .fromCurrentServletMapping().path("/user/{id}").build()
               .expand(user.getId()).toUri();
         headers.setLocation(location);
         responseStatus = HttpStatus.CREATED;
      }

      responseEntity = new ResponseEntity<Void>(headers, responseStatus);
      return responseEntity;
   }
  1. My REST operation has the URL http://localhost:8080/SampleRest/api/user/ and method is PUT
  2. If the passed resource exists it will create one, returning a Status of 201 and the URL in the location header.
  3. If it already exists, Server will update the resource returning a status of 204.
I tried to test the same with the RestTemplate provided by Spring. This style will not work with the RestTemplate as its put method returns void.
So I decided to test it using the RESTClient plugin in Firefox.
CREATE:

UPDATE:

1 comment: