Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA EmptyResultDataAccessException handling

I'm writing a simple library API for a college project. I have a database with books, each with it's own ID. I'm using Spring Boot to make the service. I have a BookRepository which extends JpaRepository<Book, Long>, and a service implementation.

@Service
public class BookServiceImpl implements BookService{

   @Autowired
   private BookRepository bookRepository;

   @Async
   @Override
   public void delete (Long id){
       bookRepository.delete(id);
    }
}

Later on, a REST controller handles the request:

@RestController
public class BookServiceController{

    @Autowired
    private BookService bookService;

    @RequestMapping(value="books/{id}", method = RequestMethod.DELETE)
    public ResponseEntity<Book> deleteBook (@PathVariable("id") Long id){
        bookService.delete(id);
        return new ResponseEntity<Book>(HttpStatus.OK);
    }
}

Now, if I were to delete a Book which is not in the database, for example with an ID of 123, I'd get a EmptyResultDataAccessException thrown.

My question is, how and where do I handle the exception, and how do I avoid casting a NullPointerException that way?

Thanks in advance.

like image 268
Flopn Avatar asked Aug 30 '16 17:08

Flopn


1 Answers

In the case of a DELETE operation, you aren't really returning an entity anymore; you're simply confirming that the resource is gone. As DELETE is idempotent (you could delete the record multiple times), you can either return the same status code regardless of whether the record exists or return a 404 if the record isn't found. You can also simplify the handler method:

@DeleteMapping("/books/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT) // because you deleted it
public void deleteBook(@PathVariable Long id) {
    try {
        bookService.delete(id); // or just use the repository directly
    } catch (EmptyResultDataAccessException ex) {
        // either do nothing to return a 204, or
        throw new NotFoundException();
    }
}

where you have an exception that indicates the status:

@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException {}

It's plausible that EmptyResultDataAccessException should already be annotated with a status of NOT_FOUND; this is a potential enhancement request.

like image 184
chrylis -cautiouslyoptimistic- Avatar answered Nov 16 '22 01:11

chrylis -cautiouslyoptimistic-