1

I have the following Rest Controller in Java/Spring. The validation of constraints are checked. However, these are completed before it reaches the body of my 'bar' method. How can I handle a violation case? Can I customize the 400 response bodies?

@RestController
@RequestMapping("foo")
public class FooController {

    @RequestMapping(value = "bar", method = RequestMethod.POST)
    public ResponseEntity<Void> bar(@RequestBody @Valid Foo foo) {
        //body part
        return ResponseEntity.status(HttpStatus.OK).build();
    }

}
codesmith
  • 1,381
  • 3
  • 20
  • 42
  • check this out - https://stackoverflow.com/questions/39001106/implementing-custom-validation-logic-for-a-spring-boot-endpoint-using-a-combinat – Rishikesh Dhokare Aug 17 '18 at 13:43

2 Answers2

3

You should use controllerAdvice, here is an exemple (in kotlin) :

@ControllerAdvice
open class ExceptionAdvice {

    @ExceptionHandler(MethodArgumentNotValidException::class)
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    open fun methodArgumentNotValidExceptionHandler(request: HttpServletRequest, e: MethodArgumentNotValidException): ErrorDto {

        val errors = HashMap<String, String>()

        for (violation in e.bindingResult.allErrors) {
            if (violation is FieldError) {
                errors.put(violation.field, violation.defaultMessage)
            }
        }

        return ErrorDto(errors)
    }

    @ExceptionHandler(BindException::class)
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    open fun bindExceptionHandler(request: HttpServletRequest, e: BindException): ErrorDto {

        val errors = HashMap<String, String>()

        for (violation in e.bindingResult.allErrors) {
            if (violation is FieldError) {
                errors.put(violation.field, violation.defaultMessage)
            }
        }

        return ErrorDto(errors)
    }
}

It allows to handle exception thrown by your controllers, including validation exceptions.

Oreste Viron
  • 3,592
  • 3
  • 22
  • 34
1

You can add BindingResult as parameter at the end into method signature.

@RequestMapping(value = "bar", method = RequestMethod.POST)
public ResponseEntity<Void> bar(@RequestBody @Valid Foo foo, BindingResult bindingResult) 
{
    if (bindingResult.hasErrors()) {
        //do something if errors occured
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
    } 

    //body part
    return ResponseEntity.status(HttpStatus.OK).build();
}
JIeIIIa
  • 48
  • 1
  • 5