Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Spring Boot throws different exceptions for Controller method argument validations?

Tags:

spring-boot

While validating a primitive type or their equivalent (Integer, Boolean) using constraints validation annotations (@Min, @NotNull, ...) Spring Boot throws ConstraintViolationException. But when validating a parameter using the @Valid annotation then MethodArgumentNotValidException is thrown.

I have a class annotated with @ControllerAdvice to handle the exceptions from the Controllers. The problem is that depending on the spring-boot-starter-parent version, the results are pretty much different. While using the version 2.0.5.RELEASE I just needed to include a handler for the ConstraintViolationException class. But there are some others versions that MethodArgumentNotValidException is thrown too.

It already was mentioned on a GitHub issue, but no useful answer...

I'll use the lukasniemeier-zalando's example here. For more detail click on the link above.

 @Validated  // needed to actually trigger validation
 @RestController
 class MyController {

   @RequestMapping
   Response serve(
     @RequestParam @Min(2) Integer parameter,  // throws ConstraintViolationException
     @RequestBody @Valid BodyModel body        // throws MethodArgumentNotValidException
     ) {
       return new Response();
     }

 }

I would expect that both validations throws the same exception, no matter which of them, just to be consistent.

Apearently there's no reason to this to be like it is, at least it was what I understood from this other GitHub issue.

Then I just want a answer why Spring Boot throws 2 types of exception to represent the same problem (argument validation).

Note: as mentioned before, using the version 2.0.5.RELEASE of the spring-boot-starter-parent it doesn't happens.

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>

But as reported by the last GitHub issue that I linked, the version 2.0.0.M4 has this behavior, and I also experienced it with the 2.2.0.M3 version.

like image 565
rfmac Avatar asked Jun 05 '19 21:06

rfmac


People also ask

How does Spring boot controller handle exceptions?

Exception HandlerThe @ExceptionHandler is an annotation used to handle the specific exceptions and sending the custom responses to the client. Define a class that extends the RuntimeException class. You can define the @ExceptionHandler method to handle the exceptions as shown.

What exception does @valid throw?

The exception thrown by @Validated when a constraint we specify is violated is of type ConstraintViolationsException , and has no response handler. To intercept the exception and customize our response, we need to build an exception handler using the @ControllerAdvice and @ExceptionHandler annotations.


Video Answer


1 Answers

They are handled by different validation mechanisms. The @Validated on the class is handled by the MethodValidationInterceptor which is a generic purpose validation mechanism for classes. Due to this it throws a ConstraintViolationException. The @Validated is used here simply because the @Valid annotation isn't allowed on types. Hence the only way to enable/trigger the MethodValidationInterceptor is by using the @Validation annotation.

The @Valid on the method argument in a controller is handled by the ModelAttributeMethodProcessor internally and leads to a web specific binding exception, the MethodArgumentNotValidException. The ModelAttributeMethodProcessor is called (indirectly) from the RequestMappingHandlerAdapter when preparing the method invocation. Instead of @Valid you could also use the @Validated annotation on the method argument. Spring MVC supports both (it actually supported @Validated before @Valid even existed!).

The solution/workaround is to create your own exception-handler which handles the ConstraintViolationException the same as a MethodArgumentNotValidException. Which is also suggested in the GitHub issue you link to.

like image 73
M. Deinum Avatar answered Nov 09 '22 19:11

M. Deinum