0

I want to return an error when the body of a REST request is empty (e.g contains only {}) but there is no way to detect if the request body contains an empty JSON or not.

I tried to change @RequestBody(required = true) but it's not working.

@PatchMapping("{id}")
public ResponseEntity<Book> updateAdvisor(@PathVariable("id") Integer id, 
   @Valid @RequestBody  BookDto newBook) {
    Book addedBook = bookService.updateBook(newBook);
    return new ResponseEntity<>(addedBook,HttpStatus.OK);
  }

If the body sent contains an empty JSON I should return an exception. If the body is not empty and at least one element is provided I won't return an error.

Aleksei Maide
  • 1,845
  • 1
  • 21
  • 23
KareemDev
  • 15
  • 1
  • 5
  • 2
    add validations on `BookDto` – Ryuzaki L May 02 '19 at 16:19
  • Obviously {} is a valid BookDto, so you have to implement a custom validator OR set composite not null constraint on the database columns... which should exist either way... for data integrity (and propagate the constraint violation exception) – Aleksei Maide May 02 '19 at 19:02
  • @AlekseiMaide what do you mean by composite notnull constraints? (is it just annotate all fields with NotNull annotation ?) if this is the case it's not a solution because user can input only few params to edit the book he is not obliged to input all params. – KareemDev May 03 '19 at 09:16
  • @KareemDev composite constraint on multiple database fields... eg. constraint book.name is not null OR book.description is not null ... and so on. (Create a constraint in the database that would check that insertable row contains at least one non null value) I dont know which database you are using, so i can't really help you with this. – Aleksei Maide May 03 '19 at 14:01

2 Answers2

1

Try @RequestBody(required = false)

This should cause the newBook parameter to be null when there is no request body.

The above still stands and is the answer to the original question.

To solve the newly edited question:

  1. Change the @RequestBody BookDto newBook parameter to a String parameter (for example, @RequestBody String newBookJson).
  2. Perform pre-conversion validation (such as, "is the body an empty JSON string value").
  3. If the body contains valid JSON, parse the JSON into to an object (example below).
@Autowired
private ObjectMapper objectMapper; // A Jackson ObjectMapper.

@PatchMapping("{id}")
public ResponseEntity<Book> updateAdvisor(
  @PathVariable("id") Integer id, 
  @Valid @RequestBody String newBookJson)
{
  if (isGoodStuff(newBookJson)) // You must write this method.
  {
    final BookDto newBook = ObjectMapper.readValue(newBookJson, BookDto.class);

    ... do stuff.
  }
  else // newBookJson is not good
  {
    .. do error handling stuff.
  }
}
DwB
  • 37,124
  • 11
  • 56
  • 82
0

Let's suppose you have a Class BookDto :

 public class BookDto {
       private String bookName;
       private String authorName;
  }

We can use @ScriptAssert Annotation on Class BookDto:

@ScriptAssert(lang = "javascript", script = "_this.bookName != null || _this.authorName != null")
public class BookDto {
       private String bookName;
       private String authorName;
  }

then in the resource/controller Class:

@PatchMapping("{id}")
public ResponseEntity<Book> updateAdvisor(@PathVariable("id") Integer id, 
   @Valid @RequestBody  BookDto newBook) {
    Book addedBook = bookService.updateBook(newBook);
    return new ResponseEntity<>(addedBook,HttpStatus.OK);
  }

Now @Valid annotation will validate whatever we have asserted in the @ScriptAssert annotation's script attribute. i.e it now checks if the body of a REST request is empty (e.g contains only {}).

Himank Batra
  • 301
  • 5
  • 3