I have two paths:
/students/students/{id}/addresses
...with the following behavior:
POST to /students - 201 Created (if successfully created the Student) POST to /students/{id}/addresses - 201 Created (if successfully created the Address under the requested user) Now, imagine a situation where the client POST to /students/12/addresses, but there's no Student with id = 12.
How should I handle this scenario?
Should I insert without any check and wait for DAO to throw the Exceptions or, before inserting, I should check for Student's existance?
1st option:
StudentController.java
@Autowired private AddressService addressService; @PostMapping("/students/{id}/addresses") public ResponseEntity<?> handleRequestOfCreateAddressToStudent(@PathVariable("id") Long studentId, @RequestBody Address address) { address.setStudent(new Student(studentId)); Address createdAddress = addressService.saveAddress(address); URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").build(createdAddress.getId()); return ResponseEntity.created(location).build(); } AddressService.java
@Autowired private AddressRepository addressRepository; public Address saveAddress(Address address) { // omitted for brevity... return addressRepository.save(address); } This way, since I'm using Spring framework, the line return addressRepository.save(address); would throw a DataIntegrityViolationException, because the constraint is violated (there's no Student with such ID to bind with that Address). And, since I need to send the response to the client, I would have to translate the exception that is throwed.
2nd option:
StudentController.java
@Autowired private StudentService studentService; @Autowired private AddressService addressService; @PostMapping("/students/{id}/addresses") public ResponseEntity<?> handleRequestOfCreateAddressToStudent(@PathVariable("id") Long studentId, @RequestBody Address address) throws StudentNotFoundException { Student student = studentService.findById(studentId); if(student == null) throw new StudentNotFoundException("message"); address.setStudent(new Student(studentId)); Address createdAddress = addressService.saveAddress(address); URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").build(createdAddress.getId()); return ResponseEntity.created(location).build(); } This way, I don't need to translate the Exception, as I already know that the Student does not exist so that I can throw a custom exception.
My thoughts in both approaches:
- Without checking, I do reduce the code and the number of times I trigger my database;
- Checking, I do know exactly why I'm unable to add the Address (the Student does not exist) and can throw a custom exception without having to translate it;
Which one is the best approach to this scenario?
Should I wait for the DAO to throw the Exception, or should I prevent it from throwing by checking if the Student exists?